Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

托管同步会话 — Swift SDK

在此页面上

  • 同步连接行为
  • 检查网络连接
  • 挂起或恢复同步会话
  • 何时暂停同步会话
  • 等待上传或下载更改
  • 检查同步会话的上传和下载进度
  • 手动重新连接所有同步会话

打开同步域会为该域启动 SyncSession 。 Realm Swift SDK提供了手动暂停和恢复同步会话的方法。

版本 10.41.0 中的新增内容

在 Realm Swift SDK 版本 10.41.0 及更高版本中,App Services 默认为所有打开的同步 Realm 共享与服务器的单个连接。 与早期版本相比,这是一项更改,在早期版本中,打开多个同步域会打开与服务器的额外连接。与服务器的连接独立于 SyncSession ,并且基于 App Services 用户。

您可以从应用程序客户端配置中更改此行为。

提示

Realm 的离线优先设计意味着您通常不需要检查当前的网络连接状态。 也就是说,如果您的应用程序需要某些连接状态指示,则connectionState属性可用。

要检查连接状态,可以直接读取同步 Realm 的 RLMSyncSession 实例的connectionState属性。

此属性 符合 KVO 标准 ,这样您就可以使用 KVO 观察更改。以下示例演示了如何实现观察者类:

@interface MySyncSessionObserver: NSObject
@end
@implementation MySyncSessionObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (![object isKindOfClass:RLMSyncSession.class]) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if (![keyPath isEqualToString:@"connectionState"]) {
// Not interested in observing this keypath
return;
}
RLMSyncSession *syncSession = (RLMSyncSession *)object;
RLMSyncConnectionState connectionState = [syncSession connectionState];
switch (connectionState) {
case RLMSyncConnectionStateConnecting:
NSLog(@"Connecting...");
break;
case RLMSyncConnectionStateConnected:
NSLog(@"Connected");
break;
case RLMSyncConnectionStateDisconnected:
NSLog(@"Disconnected");
break;
}
}
@end

然后,您可以将观察者实例附加到 RLMSyncSession对象。 请务必在完成后删除观察者。

// Observe connectionState for changes using KVO
MySyncSessionObserver *observer = [[MySyncSessionObserver alloc] init];
[syncSession addObserver:observer
forKeyPath:@"connectionState"
options:NSKeyValueObservingOptionInitial
context:nil];
// Later, when done...
[syncSession removeObserver:observer
forKeyPath:@"connectionState"
context:nil];

要检查连接状态,可以直接读取同步 Realm 的 SyncSession 实例的connectionState属性。

此属性 符合 KVO 标准 ,因此您可以使用 KVO 甚至组合来观察更改。

// Observe connectionState for changes using KVO
let observer = syncSession.observe(\.connectionState, options: [.initial]) { (syncSession, change) in
switch syncSession.connectionState {
case .connecting:
print("Connecting...")
case .connected:
print("Connected")
case .disconnected:
print("Disconnected")
default:
break
}
}
// Observe using Combine
let cancellable = syncSession.publisher(for: \.connectionState)
.sink { connectionState in
switch connectionState {
case .connecting:
print("Connecting...")
case .connected:
print("Connected")
case .disconnected:
print("Disconnected")
default:
break
}
}

您可以暂停和恢复 Realm 上的同步会话。 暂停同步会话只会暂停该 Realm 的同步会话。 如果您有多个打开 Realm,则暂停不会影响其他 Realm 的同步会话。

您可以使用已同步域的RLMSyncSession实例暂停或恢复同步会话。

RLMRealm *syncedRealm = [RLMRealm realmWithConfiguration:configuration error:nil];
RLMSyncSession *syncSession = [syncedRealm syncSession];
// Suspend synchronization
[syncSession suspend];
// Later, resume synchronization
[syncSession resume];

您可以使用同步 Realm 的SyncSession实例暂停或恢复同步会话。

let syncSession = syncedRealm.syncSession!
// Suspend synchronization
syncSession.suspend()
// Later, resume synchronization
syncSession.resume()

对于大多数应用程序,无需手动暂停和恢复同步会话。 但是,在某些情况下,您可能希望暂停或暂停同步会话:

  • 您只想在用户执行特定操作后进行同步

  • 您只想在一天中的特定时间进行同步

  • 您不想在网络连接较差时尝试同步

  • 您想要显式强制同步会话连接

在网络连接较差的情况下,不断尝试建立网络连接可能会耗尽用户的设备电池。

显式强制同步会话连接的情况最常见与离线一段时间有关。同步客户端尝试连接,一旦失败,就会Go指数退避状态。长时间离线后,客户端可能无法立即重新连接。 暂停和恢复同步会话会显式强制连接。

当您暂停同步会话时,请记住以下事项:

  • 如果客户端离线时间可能超过客户端最长离线时间,则客户端将无法恢复同步,必须执行客户端重置。

  • 暂停同步会话会使其在两个方向上暂停。您的应用在设备上所做的更改不会与后端同步,对后端或其他设备上的数据更改也不会同步到设备。 无法仅暂停上传或仅暂停下载。

  • 如果您希望客户端永久停止与后端同步,请勿暂停同步会话。 要永久停止同步,请将同步 Realm 的内容复制到非同步 Realm,并在客户端中使用该非同步 Realm。

请勿在不确定的时间段或以月和年为单位的时间范围内通过暂停同步来停止同步。 该功能不是针对这些使用案例而设计或测试的。 以这种方式使用时,您可能会遇到一系列问题。

版本 10.45.0 中的新增内容

要等待从同步域上传或下载所有更改,请调用域.syncSession?.wait(for: )。

此方法采用ProgressDirection参数来指定是否追踪上传或下载进度。

您可以将这些方法与 Swift 的异步/等待语法或回调语法一起使用。 回调版本域.syncSession?.wait(for:queue: 区块:)可以采用一个队列来调度回调,以及一个在等待完成时调用的区块。

// Wait to download all pending changes from Atlas
try await realm.syncSession?.wait(for: .download)
// Add data locally
try realm.write {
realm.create(Task.self, value: [
"taskName": "Review proposal",
"assignee": "Emma",
"completed": false,
"progressMinutes": 0,
"dueDate": date
])
}
// Wait for local changes to be uploaded to Atlas
try await realm.syncSession?.wait(for: .upload)
// Wait to download all pending changes from Atlas
realm.syncSession?.wait(for: .download, block: { _ in
// You can provide a block to execute
// after waiting for download to complete
})
// Add data locally
do {
try realm.write {
realm.create(Task.self, value: [
"taskName": "Review proposal",
"assignee": "Emma",
"completed": false,
"progressMinutes": 0,
"dueDate": date
])
}
} catch {
print("There was an error writing to realm: \(error.localizedDescription)")
}
// Wait for local changes to be uploaded to Atlas
realm.syncSession?.wait(for: .upload, block: { _ in
// You can provide a block to execute after
// waiting for upload to complete
})

在版本10.50.0中进行了更改: 已弃用transferredBytestransferrableBytes ,改用progressEstimate

您可以通过注册令牌来检查上传和下载进度,该令牌为给定的上传或下载方向和工作范围提供progressEstimate 。 您可以设立ProgressMode来确定工作范围:无限期观察或在当前工作项完成后取消注册区块。

令牌提供的 progressEstimate 值是double精度值,其值范围从 0.01.0。 在1.0处,上传或下载已完成。 您可以使用此progressEstimate来显示进度指示器或估计的数据传输百分比。

在版本10.50.0中进行了更改: 已弃用addProgressNotificationForDirection ,取而代之的是addSyncProgressNotificationForDirection

您可以使用同步 Realm 的 RLMSyncSession 实例的[--addSyncProgressNotificationForDirection:mode:block:]方法添加进度通知。

此方法会返回一个令牌,您应保留该令牌,直到您希望停止观察上传或下载进度。 请注意,如果将令牌保留在局部变量中,则当局部变量Go作用域时,观察将停止。

RLMSyncSession *syncSession = [syncedRealm syncSession];
RLMProgressNotificationToken *token = [syncSession
addSyncProgressNotificationForDirection:RLMSyncProgressDirectionUpload
mode:RLMSyncProgressModeForCurrentlyOutstandingWork
block:^(RLMSyncProgress syncProgress) {
NSLog(@"Uploaded %fB", (double)syncProgress.progressEstimate);
}];
// Upload something
[syncedRealm transactionWithBlock:^{
[syncedRealm addObject:[[Task alloc] init]];
}];

您可以使用同步 Realm 的 SyncSession 实例的addProgressNotification(for:mode:block:)方法添加进度通知。

此方法会返回一个令牌,您应保留该令牌,直到您希望停止观察上传或下载进度。 请注意,如果将令牌保留在局部变量中,则当局部变量Go作用域时,观察将停止。

let syncSession = realm.syncSession!
let token = syncSession.addProgressNotification(
for: .upload, mode: .forCurrentlyOutstandingWork) { (progress) in
let progressEstimate = progress.progressEstimate
let transferPercent = progressEstimate * 100
print("Uploaded (\(transferPercent)%)")
}

版本 10.44.0 中的新增内容

Realm 会自动检测设备何时在离线后重新获得连接,并尝试使用增量退避策略重新连接。 例如,在 Apple 平台上,Realm 会侦听网络变更通知,并在收到通知后立即自动Atlas Triggers重新连接。

在 Swift SDK 版本 10.44.0 及更高版本中,您可以选择使用SyncSession.reconnect()手动trigger重新连接尝试,而不是等待增量退避持续时间。如果您对网络状况有更准确的了解并且不想依赖 Realm 的自动重新连接检测,这非常有用。

let syncSession = realm.syncSession!
// Work with the realm. When you need to force the sync session to reconnect...
syncSession.reconnect()

调用此方法时,SDK 会强制所有同步会话立即尝试重新连接。 这会重置用于增量退避的所有计时器。

调用此方法并不能保证设备可以重新连接。 如果 SDK 出现致命错误,或者设备已连接或正在尝试连接,则调用此方法无效。

重要

无法在套接字读取超时时间内重新连接

Realm 的内部默认套接字读取超时为 2 分钟,如果读取操作在 2 分钟窗口内未收到任何数据,Realm 将超时。 如果您在该窗口内调用SyncSession.reconnect() ,Swift SDK不会尝试重新连接。

后退

在后台同步数据