Skip to content

Commit

Permalink
add u, v, w objectClassType
Browse files Browse the repository at this point in the history
  • Loading branch information
caiyue1993 committed Feb 8, 2021
1 parent 8667139 commit 10609d2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 16 deletions.
6 changes: 3 additions & 3 deletions Example/IceCream_Example/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

syncEngine = SyncEngine(objects: [
SyncObject<Dog, Cat>(),
SyncObject<Cat, Cat>(),
SyncObject<Person, Cat>(),
SyncObject(type: Dog.self),
SyncObject(type: Cat.self),
SyncObject(type: Person.self, uObjectClassType: Cat.self)
])

/// If you wanna test public Database, comment the above syncEngine code and uncomment the following one
Expand Down
60 changes: 50 additions & 10 deletions IceCream/Classes/CKRecordRecoverable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public protocol CKRecordRecoverable {
}

extension CKRecordRecoverable where Self: Object {
static func parseFromRecord<U: Object>(record: CKRecord, realm: Realm, notificationToken: NotificationToken?, listType: U.Type) -> Self? {
static func parseFromRecord<U: Object, V: Object, W: Object>(record: CKRecord, realm: Realm, notificationToken: NotificationToken?, uListType: U.Type, vListType: V.Type, wListType: W.Type) -> Self? {
let o = Self()
for prop in o.objectSchema.properties {
var recordValue: Any?
Expand Down Expand Up @@ -59,21 +59,61 @@ extension CKRecordRecoverable where Self: Object {
guard let value = record.value(forKey: prop.name) as? [CKRecord.Reference] else { break }
// 这里应该根据 List 去创建一个 unmanaged 版本的 List,而不是使用 dynamicList 获取 managed 版本的 list
// 另外需要考虑的就是类型问题
let list = List<U>()
let uList = List<U>()
let vList = List<V>()
let wList = List<W>()

// guard let list = o.value(forKey: prop.name) as? List<Object> else { break }
// let list = o.dynamicList(prop.name)
for reference in value {
if let objectClassName = prop.objectClassName,
let schema = realm.schema.objectSchema.first(where: { $0.className == objectClassName }),
let primaryKeyValue = primaryKeyForRecordID(recordID: reference.recordID, schema: schema),
let existObject = realm.object(ofType: listType, forPrimaryKey: primaryKeyValue) {
list.append(existObject)
} else {
let object = realm.create(listType)
list.append(object)
let schema = realm.schema.objectSchema.first(where: { $0.className == objectClassName }),
let primaryKeyValue = primaryKeyForRecordID(recordID: reference.recordID, schema: schema) {

// 其实在这里一个数组里所有的 className 都只会是一种

if schema.className == uListType.className() {
if let existObject = realm.object(ofType: uListType, forPrimaryKey: primaryKeyValue) {
uList.append(existObject)
} else {
let object = realm.create(uListType)
uList.append(object)
}
}

if schema.className == vListType.className() {
if let existObject = realm.object(ofType: vListType, forPrimaryKey: primaryKeyValue) {
vList.append(existObject)
} else {
let object = realm.create(vListType)
vList.append(object)
}
}

if schema.className == wListType.className() {
if let existObject = realm.object(ofType: wListType, forPrimaryKey: primaryKeyValue) {
wList.append(existObject)
} else {
let object = realm.create(wListType)
wList.append(object)
}
}

}
}
recordValue = list

if prop.objectClassName == uListType.className() {
recordValue = uList
}

if prop.objectClassName == vListType.className() {
recordValue = vList
}

if prop.objectClassName == wListType.className() {
recordValue = wList
}

default:
break
}
Expand Down
14 changes: 11 additions & 3 deletions IceCream/Classes/SyncObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,27 @@ import CloudKit
/// 2. it detects the changeSets of Realm Database and directly talks to it.
/// 3. it hands over to SyncEngine so that it can talk to CloudKit.

public final class SyncObject<T, U> where T: Object & CKRecordConvertible & CKRecordRecoverable, U: Object {
public final class SyncObject<T, U, V, W> where T: Object & CKRecordConvertible & CKRecordRecoverable, U: Object, V: Object, W: Object {

/// Notifications are delivered as long as a reference is held to the returned notification token. We should keep a strong reference to this token on the class registering for updates, as notifications are automatically unregistered when the notification token is deallocated.
/// For more, reference is here: https://realm.io/docs/swift/latest/#notifications
private var notificationToken: NotificationToken?

public var pipeToEngine: ((_ recordsToStore: [CKRecord], _ recordIDsToDelete: [CKRecord.ID]) -> ())?
// let listNameTypePairStore = ListNameTypePairStore(className: T.className())

public let realmConfiguration: Realm.Configuration

public init(realmConfiguration: Realm.Configuration = Realm.Configuration.defaultConfiguration) {
public init(
realmConfiguration: Realm.Configuration = .defaultConfiguration,
type: T.Type,
uObjectClassType: U.Type? = nil,
vObjectClassType: V.Type? = nil,
wObjectClassType: W.Type? = nil
) {
self.realmConfiguration = realmConfiguration
}

}

// MARK: - Zone information
Expand Down Expand Up @@ -72,7 +80,7 @@ extension SyncObject: Syncable {
public func add(record: CKRecord) {
BackgroundWorker.shared.start {
let realm = try! Realm(configuration: self.realmConfiguration)
guard let object = T.parseFromRecord(record: record, realm: realm, notificationToken: self.notificationToken, listType: U.self) else {
guard let object = T.parseFromRecord(record: record, realm: realm, notificationToken: self.notificationToken, uListType: U.self, vListType: V.self, wListType: W.self) else {
print("There is something wrong with the converson from cloud record to local object")
return
}
Expand Down

0 comments on commit 10609d2

Please sign in to comment.