Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing an array of custom objects with Today Extension (widget) with NSUserDefaults

this is my first stack post so please be constructive when reviewing my posting technique!

Basically, my problem is that I have an array of custom objects that I need to share with a today extension. The objects represent tasks in a to-do list, and their properties are used to store info about each task (name, location, dueDate, thumbnail, etc). The objects are stored in an array which is used to populate my to-do list. All I want to do is pass this array to my widget so that I can populate a second tableview which will act as a condensed version of the first (for the widget view).

I should point out that my widget is properly set up, as in I have properly linked it and the containing app together in 'groups'. I have also successfully used NSUserDefaults to pass an array of NSStrings to the widget, however, when I try to pass the array of objects to the widget, it crashes and my log reads:

*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (Xitem)'

I understand that this crash is related to archiving the object (Xitem), which seems to be a necessary step towards saving custom objects in NSUserDefaults. However, I have tested saving/loading the array within the same class of the containing app, and that works fine! (code below)

        NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:self.Xitems];
        NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.AaronTest"];
        [defaults setObject:encodedObject forKey:@"myArray"];
        [defaults synchronize];


        NSUserDefaults *defaults2 = [[NSUserDefaults alloc] initWithSuiteName:@"group.AaronTest"];
        NSData *encodedObject2 = [defaults2 objectForKey:@"myArray"];
        NSArray *array2 = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject2];

        for (Xitem *t in array2){

            NSLog(@"*****%@*****", t.itemName);
        }

Okay so as explained, the above code works as expected. However, when i insert the second 'unarchiver' half of this code into my today widget, i get the aforementioned error. Below is my code to show how I encode/decode the object (it may be worth noting that this object was created for the simplicity of my debugging and only contains a NSString property):

Xitem.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>


@interface Xitem : NSObject <NSCoding> 
{ 
NSString *itemName;
}

-(void)encodeWithCoder:(NSCoder*)encoder;
-(id)initWithCoder:(NSCoder*)decoder;

@property NSString *itemName;

@end

Xitem.m

#import "Xitem.h"

@implementation Xitem

@synthesize itemName;

-(void)encodeWithCoder:(NSCoder*)encoder
{

[encoder encodeObject:self.itemName forKey:@"iName"];

}

-(id)initWithCoder:(NSCoder*)decoder
{

self = [super init];

self.itemName = [decoder decodeObjectForKey:@"iName"];

return self;
}

@end

I could also post my widget and containing app code, but it doesn't differ from the first set of code i posted (apart from the renamed variables such as 'defaults2'). I should point out that I really have exhausted resources while trying to solve this problem, but the fact that using NSKeyedArchiver solely in the containing app works, has left me stumped.

I realise that this post is very similar to my own problem, but the author decides to opt for a workaround, whereas I would actually like to know why this doesn't work. I'm a new developer and I'm doing my best to pickup on the best working practices so any advice would be greatly appreciated.

I think it's also possible to replace my object (class) with an NSDictionary? However I would like to avoid this if possible because it would cause many conflicts in the main app, but obviously if that is the correct method I will tackle that problem. On a side note, if a dictionary would be better than an object for my requirements (to-do list with properties of UIImage, CLLocation, etc) for any other reasons (memory or accessibility for example) please do elaborate and help me to understand why!

Many thanks for anyones time :)

like image 594
Swankzilla Avatar asked Oct 20 '22 22:10

Swankzilla


1 Answers

Okay so I just fixed this. Incase anyone has the same problem, go to: 'Targets' > 'Widget' > 'Build Phases' > 'Compile Sources' > add custom class there (Xitem.m)

like image 80
Swankzilla Avatar answered Oct 22 '22 14:10

Swankzilla