Setting CKRecord's recordChangeTag field for unit testing

Hi,

I am rrying to add unit tests for my CloudKit error handling code. One of my tests requires me to set the 'recordChangeTag' property to something that's not nil (so it can simulate an existing server record) ... but I can't figure out a way how to set this. Setting a value using the record.recordChangeTag doesn't work, wont even compile. I tried using [record setObject: @"aad" forKey:@"recordChangeTag"]; but even that fails at run-time, failing with this:

"caught "NSInvalidArgumentException", ""recordChangeTag" is a reserved key name"



Is there any other way to set this? I need to test some conflict-handling code, and the only way to do this sensibly is to simulate an existing server record, which you can't do without a 'recordChangeTag'.

Replies

Hi, I know it's an old question, but in case somebody faces the same problem. You can use method swizzling to address this issue.

private let swizzling: (CKRecord.Type) -> Void = { record in
  guard let originalMethod = class_getInstanceMethod(record, #selector(getter: CKRecord.recordChangeTag)),
     let swizzledMethod = class_getInstanceMethod(record, #selector(CKRecord.swizzledRecordChangeTag))
     else { return }
   
  method_exchangeImplementations(originalMethod, swizzledMethod)
}

extension CKRecord {
  class func doBadSwizzleStuff() {
    swizzling(self)
  }
   
  @objc func swizzledRecordChangeTag() -> String? {
    "123"
  }
}

And then call at your test setup: CKRecord.doBadSwizzleStuff()