整体:与 CloudKit 文件系统同步时不必要的往返

Ensembles: unnecessary round-trip(s) when syncing with CloudKit file system

我已将 Ensembles v2.5 集成到我的应用程序中,并且我正在使用 CloudKit 文件系统。如 Ensembles 文档中所述,合并是通过推送通知自动触发的。

一般同步有效,但我的问题是在通过 CloudKit 将更改同步到第二台设备后,第二台设备似乎将新的事务日志上传到 CloudKit,这会触发另一次合并(通过推送通知)在第一台设备上。有时在第二个设备上进行另一个合并,导致两次不必要的合并。

实际例子:
1) 设备 1 (iPad) 进行更改
2) 更改传播到 CloudKit
3) 推送通知触发器在设备 2 (iPod Touch) 上合并

iPad 和 iPod Touch 现在具有相同的数据,不应再发生合并,但是:

4) iPod Touch 创建新的事务日志
5) 推送通知触发合并 iPad
6) iPad 创建新的事务日志
7) 推送通知触发器合并 iPod Touch

这是设备 2 (iPod Touch) 上的 Ensembles 跟踪

18:16:28.202   Enqueuing merge                                               <<<  -[CDEPersistentStoreEnsemble mergeWithOptions:completion:]
18:16:28.215   Beginning merge                                               <<<  __47-[CDEPersistentStoreEnsemble newMergeSetupStep]_block_invoke
18:16:28.234   Priming CloudKit cache                                        <<<  -[CDECloudKitFileSystem primeForActivityWithCompletion:]
18:16:28.235   Beginning change processing for CloudKit.                     <<<  -[CDECloudKitFileSystem primeForActivityWithCompletion:]
18:16:28.872   Processed cloudkit change (insert/update): /DemoAppMainStore/events/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent  <<<  __56-[CDECloudKitFileSystem primeForActivityWithCompletion:]_block_invoke
18:16:28.876   Completing CloudKit fetch record changes                      <<<  __56-[CDECloudKitFileSystem primeForActivityWithCompletion:]_block_invoke.311
18:16:28.887   Checking identity in cloud system                             <<<  -[CDEPersistentStoreEnsemble checkCloudFileSystemIdentityWithCompletion:]
18:16:29.314   Passed identity check with identity: <CKRecordID: 0x1660a840; _7fd2f6a37e22282e02a1d8fb52ba2d8e:(_defaultZone:__defaultOwner__)>  <<<  __73-[CDEPersistentStoreEnsemble checkCloudFileSystemIdentityWithCompletion:]_block_invoke
18:16:29.324   Checking registration info                                    <<<  -[CDEPersistentStoreEnsemble checkStoreRegistrationInCloudWithCompletion:]
18:16:29.325   Checking existence of registration info                       <<<  -[CDECloudManager checkExistenceOfRegistrationInfoForStoreWithIdentifier:completion:]
18:16:29.326   Checking existence of file: /DemoAppMainStore/stores/0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA  <<<  -[CDECloudKitFileSystem fileExistsAtPath:completion:]
18:16:29.329   Retrieving records for paths: (
    "/DemoAppMainStore/stores/0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA"
)  <<<  -[CDECloudKitFileSystem fetchRecordsAtPaths:completion:]
18:16:29.330   File exists. Is dir? 0                                        <<<  __53-[CDECloudKitFileSystem fileExistsAtPath:completion:]_block_invoke
18:16:29.343 Localizable string "(A Document Being Saved By %@)" not found in strings table "Document" of bundle CFBundle 0x166429d0 </System/Library/Frameworks/Foundation.framework> (not loaded).
18:16:29.380   Getting contents of directory at path: /DemoAppMainStore/baselines  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:29.383   Getting contents of directory at path: /DemoAppMainStore/events  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:29.386   Getting contents of directory at path: /DemoAppMainStore/data  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:29.394   Removing incomplete remote file sets                          <<<  -[CDECloudManager removeLocallyProducedIncompleteRemoteFileSets:]
18:16:29.447   Transferring new data files from cloud to event store         <<<  -[CDECloudManager importNewDataFilesWithProgress:]
18:16:29.459   Transferring new baselines from cloud to event store          <<<  -[CDECloudManager importNewBaselineEventsWithProgress:]
18:16:29.486   Consolidating baselines                                       <<<  -[CDEBaselineConsolidator consolidateBaselineWithCompletion:]
18:16:29.498   Found baselines with unique ids: (
    "848B3010-D3D0-4928-BFA9-249D2CE617A0-777-000002E2704C7408"
)  <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke
18:16:29.499   Baselines remaining that need merging: 1                      <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke
18:16:29.501   Finishing baseline consolidation                              <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke_2
18:16:29.506   Transferring new events from cloud to event store             <<<  -[CDECloudManager importNewRemoteNonBaselineEventsWithProgress:]
18:16:29.588   Downloading files to transit cache: (
    "/DemoAppMainStore/events/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent"
)  <<<  __83-[CDECloudManager downloadFiles:fromRemoteDirectory:batchCompletionBlock:progress:]_block_invoke_2
18:16:29.591   Downloading from paths (
    "/DemoAppMainStore/events/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent"
) to path (
    "/var/mobile/Containers/Data/Application/3EA6BB44-7135-4C5D-91D3-D36878005B1C/Library/Application Support/ch.appzoo.DemoApp/com.mentalfaculty.ensembles.eventdata/transitcache/DemoAppMainStore/download/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent"
)  <<<  -[CDECloudKitFileSystem downloadFromPaths:toLocalFiles:completion:]
18:16:32.120   Migrating event in to event store from files: (
    "33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent"
)  <<<  __84-[CDECloudManager migrateNewEventsWhichAreBaselines:fromTransitCacheWithCompletion:]_block_invoke.292
18:16:32.121   Migrating events in from files                                <<<  -[CDEEventMigrator migrateEventInFromFileURLs:completion:]
18:16:32.124   Migrating file events to event store                          <<<  -[CDEEventImport main]
18:16:32.125   Importing file at URL: file:///var/mobile/Containers/Data/Application/3EA6BB44-7135-4C5D-91D3-D36878005B1C/Library/Application%20Support/ch.appzoo.DemoApp/com.mentalfaculty.ensembles.eventdata/transitcache/DemoAppMainStore/download/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent  <<<  __22-[CDEEventImport main]_block_invoke.22
18:16:32.382   Determining events to include in integration                  <<<  -[CDEEventIntegrator storeModificationEventIDsForIntegration:]
18:16:32.546   Including these events in the integration: (
    "<CDEStoreModificationEvent: 0x167b3590> (entity: CDEStoreModificationEvent; id: 0x167d6720 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEStoreModificationEvent/p37> ; data: {\n    eventRevision = \"0x167a7280 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p72>\";\n    eventRevisionsOfOtherStores =     (\n        \"0x167ddf40 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p71>\"\n    );\n    globalCount = 32;\n    modelVersion = \"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>\n<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">\n<plist version=\\"1.0\\">\n<dict>\n\t<key>DMBuddy</key>\n\t<data>\n\t\";\n    objectChanges = \"<relationship fault: 0x17878a60 'objectChanges'>\";\n    timestamp = \"16:49:55 +0000\";\n    type = 300;\n    uniqueIdentifier = \"E432A13E-3825-4833-A306-F84044492252-498-0000010ED9BE7E88\";\n})",
    "<CDEStoreModificationEvent: 0x167b3620> (entity: CDEStoreModificationEvent; id: 0x16730ac0 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEStoreModificationEvent/p38> ; data: {\n    eventRevision = \"0x166b4420 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p73>\";\n    eventRevisionsOfOtherStores =     (\n        \"0x167ecb10 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p74>\"\n    );\n    globalCount = 33;\n    modelVersion = \"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>\n<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">\n<plist version=\\"1.0\\">\n<dict>\n\t<key>DMBuddy</key>\n\t<data>\n\t\";\n    objectChanges = \"<relationship fault: 0x1651f9a0 'objectChanges'>\";\n    timestamp = \"17:16:23 +0000\";\n    type = 200;\n    uniqueIdentifier = \"83664AB6-F3FE-4454-B794-12858EB3215C-501-00000110A14995E1\";\n})"
)  <<<  __62-[CDEEventIntegrator storeModificationEventIDsForIntegration:]_block_invoke
18:16:32.550   Checking which events can be integrated                       <<<  -[CDEEventIntegrator integrableEventIDsFromEventIDs:informativeErrorCodes:]
18:16:32.554   Determining integrable events                                 <<<  -[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]
18:16:39.046   Checking store: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:39.047   Revision range: store id: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3
revision: 20
global count: 32 store id: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3
revision: 21
global count: 33  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:39.098   Checking store: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:39.099   Revision range: store id: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA
revision: 15
global count: 32 store id: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA
revision: 15
global count: 33  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:39.131   Checking if ready for integration                             <<<  -[CDEEventIntegrator integrationIsNeededForEventIDs:]
18:16:39.254   Beginning integration                                         <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.256   Integrating entity: DMBuddy                                   <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.267   Integrating entity: DMCertificate                             <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.287   Integrating entity: DMDiveLogEntry                            <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.309   Number of objects remaining to integrate for this entity: 0   <<<  __46-[CDEEventIntegrator integrateEventIDs:error:]_block_invoke
18:16:39.431   Integrating entity: DMDiver                                   <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.555   Integrating entity: DMEquipment                               <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.603   Integrating entity: DMPhoto                                   <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.672   Integrating entity: DMPlace                                   <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.765   Integrating entity: DMTagValue                                <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.784   Integrating entity: DMTankData                                <<<  -[CDEEventIntegrator integrateEventIDs:error:]
18:16:39.851   Repairing context after integrating changes                   <<<  -[CDEEventIntegrator repair:]
18:16:39.856   Committing merge changes to store                             <<<  -[CDEEventIntegrator commit:]
18:16:39.863   Storing pre-save changes from updated objects                 <<<  -[CDESaveMonitor storePreSaveChangesFromUpdatedObjects:]
18:16:40.045   Transferring data files from event store to cloud             <<<  -[CDECloudManager exportDataFilesWithProgress:]
18:16:40.094   Transferring baseline from event store to cloud               <<<  -[CDECloudManager exportNewLocalBaselineWithProgress:]
18:16:40.176   Transferring events from event store to cloud                 <<<  -[CDECloudManager exportNewLocalNonBaselineEventsWithProgress:]
18:16:40.322   Migrating events out to files                                 <<<  -[CDEEventMigrator migrateStoreModificationEventWithObjectID:toTemporaryFilesWithCompletion:]
18:16:40.369   Exporting files for entity: DMBuddy                           <<<  -[CDEEventExport main]
18:16:40.382   Exporting files for entity: DMCertificate                     <<<  -[CDEEventExport main]
18:16:40.394   Exporting files for entity: DMDiveLogEntry                    <<<  -[CDEEventExport main]
18:16:40.406   Exporting files for entity: DMDiver                           <<<  -[CDEEventExport main]
18:16:40.414   Exporting files for entity: DMEquipment                       <<<  -[CDEEventExport main]
18:16:40.423   Exporting files for entity: DMPhoto                           <<<  -[CDEEventExport main]
18:16:40.431   Exporting files for entity: DMPlace                           <<<  -[CDEEventExport main]
18:16:40.441   Exporting files for entity: DMTagValue                        <<<  -[CDEEventExport main]
18:16:40.451   Exporting files for entity: DMTankData                        <<<  -[CDEEventExport main]
18:16:40.485   Uploading files to remote path: (
    "/DemoAppMainStore/events/34_0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA_16.cdeevent"
)  <<<  __73-[CDECloudManager transferFilesInTransitCacheToRemoteDirectory:progress:]_block_invoke_3
18:16:40.487   Uploading from paths (
    "/var/mobile/Containers/Data/Application/3EA6BB44-7135-4C5D-91D3-D36878005B1C/Library/Application Support/ch.appzoo.DemoApp/com.mentalfaculty.ensembles.eventdata/transitcache/DemoAppMainStore/upload/34_0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA_16.cdeevent"
) to paths (
    "/DemoAppMainStore/events/34_0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA_16.cdeevent"
)  <<<  -[CDECloudKitFileSystem uploadLocalFiles:toPaths:completion:]
18:16:42.525   Removing outdated files                                       <<<  -[CDECloudManager removeOutdatedRemoteFilesWithCompletion:]
18:16:42.607   Removing cloud files:                                         <<<  -[CDECloudManager removeOutdatedRemoteFilesWithCompletion:]
18:16:42.625   Removing items at paths: (
)                                  <<<  -[CDECloudKitFileSystem removeItemsAtPaths:completion:]
18:16:42.626   Retrieving records for paths: (
)                             <<<  -[CDECloudKitFileSystem fetchRecordsAtPaths:completion:]
18:16:42.628   Fetched records for removal: (
)                              <<<  __55-[CDECloudKitFileSystem removeItemsAtPaths:completion:]_block_invoke
18:16:42.630   Removing items with recordIDs: (
)                            <<<  -[CDECloudKitFileSystem removeItemsWithRecordIDs:completion:]
18:16:42.651   Completing Merge                                              <<<  __58-[CDEPersistentStoreEnsemble mergeWithOptions:completion:]_block_invoke.694



18:16:48.068   Enqueuing merge                                               <<<  -[CDEPersistentStoreEnsemble mergeWithOptions:completion:]
18:16:48.082   Beginning merge                                               <<<  __47-[CDEPersistentStoreEnsemble newMergeSetupStep]_block_invoke
18:16:48.096   Priming CloudKit cache                                        <<<  -[CDECloudKitFileSystem primeForActivityWithCompletion:]
18:16:48.097   Beginning change processing for CloudKit.                     <<<  -[CDECloudKitFileSystem primeForActivityWithCompletion:]

18:16:48.464   Processed cloudkit change (insert/update): /DemoAppMainStore/events/34_0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA_16.cdeevent  <<<  __56-[CDECloudKitFileSystem primeForActivityWithCompletion:]_block_invoke
18:16:48.474   Processed cloudkit change (insert/update): /DemoAppMainStore/events/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent  <<<  __56-[CDECloudKitFileSystem primeForActivityWithCompletion:]_block_invoke
18:16:48.477   Completing CloudKit fetch record changes                      <<<  __56-[CDECloudKitFileSystem primeForActivityWithCompletion:]_block_invoke.311
18:16:48.489   Checking identity in cloud system                             <<<  -[CDEPersistentStoreEnsemble checkCloudFileSystemIdentityWithCompletion:]
18:16:48.884   Passed identity check with identity: <CKRecordID: 0x1660a840; _7fd2f6a37e22282e02a1d8fb52ba2d8e:(_defaultZone:__defaultOwner__)>  <<<  __73-[CDEPersistentStoreEnsemble checkCloudFileSystemIdentityWithCompletion:]_block_invoke
18:16:48.889   Checking registration info                                    <<<  -[CDEPersistentStoreEnsemble checkStoreRegistrationInCloudWithCompletion:]
18:16:48.890   Checking existence of registration info                       <<<  -[CDECloudManager checkExistenceOfRegistrationInfoForStoreWithIdentifier:completion:]
18:16:48.891   Checking existence of file: /DemoAppMainStore/stores/0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA  <<<  -[CDECloudKitFileSystem fileExistsAtPath:completion:]
18:16:48.892   Retrieving records for paths: (
    "/DemoAppMainStore/stores/0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA"
)  <<<  -[CDECloudKitFileSystem fetchRecordsAtPaths:completion:]
18:16:48.893   File exists. Is dir? 0                                        <<<  __53-[CDECloudKitFileSystem fileExistsAtPath:completion:]_block_invoke
18:16:48.907 Localizable string "(A Document Being Saved By %@)" not found in strings table "Document" of bundle CFBundle 0x166429d0 </System/Library/Frameworks/Foundation.framework> (not loaded).
18:16:48.942   Getting contents of directory at path: /DemoAppMainStore/baselines  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:48.944   Getting contents of directory at path: /DemoAppMainStore/events  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:48.947   Getting contents of directory at path: /DemoAppMainStore/data  <<<  -[CDECloudKitFileSystem contentsOfDirectoryAtPath:completion:]
18:16:48.954   Removing incomplete remote file sets                          <<<  -[CDECloudManager removeLocallyProducedIncompleteRemoteFileSets:]
18:16:49.016   Transferring new data files from cloud to event store         <<<  -[CDECloudManager importNewDataFilesWithProgress:]
18:16:49.028   Transferring new baselines from cloud to event store          <<<  -[CDECloudManager importNewBaselineEventsWithProgress:]
18:16:49.057   Consolidating baselines                                       <<<  -[CDEBaselineConsolidator consolidateBaselineWithCompletion:]
18:16:49.068   Found baselines with unique ids: (
    "848B3010-D3D0-4928-BFA9-249D2CE617A0-777-000002E2704C7408"
)  <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke
18:16:49.069   Baselines remaining that need merging: 1                      <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke
18:16:49.071   Finishing baseline consolidation                              <<<  __61-[CDEBaselineConsolidator consolidateBaselineWithCompletion:]_block_invoke_2
18:16:49.075   Transferring new events from cloud to event store             <<<  -[CDECloudManager importNewRemoteNonBaselineEventsWithProgress:]
18:16:49.150   Downloading files to transit cache: (
    "/DemoAppMainStore/events/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent"
)  <<<  __83-[CDECloudManager downloadFiles:fromRemoteDirectory:batchCompletionBlock:progress:]_block_invoke_2
18:16:49.153   Downloading from paths (
    "/DemoAppMainStore/events/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent"
) to path (
    "/var/mobile/Containers/Data/Application/3EA6BB44-7135-4C5D-91D3-D36878005B1C/Library/Application Support/ch.appzoo.DemoApp/com.mentalfaculty.ensembles.eventdata/transitcache/DemoAppMainStore/download/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent"
)  <<<  -[CDECloudKitFileSystem downloadFromPaths:toLocalFiles:completion:]
18:16:50.214   Migrating event in to event store from files: (
    "35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent"
)  <<<  __84-[CDECloudManager migrateNewEventsWhichAreBaselines:fromTransitCacheWithCompletion:]_block_invoke.292
18:16:50.215   Migrating events in from files                                <<<  -[CDEEventMigrator migrateEventInFromFileURLs:completion:]
18:16:50.218   Migrating file events to event store                          <<<  -[CDEEventImport main]
18:16:50.219   Importing file at URL: file:///var/mobile/Containers/Data/Application/3EA6BB44-7135-4C5D-91D3-D36878005B1C/Library/Application%20Support/ch.appzoo.DemoApp/com.mentalfaculty.ensembles.eventdata/transitcache/DemoAppMainStore/download/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent  <<<  __22-[CDEEventImport main]_block_invoke.22
18:16:50.456   Determining events to include in integration                  <<<  -[CDEEventIntegrator storeModificationEventIDsForIntegration:]
18:16:50.600   Including these events in the integration: (
    "<CDEStoreModificationEvent: 0x178b45e0> (entity: CDEStoreModificationEvent; id: 0x165342e0 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEStoreModificationEvent/p40> ; data: {\n    eventRevision = \"0x178a4cc0 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p77>\";\n    eventRevisionsOfOtherStores =     (\n        \"0x178a4cd0 <x-coredata://7EC8021F-B83B-4A27-B9B9-D1645A533448/CDEEventRevision/p78>\"\n    );\n    globalCount = 35;\n    modelVersion = \"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>\n<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">\n<plist version=\\"1.0\\">\n<dict>\n\t<key>DMBuddy</key>\n\t<data>\n\t\";\n    objectChanges = \"<relationship fault: 0x1651e8d0 'objectChanges'>\";\n    timestamp = \"17:16:45 +0000\";\n    type = 300;\n    uniqueIdentifier = \"3F19C4EE-816D-425F-99BC-BE991EEE1476-501-00000110C03D4133\";\n})"
)  <<<  __62-[CDEEventIntegrator storeModificationEventIDsForIntegration:]_block_invoke
18:16:50.601   Checking which events can be integrated                       <<<  -[CDEEventIntegrator integrableEventIDsFromEventIDs:informativeErrorCodes:]
18:16:50.603   Determining integrable events                                 <<<  -[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]
18:16:54.843   Checking store: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:54.845   Revision range: store id: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3
revision: 22
global count: 35 store id: 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3
revision: 22
global count: 35  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:54.872   Checking store: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:54.874   Revision range: store id: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA
revision: 16
global count: 35 store id: 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA
revision: 16
global count: 35  <<<  __71-[CDERevisionManager integrableEventsFromEvents:informativeErrorCodes:]_block_invoke
18:16:54.903   Checking if ready for integration                             <<<  -[CDEEventIntegrator integrationIsNeededForEventIDs:]
18:16:54.975   Transferring data files from event store to cloud             <<<  -[CDECloudManager exportDataFilesWithProgress:]
18:16:54.996   Transferring baseline from event store to cloud               <<<  -[CDECloudManager exportNewLocalBaselineWithProgress:]
18:16:55.058   Transferring events from event store to cloud                 <<<  -[CDECloudManager exportNewLocalNonBaselineEventsWithProgress:]
18:16:55.163   Removing outdated files                                       <<<  -[CDECloudManager removeOutdatedRemoteFilesWithCompletion:]
18:16:55.249   Removing cloud files:                                         <<<  -[CDECloudManager removeOutdatedRemoteFilesWithCompletion:]
18:16:55.269   Removing items at paths: (
)                                  <<<  -[CDECloudKitFileSystem removeItemsAtPaths:completion:]
18:16:55.270   Retrieving records for paths: (
)                             <<<  -[CDECloudKitFileSystem fetchRecordsAtPaths:completion:]
18:16:55.273   Fetched records for removal: (
)                              <<<  __55-[CDECloudKitFileSystem removeItemsAtPaths:completion:]_block_invoke
18:16:55.274   Removing items with recordIDs: (
)                            <<<  -[CDECloudKitFileSystem removeItemsWithRecordIDs:completion:]
18:16:55.298   Completing Merge                                              <<<  __58-[CDEPersistentStoreEnsemble mergeWithOptions:completion:]_block_invoke.694

...这是推送通知:

IPOD TOUCH
18:16:28.199 | iCloudSyncActivity | Thread 16 | did receive remote notification, userInfo = '{
    aps =     {
        "content-available" = 1;
        sound = "";
    };
    ck =     {
        ce = 2;
        cid = "iCloud.com.example.app";
        nid = "cc0f33fc-0488-4abb-b9aa-2bfd7c8db88b";
        qry =         {
            dbs = 1;
            fo = 1;
            rid = "CDEFileSystemNode_/DiveMateMainStore/events/33_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_21.cdeevent";
            sid = CDEFileAddedSubscription;
            zid = "com.mentalfaculty.ensembles.zone.schema2";
            zoid = "_7fd2f6a37e22282e02a1d8fb52ba2d8e";
        };
    };
}'

IPAD:
18:16:42.258 | iCloudSyncActivity | Thread 15 | did receive remote notification, userInfo = '{
    aps =     {
        "content-available" = 1;
        sound = "";
    };
    ck =     {
        ce = 2;
        cid = "iCloud.com.example.app";
        nid = "2bb1a2f0-5dbb-47b7-b6e1-1e6de9afdac9";
        qry =         {
            dbs = 1;
            fo = 1;
            rid = "CDEFileSystemNode_/DiveMateMainStore/events/34_0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA_16.cdeevent";
            sid = CDEFileAddedSubscription;
            zid = "com.mentalfaculty.ensembles.zone.schema2";
            zoid = "_7fd2f6a37e22282e02a1d8fb52ba2d8e";
        };
    };
}'

IPOD TOUCH
[260     ] 18:16:48.064 | iCloudSyncActivity | Thread 16 | did receive remote notification, userInfo = '{
    aps =     {
        "content-available" = 1;
        sound = "";
    };
    ck =     {
        ce = 2;
        cid = "iCloud.com.example.app";
        nid = "4ee5383d-9a94-4596-99f2-18ae7da6e0ca";
        qry =         {
            dbs = 1;
            fo = 1;
            rid = "CDEFileSystemNode_/DiveMateMainStore/events/35_826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3_22.cdeevent";
            sid = CDEFileAddedSubscription;
            zid = "com.mentalfaculty.ensembles.zone.schema2";
            zoid = "_7fd2f6a37e22282e02a1d8fb52ba2d8e";
        };
    };
}'

对我来说奇怪的是 Ensembles 跟踪指的是 2 家商店:
-一个 ID 为 826D4BD2-2ED2-4C3B-9A89-22E3D910EC55-476-000000FAF9F774C3
-ID 为 0B96EB62-03B1-414F-BBA5-3FCBDD2E9CD4-777-000002E26205C2DA

作为参考,我是这样设置 Ensembles 的:

_ensemble = [[CDEPersistentStoreEnsemble alloc] initWithEnsembleIdentifier:DM_ENSEMBLE_IDENTIFIER
                                                        persistentStoreURL:storeURL
                                                     managedObjectModelURL:[self _getManagedObjectModelURL]
                                                           cloudFileSystem:_iCloudFileSystem];

非常感谢任何方向正确的 help/pointers。

这是预期的行为,最后一次合并应该非常快。如果您发现太多,您可以轻松地选择限制由推送通知触发的合并。例如。如果在进行合并后一分钟内有推送进来,您可以选择忽略它。

每次更改 3 次合并不是空操作。他们正在进行重要的核算,以确保所有设备最终都具有相同的数据。

将合奏想象成 Git。在内部,基本上就是这样。现在,您在一台设备上进行更改,这会在该设备上触发新的提交 (S1_D1)。然后您进行合并以将数据推送到云端。

由于推送通知,第二个设备现在合并以获取该数据,并为此创建一个提交 (M1_D2)。这可能包括也可能不包括冲突解决方案,但它对并发系统很重要。它相当于 Git 合并两个分支,并且你必须有一个新的提交来代表历史中的那个。

合并(M1_D2)被推送到云端,现在原始设备看到一个新的提交,并且必须进行合并操作来导入它,尽管它不会产生任何新的提交本身。

所以一个存档应该需要在原设备上合并,在另一台设备上合并,在原设备上再合并,才能完整完成。这就是它在像 Git 这样的系统中以及在 Ensembles 中的工作方式。

请注意,虽然需要 3 次合并操作,但您可以完全控制它们何时发生。您可以根据需要延迟它们,或者像我提到的那样忽略某些推送。该系统足够聪明,可以在您最终合并时解决所有问题(就像 Git 一样)。