insidegui / CloudKitCodable

An encoder and decoder for CKRecord
BSD 2-Clause "Simplified" License
387 stars 29 forks source link

Expose mechanism for viewing system fields #7

Open edorphy opened 3 years ago

edorphy commented 3 years ago

Hey Gui,

It would be great to have access to the system fields typed data of the CKRecord to provide the capability to the following workflows:

  1. Inspect recordChangeTag to detect conflicts before executing an CKModifyRecordsOperation
  2. Inspect the creatorUserRecordID for presentation to the user or logic purposes Example: owner can update, but enforce this client side--not by using security role
  3. Inspect modificationDate for display or logic purposes
  4. Etc for other system fields

Do you think this would compliment your library? I assume the above use cases would be commonly desired. Here is some quick and dirty on what I was thinking.

public struct CloudKitRecordSystemFields {

    private let metaRecord: CKRecord

    public var recordID: CKRecord.ID {
        metaRecord.recordID
    }

    public var recordType: CKRecord.RecordType {
        metaRecord.recordType
    }

    public var creationDate: Date? {
        metaRecord.creationDate
    }

    public var creatorUserRecordID: CKRecord.ID? {
        metaRecord.creatorUserRecordID
    }

    public var modificationDate: Date? {
        metaRecord.modificationDate
    }

    public var lastModifiedUserRecordID: CKRecord.ID? {
        metaRecord.lastModifiedUserRecordID
    }

    public var recordChangeTag: String? {
        metaRecord.recordChangeTag
    }

    public init(record: CKRecord) {
        self.metaRecord = record
    }
}

extension CloudKitRecordSystemFields {

    // Discussion: Static factory, convenience initializers, or both?

    public init(coder: NSCoder) {
        guard let metaRecord = CKRecord(coder: coder) else {
            // NOTE: Might have to use generics to infer recordType if coder initializer of the metaRecord fails if returning a default value instead of throw or nil
            fatalError()
        }

        self.metaRecord = metaRecord
    }

    public static from(coder: NSCoder) -> CloudKitRecordSystemFields {
        // TODO: Implement this signature
        fatalError()
    }

    public init(data: Data) {
        // TODO: Implement this signature
        fatalError()
    }

    public static func from(data: Data) -> CloudKitRecordSystemFields {
        // TODO: Implement this signature
        fatalError()
    }
}
insidegui commented 3 years ago

That seems like a good addition, feel free to PR the implementation 👍🏻