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 :)
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With