Handling “Ghost” Records After Sync Down Operations

If you’re finding that sync down operations sometimes leave unwanted records in your SmartStore soups, you can use the cleanResyncGhosts API to get rid of them.

In certain prescribed cases, SmartStore soups do not reflect the exact contents of the most recent sync down request. For example, if a record is deleted on the Salesforce server, the next sync down operation doesn’t remove that record from SmartStore. Also, records that don’t satisfy the sync criteria are excluded from the sync down results but aren’t automatically removed from the soup. These records that unexpectedly remain in the SmartStore soup are known as ghosts.

To root out these haunts, Mobile Sync provides a set of cleanResyncGhosts methods that identify and remove ghosts. You pass in the ID or name of a sync object and define a callback block. These methods are available for Android native, iOS native, hybrid, and React Native platforms.

Exercise restraint in using the cleanResyncGhosts methods! Calls to these methods can be expensive in both runtime performance and payload size. Use these methods for low-frequency cleanup, rather than as part of every sync down operation. Use your own judgment to determine whether a particular set of ghosts is problematic and therefore requires immediate cleanup.

Warning

Using cleanResyncGhosts with Custom Sync Down Targets

If your app uses a custom sync down target, cleanResyncGhosts requires the custom target to implement the getListOfRemoteIds method. This method returns the list of Salesforce IDs that satisfy the sync down target’s criteria. For getListOfRemoteIds coding examples, see the SOQL, SOSL, or MRU sync down target in these Mobile Sync library folders:

iOS
https://github.com/forcedotcom/SalesforceMobileSDK-iOS/tree/master/libs/MobileSync/MobileSync/Classes/Util
Android
https://github.com/forcedotcom/SalesforceMobileSDK-Android/tree/master/libs/MobileSync/src/com/salesforce/androidsdk/mobilesync/util

Preparing Soups for cleanResyncGhosts

For the target soup, add an index for the following field:
__sync_id__
This field ensures that the cleanResyncGhosts() method removes only the desired soup elements. Mobile Sync manages the content of this field for you.

Calling cleanResyncGhosts Methods by Sync ID

iOS Native
Swift Objective-C
SyncManager SFMobileSyncSyncManager
Swift
In Mobile SDK 7.1, the following method is updated to throw.
1open func cleanResyncGhosts(
2                        forId syncId: NSNumber, 
3    onComplete completionStatusBlock: @escaping SyncCompletionBlock) throws
Objective-C
In Mobile SDK 7.1, the following method is updated to support an NSError output parameter.
1- (BOOL) 
2        cleanResyncGhosts:(NSNumber*)syncId
3    completionStatusBlock:
4        (SFSyncSyncManagerCompletionStatusBlock)completionStatusBlock 
5                    error:(NSError**)error;
Android Native
Kotlin
1suspend fun suspendCleanResyncGhosts(syncId: Long): Int
Java
1public void cleanResyncGhosts(final long syncId) 
2    throws JSONException, IOException
3
4public void cleanResyncGhosts(long syncId, 
5    final CleanResyncGhostsCallback callback) 
6    throws JSONException
Hybrid
1cleanResyncGhosts(isGlobalStore, syncId, successCB, errorCB)
2
3cleanResyncGhosts(storeConfig, syncId, successCB, errorCB)
React Native
1mobilesync.cleanResyncGhosts(isGlobalStore, syncId, successCB, errorCB)
2
3mobilesync.cleanResyncGhosts(storeConfig, syncId, successCB, errorCB)

Calling cleanResyncGhosts Methods by Sync Name

You can also call cleanResyncGhosts with a sync name.
iOS (Swift)
1//Mobile Sync native Swift extension function
2public func cleanGhosts(named syncName: String, 
3    _ completionBlock: @escaping (Result<UInt, MobileSyncError>) -> Void
4
5//Objective-C function renamed for Swift
6open func cleanResyncGhosts(
7                    forName syncName: String, 
8    onComplete completionStatusBlock: @escaping SyncCompletionBlock) throws
9
10//iOS 13 or above only:
11//Mobile Sync native Swift extension function, using Combine Publisher
12public func cleanGhostsPublisher(for syncName: String) -> 
13    Future<UInt, MobileSyncError>
iOS (Objective-C)
1- (*BOOL*) 
2    cleanResyncGhostsByName:(NSString*)syncName
3      completionStatusBlock:
4          (SFSyncSyncManagerCompletionStatusBlock)completionStatusBlock 
5                      error:(NSError**)error;
6
7- (*BOOL*) 
8        cleanResyncGhosts:(NSNumber*)syncId
9    completionStatusBlock:
10        (SFSyncSyncManagerCompletionStatusBlock)completionStatusBlock 
11                    error:(NSError**)error;
Android (Kotlin)
1suspend fun suspendCleanResyncGhosts(syncId: Long): Int
Android (Java)
1public void cleanResyncGhosts(final String syncName, final CleanResyncGhostsCallback callback)

Deprecations in Mobile SDK 7.1

Deprecated iOS Method (Objective-C)
The following method that does not support an NSError output parameter is slated for removal in a future major release.
1- (*BOOL*) 
2        cleanResyncGhosts:(NSNumber*)syncId
3    completionStatusBlock:
4        (SFSyncSyncManagerCompletionStatusBlock)completionStatusBlock;