CKAsset behaves differently on iOS vs Mac OS X

I am writing an activity logging system for one of my tables in CloudKit to help tracking down bugs.


The app runs on both iOS devices and Macs. Either one can add and edit CKRecords.


I have added a table in the cloud called CKRecordLogType and am storing a number of fields of data about the device making a change to a record. I am also storing the CKRecord being acted upon within the CKRecordLogType as a CKAsset.


This works great on the Mac, but on iOS, the CKAsset doesn't contain the original CKRecord I stored in it. The code I use for uploading the log records is shared between the Mac project and the iOS project, so the code is exactly the same.


I then add functionality in the Mac app to view the log reccrds. Each log record is read into a wrapper class which decodes and reinstantiates the original CKRecord. This work great if the log record was uploaded from a Mac, but is unusable if the log record was uploaded from an iOS device.


Here is the code which uploads a log record:

-(void) logActivityForCKRecord:(CKRecord*) ckRecord forCloudLoadType: (enum cloudLoadType) cloudLoadType{
   
    NSLog(@"logActivityForCKRecord: %@", ckRecord);
   
    NSString* recordKey = [NSUUID UUID].UUIDString;;
    CKRecord* logCKRecord;
   
    /
    CKRecordID *wellKnownID = [[CKRecordID alloc] initWithRecordName:recordKey];
   
    logCKRecord = [[CKRecord alloc] initWithRecordType:@"CKRecordLogType" recordID:wellKnownID];
    logCKRecord[@"recordKey"] = recordKey;
   
    logCKRecord[@"sourceRecordKey"] = ckRecord[@"recordKey"];
   
    logCKRecord[@"createdBy"] = [PublicEnums userID];
   
    logCKRecord[@"modifiedDate"] = [NSDate date];
   
    logCKRecord[@"sourceRecordType"] = ckRecord[@"recordType"];
   
    logCKRecord[@"cloudLoadType"] = [NSNumber numberWithInteger:cloudLoadType];
   
    NSURL* imagesFolderURL = [[CoreDataManager sharedManager]imagesFolderURL];
   
    NSURL* ckRecordURL = [imagesFolderURL URLByAppendingPathComponent:recordKey];
   
    /
    NSMutableData* encodedCKRecord = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:encodedCKRecord];
    [archiver encodeObject:ckRecord forKey:@"attrs"];
    [archiver finishEncoding];
   
    [encodedCKRecord writeToURL:ckRecordURL atomically:YES];
   
    CKAsset* ckRecordAsset = [[CKAsset alloc] initWithFileURL:ckRecordURL];
   
    logCKRecord[@"ckRecordCopy"] = ckRecordAsset;
   
    NSString* ckRecordKey = ckRecord[@"recordKey"];
   
    CKRecordID *ckRecordKeyID = [[CKRecordID alloc] initWithRecordName:ckRecordKey];
   
    CKReference *ckRecordReference = [[CKReference alloc] initWithRecordID:ckRecordKeyID action:CKReferenceActionNone];
    logCKRecord[@"sourceCKRecord"] = ckRecordReference;
   
   
    /
   
    CKAsset *encodedCKRecordAsset = logCKRecord[@"ckRecordCopy"];
   
    NSURL* cloudImageURL = encodedCKRecordAsset.fileURL;
   
    NSData* encodedCKRecordCopyData = [NSData dataWithContentsOfURL:cloudImageURL];
   
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:encodedCKRecordCopyData];
   
    CKRecord* sourceCKRecord = [unarchiver decodeObjectForKey:@"attrs"];
   
    NSLog(@"sourceCKRecord: %@", sourceCKRecord);
   
    /
   
    [self saveCKRecordToCloud:logCKRecord forManagedObject:nil];
}

toward the end of the method I unarchive the CKRecord just to check that it is ok, which it is on both Mac and iOS


Here is the wrapper init method:

-(CKRecordLogWrapper*) initWithCKLogRecord:(CKRecord* )ckLogRecord{
    self = [super init];

    self.ckLogRecord = ckLogRecord;

    CKAsset *encodedCKRecordAsset = ckLogRecord[@"ckRecordCopy"];

    NSURL* cloudImageURL = encodedCKRecordAsset.fileURL;

    NSData* encodedCKRecordCopyData = [NSData dataWithContentsOfURL:cloudImageURL];

    NSLog(@"encodedCKRecordCopyData.length: %ld", encodedCKRecordCopyData.length);

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:encodedCKRecordCopyData];

    self.sourceCKRecord = [unarchiver decodeObjectForKey:@"attrs"];

    NSLog(@"self.sourceCKRecord: %@", self.sourceCKRecord);

    return self;
}


the resulting logged output for a Mac-saved log record:

2018-01-24 15:58:04.196886-0700 Bubinga[7561:1636961] encodedCKRecordCopyData.length: 2793
2018-01-24 15:58:04.197536-0700 Bubinga[7561:1636961] self.sourceCKRecord: <CKRecord: 0x100db4540; recordID=6DB02EE4-67E8-42CD-89AA-C30DCE18B37C:(_defaultZone:__defaultOwner__), recordChangeTag=jctmotlj, values={
    backordered = 0;
    completeStatus = 0;
    createdBy = "Rick\U2019s 2017 MacBook Pro";
    displayOrder = 2;
    extension = 0;
    finalValueFee = 0;
    itemRecordType = "<CKReference: 0x61800063b4c0; 8B169D14-F6EE-4B84-A1D1-4E39AC6BF549:(_defaultZone:__defaultOwner__)>";
    length = 0;
    modificationRecordType = "<CKReference: 0x61800063ba00; 4D59DB38-F783-47E6-A7EE-4435CDCFB72E:(_defaultZone:__defaultOwner__)>";
    modifiedBy = "Rick\U2019s 2017 MacBook Pro";
    price = 8;
    quantityChange = 1;
    quantityString = 1;
    recordKey = "6DB02EE4-67E8-42CD-89AA-C30DCE18B37C";
    shipping = 0;
    taxAmount = 0;
    thickness = 0;
    width = 0;
}, recordType=OnhandChangeRecordType>

the resulting logged output for an iOS-saved record:

2018-01-24 15:56:37.809312-0700 Bubinga[7561:1636961] encodedCKRecordCopyData.length: 3547
2018-01-24 15:56:37.809541-0700 Bubinga[7561:1636961] self.sourceCKRecord: <CKRecord: 0x100df27d0; recordID=6DB02EE4-67E8-42CD-89AA-C30DCE18B37C:(_defaultZone:__defaultOwner__), recordChangeTag=jctmotlj, recordType=OnhandChangeRecordType>

putting a break after reading a bad reord:

(lldb) po self.sourceCKRecord
<CKRecord: 0x100d634d0; recordID=6DB02EE4-67E8-42CD-89AA-C30DCE18B37C:(_defaultZone:__defaultOwner__), recordChangeTag=jctmotlj, recordType=OnhandChangeRecordType>
{
  creatorUserRecordID -> <CKRecordID: 0x600000631d80; recordName=__defaultOwner__, zoneID=_defaultZone:__defaultOwner__>
  lastModifiedUserRecordID -> <CKRecordID: 0x600000632400; recordName=__defaultOwner__, zoneID=_defaultZone:__defaultOwner__>
  creationDate -> 2018-01-24 22:15:34 +0000
  modificationDate -> 2018-01-24 22:15:34 +0000
  modifiedByDevice -> E38764E7CFD4BBDA02B61196028408F3569D3D258A27C5C445560CD92484F629
}

after reading a good record:(from a Mac)

(lldb) po self.sourceCKRecord
<CKRecord: 0x100b92000; recordID=6DB02EE4-67E8-42CD-89AA-C30DCE18B37C:(_defaultZone:__defaultOwner__), values={
    backordered = 0;
    completeStatus = 0;
    createdBy = "Rick\U2019s 2017 MacBook Pro";
    displayOrder = 2;
    extension = 0;
    finalValueFee = 0;
    itemRecordType = "<CKReference: 0x6080004257c0; 8B169D14-F6EE-4B84-A1D1-4E39AC6BF549:(_defaultZone:__defaultOwner__)>";
    length = 0;
    modificationRecordType = "<CKReference: 0x608000025bc0; 4D59DB38-F783-47E6-A7EE-4435CDCFB72E:(_defaultZone:__defaultOwner__)>";
    modifiedBy = "Rick\U2019s 2017 MacBook Pro";
    price = 8;
    quantityChange = 1;
    quantityString = 1;
    recordKey = "6DB02EE4-67E8-42CD-89AA-C30DCE18B37C";
    shipping = 0;
    taxAmount = 0;
    thickness = 0;
    width = 0;
}, recordType=OnhandChangeRecordType>
{
  creatorUserRecordID -> (null)
  lastModifiedUserRecordID -> (null)
  creationDate -> (null)
  modificationDate -> (null)
  completeStatus (modified) -> 0 (type q)
  shipping (modified) -> 0 (type d)
  modificationRecordType (modified) -> <CKReference: 0x608000025bc0; 4D59DB38-F783-47E6-A7EE-4435CDCFB72E:(_defaultZone:__defaultOwner__)>
  thickness (modified) -> 0 (type d)
  recordKey (modified) -> "6DB02EE4-67E8-42CD-89AA-C30DCE18B37C"
  width (modified) -> 0 (type d)
  quantityChange (modified) -> 1 (type d)
  modifiedBy (modified) -> "Rick’s 2017 MacBook Pro"
  length (modified) -> 0 (type d)
  price (modified) -> 8 (type d)
  displayOrder (modified) -> 2 (type q)
  createdBy (modified) -> "Rick’s 2017 MacBook Pro"
  itemRecordType (modified) -> <CKReference: 0x6080004257c0; 8B169D14-F6EE-4B84-A1D1-4E39AC6BF549:(_defaultZone:__defaultOwner__)>
  extension (modified) -> 0 (type d)
  quantityString (modified) -> "1"
  backordered (modified) -> 0 (type q)
  finalValueFee (modified) -> 0 (type d)
  taxAmount (modified) -> 0 (type d)
}


I haven't been able to find anything on the internet relating to this issue. I have been working with Cloudkit for over a year now and have not run into this before. I commonly store images as CKAssets and they upload and download fine on both the Mac and on iOS.