4

I have developed a small app that stores locally in iOS through archiving an array of custom objects containing:

@property (nonatomic, copy) NSString    *name;
@property (nonatomic, copy) NSString    *dateCreated;
@property (nonatomic, copy) NSString    *desc;
@property (nonatomic, copy) NSString    *url;

I want to sync said archive using iCloud and I believe the recommended mechanism is through a UIDocument subclass. All UIDocument examples I found utlilized a single instance with 1 single NSString, so I am a little confused how to go about syncing a whole array of custom objects but utilizing UIDocument (like I do today locally through NSCoding).

Should I create an array of UIDocument objects containing the properties listed above, should I create an instance of UIDocument containing 1 instance of the data object described above and then create an array containing all the instances, or should 1 single UIDocument contain the complete array of custom objects ?

I have done some research but I am still confused. In the end I would need to sync just 1 file containing an array of said custom objects.

Thanks in advance for your help

What I have today is a custom class as described above with 4 strings called Snippet and in my Root view Controller I have an NSMutableArray called list where I add each new instance of that Snippet Class.

self.list = [[NSMutableArray alloc] init];
Snippet *newEntry = [[Snippet alloc] init];
[self.list addObject:newEntry];

Should I create an UI Document subclass that owns the array of custom objects ?

Will
  • 303
  • 3
  • 9

1 Answers1

2

The example in the docs does indeed show a UIDocument subclass that just has one string, but it returns a NSData from -contentsForType:error:. You can store as many objects as you like in an NSData using an NSKeyedArchiver. Read Serializing Objects to learn how to encode objects using NSKeyedArchiver (and keep reading to learn how to get them back!).

Using your properties as an example...

@interface MyDocument : UIDocument
{
}
@property (nonatomic, copy) NSString    *name;
@property (nonatomic, copy) NSString    *dateCreated;
@property (nonatomic, copy) NSString    *desc;
@property (nonatomic, copy) NSString    *url;
@end

@implementation MyDocument

//...

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:name forKey:@"name"];
    [archiver encodeObject:dateCreated forKey:@"created"];
    [archiver encodeObject:desc forKey:@"desc"];
    [archiver encodeObject:url forKey:@"url"];
    [archiver finishEncoding];
    // release archiver if you're not using ARC
    return data;
}
@end;

WARNING: I haven't compiled the code above, so no guarantees. This should serve as an example to illustrate using an archiver to store multiple objects in a single data object which you can return as your document's content.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • Thanks for your answer. So if I understood you correctly I could use + (NSData *)archivedDataWithRootObject:(id)rootObject with the array and then - (id)contentsForType:(NSString *)typeName error:(NSError **)outError archiving the whole array in 1 single instance of UIDocument – Will Dec 12 '11 at 21:22
  • How would you declare the UIDocument in that case ? – Will Dec 12 '11 at 21:36
  • I don't see what array you're talking about. I'll add a snippet above to try to help. – Caleb Dec 12 '11 at 23:39
  • I added to clarify what I meant about the array – Will Dec 13 '11 at 00:29
  • If you want to add an array to the mix, you can use `-encodeObject:forKey:` just as you do for strings. Just make sure that all the objects in the array implement NSCoding. You really ought to read the *Archives and Serializations Programming Guide* -- this is all explained there. – Caleb Dec 13 '11 at 01:45