title: iCloud: Is it possible to use KVS for custom objects?
body: <p>I am trying to wrap my head around iCloud storage. I have read through the <a href="https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html" rel="nofollow">iCloud Design Guide</a> and some questions here on SO. Here is my scenario:</p>
  
  <p>I have a class that only has an <code>NSMutableArray</code>...that collection holds my custom objects which all adhere to <code>NSCoding</code> and saving locally works perfectly. That class is MasterList and has the property masterList, brilliant - I know :-p. When I looked on how to start implementing iCloud I thought KVS would be great, since my data footprint is extremely small. When I attempted this, I kept getting:</p>
  
  <pre><code>[NSUbiquitousKeyValueStore setObject:forKey:]: Attempt to insert non-property value &lt;my custom objects&gt;...
  </code></pre>
  
  <p>After seeing why that was, it seems you can only store scalar and P-List types with KVS. So I moved to using <code>UIDocument</code> and am struggling with it. </p>
  
  <p><strong>Bottom line -</strong> </p>
  
  <p>For custom objects, do you have to use <code>UIDocument</code>, or is it possible to use KVS?</p>
  
  <p>and </p>
  
  <p>If I must use <code>UIDocument</code>, did any of you read a tutorial that was simple in nature (maybe stored a few props and loaded them back, maybe in a sample project?) that made it click for you?</p>
  
  <p>Below is my code for using KVS if that helps at all. Not production or anything, just trying to get it to work:</p>
  
  <pre><code>//Load it
  +(MasterList *)decodeMasterList:(MasterList *)objectToDecode
  {
  
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  
      NSURL *dataFile = [self pathForDocumentsFile:kFilePathAllLists];
      NSString *filePath = [dataFile path];
  
      objectToDecode = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
  
      //First time runnign the app :-)
      if (!objectToDecode) objectToDecode = [[MasterList alloc] init];
  
      if ([defaults boolForKey:kIsUsingiCloud])
      {
          objectToDecode.masterList = [[[NSUbiquitousKeyValueStore defaultStore] arrayForKey:kiCloudPath] mutableCopy];
  
          //If we just started and nothing is there
          if (!objectToDecode.masterList)
          {
              objectToDecode.masterList  = [[NSMutableArray alloc] initWithObjects:[CustomList new], nil];
          }
      }
  
      return objectToDecode;
  }
  
  //Save it
  +(BOOL)encodeMasterList:(MasterList *)objectToEncode
  {
      @try
      {
          NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
          if ([defaults boolForKey:kIsUsingiCloud])
          {
              [[NSUbiquitousKeyValueStore defaultStore] setArray:objectToEncode.masterList forKey:kiCloudPath];
              [[NSUbiquitousKeyValueStore defaultStore] synchronize];
          }
  
          NSURL *dataFile = [FileSystemHelper pathForDocumentsFile:kFilePathAllLists];
          NSString *filePath = [dataFile path];
          [NSKeyedArchiver archiveRootObject:objectToEncode toFile:filePath];
  
      }
      @catch (NSException *exception)
      {
          return NO;
      }
  
      return YES;
  }
  </code></pre>