Skip to content

Commit

Permalink
Add support for fetching Realm
Browse files Browse the repository at this point in the history
Changes:
- Session handles can now wait for uploads/downloads to complete
- Added API to fetch a Realm and expose it to the user upon download completion
- Fix Xcode project target membership for certain Sync source files
- Fix a threading bug
- Changed the `standaloneSession` BOOL argument some internal methods took into a `purpose` enum to more clearly distinguish between fetching Realms, opening Realms, and getting a standalone session
  • Loading branch information
austinzheng committed Sep 29, 2016
1 parent b7f61f8 commit cc1d666
Show file tree
Hide file tree
Showing 18 changed files with 358 additions and 77 deletions.
11 changes: 11 additions & 0 deletions Realm.xcodeproj/project.pbxproj
Expand Up @@ -86,6 +86,7 @@
1A58C0AC1D88AF9C001589D9 /* RLMSyncSessionHandle.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1A58C0A71D88AF84001589D9 /* RLMSyncSessionHandle.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
1A64CA8B1D8763B400BC0F9B /* keychain_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A64CA891D8763B400BC0F9B /* keychain_helper.cpp */; };
1A64CA8C1D8763B400BC0F9B /* keychain_helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1A64CA8A1D8763B400BC0F9B /* keychain_helper.hpp */; };
1A6660221D91BA1800BEF2A3 /* RLMSyncUser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDCDAF1D793008003489E3 /* RLMSyncUser.mm */; };
1A6921D31D779774004C3232 /* RLMTokenModels.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A6921D11D779774004C3232 /* RLMTokenModels.h */; settings = {ATTRIBUTES = (Private, ); }; };
1A6921D41D779774004C3232 /* RLMTokenModels.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A6921D21D779774004C3232 /* RLMTokenModels.m */; };
1A7003081D5270C400FD9EE3 /* RLMSyncSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AD3870B1D4A7FBB00479110 /* RLMSyncSession.mm */; };
Expand Down Expand Up @@ -125,6 +126,8 @@
1ABDCDB01D793008003489E3 /* RLMSyncUser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDCDAF1D793008003489E3 /* RLMSyncUser.mm */; };
1ABDCDB11D793012003489E3 /* RLMSyncUser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABDCDAD1D792FEB003489E3 /* RLMSyncUser.h */; settings = {ATTRIBUTES = (Public, ); }; };
1ABDCDB21D7931F3003489E3 /* RLMTokenModels.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A6921D11D779774004C3232 /* RLMTokenModels.h */; settings = {ATTRIBUTES = (Private, ); }; };
1ABE87DF1D8CBB0A00B3F283 /* RLMSyncUser_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABE87DE1D8CBAAA00B3F283 /* RLMSyncUser_Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
1ABE87E01D8CBB0A00B3F283 /* RLMSyncUser_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABE87DE1D8CBAAA00B3F283 /* RLMSyncUser_Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
1ABF256F1D52AB6200BAC441 /* RLMRealmConfiguration+Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABF256D1D52AB6200BAC441 /* RLMRealmConfiguration+Sync.h */; settings = {ATTRIBUTES = (Public, ); }; };
1ABF25701D52AB6200BAC441 /* RLMRealmConfiguration+Sync.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ABF256E1D52AB6200BAC441 /* RLMRealmConfiguration+Sync.mm */; };
1AD3870C1D4A7FBB00479110 /* RLMSyncSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AD3870A1D4A7FBB00479110 /* RLMSyncSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -666,6 +669,7 @@
1ABDCDA91D790AD0003489E3 /* RLMSyncFileManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RLMSyncFileManager.mm; sourceTree = "<group>"; };
1ABDCDAD1D792FEB003489E3 /* RLMSyncUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLMSyncUser.h; sourceTree = "<group>"; };
1ABDCDAF1D793008003489E3 /* RLMSyncUser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RLMSyncUser.mm; sourceTree = "<group>"; };
1ABE87DE1D8CBAAA00B3F283 /* RLMSyncUser_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RLMSyncUser_Private.h; sourceTree = "<group>"; };
1ABF256A1D528B9900BAC441 /* RLMSyncSession_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RLMSyncSession_Private.h; sourceTree = "<group>"; };
1ABF256D1D52AB6200BAC441 /* RLMRealmConfiguration+Sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RLMRealmConfiguration+Sync.h"; sourceTree = "<group>"; };
1ABF256E1D52AB6200BAC441 /* RLMRealmConfiguration+Sync.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "RLMRealmConfiguration+Sync.mm"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1048,6 +1052,7 @@
1ABF256A1D528B9900BAC441 /* RLMSyncSession_Private.h */,
1AD3870B1D4A7FBB00479110 /* RLMSyncSession.mm */,
1ABDCDAD1D792FEB003489E3 /* RLMSyncUser.h */,
1ABE87DE1D8CBAAA00B3F283 /* RLMSyncUser_Private.h */,
1A8413351D4C0B5B00C5326F /* RLMSyncUser_Private.hpp */,
1ABDCDAF1D793008003489E3 /* RLMSyncUser.mm */,
1A4FFC971D35A71000B4B65C /* RLMSyncUtil.h */,
Expand Down Expand Up @@ -1503,6 +1508,7 @@
1AF6EA471D36B1850014EB85 /* RLMAuthResponseModel.h in Headers */,
5D274C531D6D16BA006FEBB1 /* event_loop_signal.hpp in Headers */,
5D659EAF1BE04556006515A0 /* RLMMigration.h in Headers */,
1ABE87DF1D8CBB0A00B3F283 /* RLMSyncUser_Private.h in Headers */,
5D659EB01BE04556006515A0 /* RLMMigration_Private.h in Headers */,
5D659EB11BE04556006515A0 /* RLMObject.h in Headers */,
5D659EB21BE04556006515A0 /* RLMObject_Private.h in Headers */,
Expand Down Expand Up @@ -1620,6 +1626,7 @@
5DD755C11BE056DE002800DA /* RLMRealmConfiguration_Private.h in Headers */,
E86900E31CC04F5B0008A8B6 /* RLMRealmConfiguration_Private.hpp in Headers */,
5DD755C21BE056DE002800DA /* RLMRealmUtil.hpp in Headers */,
1ABE87E01D8CBB0A00B3F283 /* RLMSyncUser_Private.h in Headers */,
5DD755C31BE056DE002800DA /* RLMResults.h in Headers */,
5DD755C41BE056DE002800DA /* RLMResults_Private.h in Headers */,
5DD755C51BE056DE002800DA /* RLMSchema.h in Headers */,
Expand Down Expand Up @@ -2271,13 +2278,15 @@
3F75566D1BE94CEA0058BC7E /* results.cpp in Sources */,
17051FD01D93E0CC00EF8E67 /* RLMSyncCredential.m in Sources */,
3F9801B11C90FD31000A8B07 /* results_notifier.cpp in Sources */,
1AB7E5BC1D91F01F00917223 /* RLMSyncFileManager.mm in Sources */,
5DD755831BE056DE002800DA /* RLMAccessor.mm in Sources */,
17051FCE1D93DA0A00EF8E67 /* RLMSyncUser.mm in Sources */,
5DD755841BE056DE002800DA /* RLMAnalytics.mm in Sources */,
5DD755851BE056DE002800DA /* RLMArray.mm in Sources */,
5DD755861BE056DE002800DA /* RLMArrayLinkView.mm in Sources */,
3F9863BC1D36876B00641C98 /* RLMClassInfo.mm in Sources */,
3FBEF67C1C63D66400F6935B /* RLMCollection.mm in Sources */,
1A6660221D91BA1800BEF2A3 /* RLMSyncUser.mm in Sources */,
5DD755871BE056DE002800DA /* RLMConstants.m in Sources */,
5DD755881BE056DE002800DA /* RLMListBase.mm in Sources */,
1A70030A1D5270CF00FD9EE3 /* RLMAuthResponseModel.m in Sources */,
Expand All @@ -2302,12 +2311,14 @@
5DD755961BE056DE002800DA /* RLMSchema.mm in Sources */,
1A0512721D873F3300806AEC /* RLMSyncConfiguration.mm in Sources */,
1A90FCBB1D3D37F50086A57F /* RLMSyncManager.mm in Sources */,
1AB7E5BD1D91F02600917223 /* RLMTokenModels.m in Sources */,
1A90FCBC1D3D37F70086A57F /* RLMNetworkClient.m in Sources */,
1A7003091D5270C700FD9EE3 /* RLMSyncUtil.mm in Sources */,
1A7003081D5270C400FD9EE3 /* RLMSyncSession.mm in Sources */,
E8FD2E391D93345100569F10 /* sync_metadata.cpp in Sources */,
5DD755971BE056DE002800DA /* RLMSwiftSupport.m in Sources */,
5DD755981BE056DE002800DA /* RLMUpdateChecker.mm in Sources */,
1AB7E5BB1D91F00D00917223 /* RLMSyncCredential.m in Sources */,
5DD755991BE056DE002800DA /* RLMUtil.mm in Sources */,
5DD7559A1BE056DE002800DA /* schema.cpp in Sources */,
5DD7559B1BE056DE002800DA /* shared_realm.cpp in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Realm/ObjectStore
2 changes: 1 addition & 1 deletion Realm/RLMRealmConfiguration+Sync.mm
Expand Up @@ -20,7 +20,7 @@

#import "RLMRealmConfiguration_Private.hpp"
#import "RLMSyncConfiguration_Private.hpp"
#import "RLMSyncUser_Private.hpp"
#import "RLMSyncUser_Private.h"
#import "RLMSyncFileManager.h"
#import "RLMSyncManager_Private.hpp"
#import "RLMSyncUtil_Private.hpp"
Expand Down
3 changes: 3 additions & 0 deletions Realm/RLMSyncFileManager.h
Expand Up @@ -28,6 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSURL *)fileURLForMetadata;
+ (BOOL)removeFilesForUserIdentity:(NSString *)identity error:(NSError * _Nullable* _Nullable)error;

/// Delete a Realm file and all associated state. Specify the path of the primary file (the Realm file itself).
+ (BOOL)deleteRealmAtPath:(NSURL *)realmPath;

NS_ASSUME_NONNULL_END

@end
25 changes: 25 additions & 0 deletions Realm/RLMSyncFileManager.mm
Expand Up @@ -24,6 +24,12 @@
static NSString *const RLMSyncUtilityFolderName = @"io.realm.object-server-metadata";
static NSString *const RLMSyncMetadataRealmName = @"sync_metadata.realm";

/// Given an `NSError` outputted from a call to `removeItemAtURL:error:`, return whether or not we should consider the
/// file deletion a success.
static BOOL fileDeletionSucceeded(NSError * _Nullable error) {
return !error || (error.domain == NSCocoaErrorDomain && error.code == NSFileNoSuchFileError);
}

@implementation RLMSyncFileManager

/**
Expand Down Expand Up @@ -115,4 +121,23 @@ + (BOOL)removeFilesForUserIdentity:(NSString *)identity error:(NSError **)error
return [manager removeItemAtURL:userDir error:error];
}

+ (BOOL)deleteRealmAtPath:(NSURL *)realmPath {
BOOL success = YES;
NSFileManager *manager = [NSFileManager defaultManager];
// Delete the primary Realm file.
NSError *error = nil;
[manager removeItemAtURL:realmPath error:&error];
success = success && fileDeletionSucceeded(error);
// Delete the lock file.
error = nil;
NSURL *lockURL = [realmPath URLByAppendingPathExtension:@"lock"];
[manager removeItemAtURL:lockURL error:&error];
success = success && fileDeletionSucceeded(error);
// Delete the management directory.
NSURL *managementURL = [realmPath URLByAppendingPathExtension:@"management"];
[manager removeItemAtURL:managementURL error:nil];
success = success && fileDeletionSucceeded(error);
return success;
}

@end
12 changes: 12 additions & 0 deletions Realm/RLMSyncManager.h
Expand Up @@ -22,6 +22,9 @@

@class RLMSyncSession, RLMSyncConfiguration;

/// A block type allowing an API to vend a sync session asynchronously.
typedef void(^RLMSyncSessionCompletionBlock)(NSError * _Nullable, RLMSyncSession * _Nullable);

/// An enum representing different levels of sync-related logging that can be configured.
typedef NS_ENUM(NSUInteger, RLMSyncLogLevel) {
/// Nothing will ever be logged.
Expand Down Expand Up @@ -91,6 +94,15 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable)
/// The sole instance of the singleton.
+ (instancetype)sharedManager;

/**
Given a sync configuration, open and return a standalone session.
If a standalone session was previously opened but encountered a fatal error, attempting to open an equivalent session
(by using the same configuration) will return `nil`.
*/
- (void)fetchSessionForSyncConfiguration:(RLMSyncConfiguration *)config
onCompletion:(nullable RLMSyncSessionCompletionBlock)completion;

/// :nodoc:
- (instancetype)init __attribute__((unavailable("RLMSyncManager cannot be created directly")));

Expand Down
49 changes: 43 additions & 6 deletions Realm/RLMSyncManager.mm
Expand Up @@ -87,12 +87,22 @@ + (instancetype)sharedManager {
return s_sharedManager;
}

- (RLMSyncSession *)sessionForSyncConfiguration:(RLMSyncConfiguration *)config {
- (void)fetchSessionForSyncConfiguration:(RLMSyncConfiguration *)config
onCompletion:(nullable RLMSyncSessionCompletionBlock)completion {
NSURL *fileURL = [RLMSyncFileManager fileURLForRawRealmURL:config.realmURL user:config.user];
return [config.user _registerSessionForBindingWithFileURL:fileURL
syncConfig:config
standaloneSession:YES
onCompletion:nil];
[config.user _registerSessionForBindingWithFileURL:fileURL
syncConfig:config
purpose:RLMSyncSessionPurposeStandalone
onCompletion:completion];
}

- (void)_fetchSessionForFetchingRealm:(RLMSyncConfiguration *)config
onCompletion:(RLMSyncSessionCompletionBlock)completion {
NSURL *fileURL = [RLMSyncFileManager fileURLForRawRealmURL:config.realmURL user:config.user];
[config.user _registerSessionForBindingWithFileURL:fileURL
syncConfig:config
purpose:RLMSyncSessionPurposeFetchRealm
onCompletion:completion];
}

- (instancetype)initPrivate {
Expand Down Expand Up @@ -128,6 +138,7 @@ - (instancetype)initPrivate {
NSString *metadataDirectory = [[RLMSyncFileManager fileURLForMetadata] path];
bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION");
_metadata_manager = std::make_unique<SyncMetadataManager>([metadataDirectory UTF8String], should_encrypt);
[self _performFileActions];
[self _cleanUpMarkedUsers];
[self _loadPersistedUsers];
return self;
Expand Down Expand Up @@ -260,6 +271,32 @@ - (void)_cleanUpMarkedUsers {
}
}

- (void)_performFileActions {
@synchronized (self) {
std::vector<SyncFileActionMetadata> remove_queue;
// Get and execute the outstanding tasks.
SyncFileActionMetadataResults outstanding = _metadata_manager->all_file_actions();
for (size_t i=0; i<outstanding.size(); i++) {
SyncFileActionMetadata task = outstanding.get(i);
switch (task.action()) {
case SyncFileActionMetadata::Action::DeleteRealmFiles: {
NSURL *realmURL = [NSURL fileURLWithPath:@(task.current_path().c_str())];
if ([RLMSyncFileManager deleteRealmAtPath:realmURL]) {
remove_queue.emplace_back(std::move(task));
}
break;
}
case SyncFileActionMetadata::Action::MoveRealmFiles:
// FIXME: implement this once we need it
break;
}
}
for (auto task : remove_queue) {
task.remove();
}
}
}

- (void)_handleBindRequestForSyncConfig:(RLMSyncConfiguration *)syncConfig
localFilePath:(NSString *)filePathString {
@synchronized(self) {
Expand All @@ -272,7 +309,7 @@ - (void)_handleBindRequestForSyncConfig:(RLMSyncConfiguration *)syncConfig
// FIXME: should the completion block actually do anything?
[user _registerSessionForBindingWithFileURL:[NSURL fileURLWithPath:filePathString]
syncConfig:syncConfig
standaloneSession:NO
purpose:RLMSyncSessionPurposeOpenRealm
onCompletion:self.sessionCompletionNotifier];
}
}
Expand Down
5 changes: 4 additions & 1 deletion Realm/RLMSyncManager_Private.hpp
Expand Up @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
std::unique_ptr<realm::SyncMetadataManager> _metadata_manager;
}

@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock sessionCompletionNotifier;
@property (nullable, nonatomic, copy) RLMSyncSessionCompletionBlock sessionCompletionNotifier;

/**
Given a sync configuration, open and return a standalone session.
Expand All @@ -59,6 +59,9 @@ NS_ASSUME_NONNULL_BEGIN

- (NSArray<RLMSyncUser *> *)_allUsers;

- (void)_fetchSessionForFetchingRealm:(RLMSyncConfiguration *)config
onCompletion:(RLMSyncSessionCompletionBlock)completion;

/**
Register a user. If an equivalent user has already been registered, the argument is not added to the store, and the
existing user is returned. Otherwise, the argument is added to the store and `nil` is returned.
Expand Down
21 changes: 14 additions & 7 deletions Realm/RLMSyncSession.mm
Expand Up @@ -23,24 +23,26 @@
#import "RLMRealmConfiguration+Sync.h"
#import "RLMSyncConfiguration.h"
#import "RLMSyncManager_Private.hpp"
#import "RLMSyncSession_Private.h"
#import "RLMSyncSessionHandle.hpp"
#import "RLMSyncUser_Private.hpp"
#import "RLMSyncUser_Private.h"
#import "RLMSyncUtil.h"
#import "RLMTokenModels.h"
#import "RLMUtil.hpp"

#import "sync_manager.hpp"
#import "sync_metadata.hpp"

@implementation RLMSessionBindingPackage

- (instancetype)initWithFileURL:(NSURL *)fileURL
syncConfig:(RLMSyncConfiguration *)syncConfig
standalone:(BOOL)isStandalone
block:(RLMSyncBasicErrorReportingBlock)block {
purpose:(RLMSyncSessionPurpose)purpose
block:(RLMSyncSessionCompletionBlock)block {
if (self = [super init]) {
self.fileURL = fileURL;
self.syncConfig = syncConfig;
self.isStandalone = isStandalone;
self.purpose = purpose;
self.block = block;
return self;
}
Expand All @@ -55,8 +57,6 @@ @interface RLMSyncSession ()
@property (nonatomic, readwrite) RLMSyncUser *parentUser;
@property (nonatomic, readwrite) NSURL *realmURL;

@property (nullable, nonatomic) RLMSyncSessionHandle *sessionHandle;

@end

@implementation RLMSyncSession
Expand Down Expand Up @@ -95,6 +95,12 @@ - (void)_invalidate {
self.parentUser = nil;
}

- (void)_markFilesForDeletion {
realm::SyncFileActionMetadata file_action_metadata([[RLMSyncManager sharedManager] _metadataManager],
realm::SyncFileActionMetadata::Action::DeleteRealmFiles,
[[self.fileURL path] UTF8String]);
}

#pragma mark - per-Realm access token API

- (void)configureWithAccessToken:(RLMServerToken)token
Expand Down Expand Up @@ -160,8 +166,9 @@ - (void)_refresh {
self.accessToken = model.accessToken.token;
self.accessTokenExpiry = tokenModel.tokenData.expires;
[self _scheduleRefreshTimer];
NSString *accessToken = tokenModel.token;

[self refreshAccessToken:tokenModel.token serverURL:nil];
[self refreshAccessToken:accessToken serverURL:nil];
}
} else {
// Something else went wrong
Expand Down
14 changes: 10 additions & 4 deletions Realm/RLMSyncSession_Private.h
Expand Up @@ -19,6 +19,8 @@
#import "RLMSyncSession.h"

#import "RLMSyncConfiguration.h"
#import "RLMSyncManager.h"
#import "RLMSyncUser_Private.h"
#import "RLMSyncUtil_Private.h"

@class RLMSyncUser, RLMSyncSessionHandle;
Expand All @@ -27,15 +29,15 @@

NS_ASSUME_NONNULL_BEGIN

@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock block;
@property (nullable, nonatomic, copy) RLMSyncSessionCompletionBlock block;
@property (nonatomic) NSURL *fileURL;
@property (nonatomic) RLMSyncConfiguration *syncConfig;
@property (nonatomic) BOOL isStandalone;
@property (nonatomic) RLMSyncSessionPurpose purpose;

- (instancetype)initWithFileURL:(NSURL *)fileURL
syncConfig:(RLMSyncConfiguration *)syncConfig
standalone:(BOOL)isStandalone
block:(nullable RLMSyncBasicErrorReportingBlock)block;
purpose:(RLMSyncSessionPurpose)purpose
block:(nullable RLMSyncSessionCompletionBlock)block;

@end

Expand All @@ -45,8 +47,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)_logOut;
- (void)_invalidate;

- (void)_markFilesForDeletion;

- (void)setState:(RLMSyncSessionState)state;

@property (nullable, nonatomic) RLMSyncSessionHandle *sessionHandle;

/// The path on disk where the Realm file backing this synced Realm is stored.
@property (nonatomic) NSURL *fileURL;

Expand Down
10 changes: 10 additions & 0 deletions Realm/RLMSyncUser.h
Expand Up @@ -35,6 +35,9 @@ typedef NS_ENUM(NSUInteger, RLMSyncUserState) {
/// A block type used for APIs which asynchronously vend a `RLMSyncUser`.
typedef void(^RLMUserCompletionBlock)(RLMSyncUser * _Nullable, NSError * _Nullable);

/// A block type used for APIs which asynchronously vend a `RLMRealm`.
typedef BOOL(^RLMFetchedRealmCompletionBlock)(NSError * _Nullable, RLMRealm * _Nullable);

NS_ASSUME_NONNULL_BEGIN

/**
Expand Down Expand Up @@ -97,6 +100,13 @@ NS_SWIFT_UNAVAILABLE("Use the full version of this API.");

/**
Retrieve a valid session object belonging to this user for a given URL, or `nil` if no such object exists.
Fetch a remote Realm and download pending changes before exposing it within a completion block.
*/
- (void)getRealmForURL:(NSURL *)realmURL
onCompletion:(RLMFetchedRealmCompletionBlock)completion NS_SWIFT_UNAVAILABLE("Use getRealm(at:completion:)");

/**
Retrieve a valid session object for a given URL, or `nil` if no such object exists.
*/
- (nullable RLMSyncSession *)sessionForURL:(NSURL *)url;

Expand Down

0 comments on commit cc1d666

Please sign in to comment.