diff --git a/README.md b/README.md index b3b8995..14f16b2 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,12 @@ func ignoredProperties() -> [String] ``` which how its name suggests, let you ignore some properties from being encoded in the resultant `CKRecord`. +You can implement the function +```swift +func cloudKitReferenceActions() -> [String: CKRecord.Reference.Action] +``` +which how its name suggests, let you set `CKRecord.Reference.Action` for any reference property. The default action is `.deleteSelf`. + ### CLLocation `CLLocation` properties has a special behavior. Since they are primitive types for `CloudKit` but they are not for `Codable` protocol, it was necessary to create a workaround to encode/decode them. diff --git a/Shared/Example Objects/School.swift b/Shared/Example Objects/School.swift index 3322058..46db624 100644 --- a/Shared/Example Objects/School.swift +++ b/Shared/Example Objects/School.swift @@ -9,6 +9,7 @@ import CoreLocation import NestedCloudKitCodable import UIKit +import CloudKit // swiftlint:disable implicitly_unwrapped_optional struct School: CKCodable { @@ -61,4 +62,12 @@ struct School: CKCodable { try container.encode(director, forKey: .director) try container.encode(books, forKey: .books) } + + func cloudKitReferenceActions() -> [String : CKRecord.Reference.Action] { + return [ + "students": .deleteSelf, + "director": .deleteSelf, + "books": .none + ] + } } diff --git a/Source/Classes/CKRecordRepresentable.swift b/Source/Classes/CKRecordRepresentable.swift index 80e4df7..5886c3b 100644 --- a/Source/Classes/CKRecordRepresentable.swift +++ b/Source/Classes/CKRecordRepresentable.swift @@ -14,10 +14,12 @@ public protocol CKRecordRepresentable { var cloudKitIdentifier: String { get } func ignoredProperties() -> [String] + func cloudKitReferenceActions() -> [String: CKRecord.Reference.Action] } public extension CKRecordRepresentable { func ignoredProperties() -> [String] { return [] } + func cloudKitReferenceActions() -> [String: CKRecord.Reference.Action] { return [:] } } public typealias CKEncodable = CKRecordRepresentable & Encodable diff --git a/Source/Classes/Encoder/CKEncoderKeyedContainer.swift b/Source/Classes/Encoder/CKEncoderKeyedContainer.swift index c0624e2..7c07d93 100644 --- a/Source/Classes/Encoder/CKEncoderKeyedContainer.swift +++ b/Source/Classes/Encoder/CKEncoderKeyedContainer.swift @@ -71,7 +71,7 @@ extension CKEncoderKeyedContainer: KeyedEncodingContainerProtocol { // MARK: Auxiliar Encode functions private func encodeSingleValue(_ value: CKEncodable, forKey key: Key) throws { - storage[key.stringValue] = try produceReference(for: value) + storage[key.stringValue] = try produceReference(for: value, key: key) let encoder = CloudKitRecordEncoder(object: value, zoneID: zoneID, createdRecords: createdRecords) @@ -87,7 +87,7 @@ extension CKEncoderKeyedContainer: KeyedEncodingContainerProtocol { forKey key: Key) throws where T: Encodable { var references = [CKRecord.Reference]() try castedValues.forEach { - let reference = try produceReference(for: $0) + let reference = try produceReference(for: $0, key: key) references.append(reference) } storage[key.stringValue] = references as CKRecordValue @@ -198,9 +198,11 @@ extension CKEncoderKeyedContainer: KeyedEncodingContainerProtocol { storage[key.stringValue] = locations as CKRecordValue } - private func produceReference(for value: CKEncodable) throws -> CKRecord.Reference { + private func produceReference(for value: CKEncodable, key: Key) throws -> CKRecord.Reference { let recordID = CKRecord.ID(recordName: value.cloudKitIdentifier, zoneID: zoneID ?? .default) - return CKRecord.Reference(recordID: recordID, action: .deleteSelf) + let actions = object.cloudKitReferenceActions() + let action = actions[key.stringValue] ?? .deleteSelf + return CKRecord.Reference(recordID: recordID, action: action) } func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {