Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
SRCT
whats-open-ios
Commits
23c1cdb1
Unverified
Commit
23c1cdb1
authored
Jan 24, 2019
by
Zach Knox
Browse files
notifications work—still work to do but it's progress
also updated pods
parent
fa006df2
Changes
246
Show whitespace changes
Inline
Side-by-side
WhatsOpen/Pods/Realm/Realm/RLMRealm+Sync.mm
View file @
23c1cdb1
...
...
@@ -19,6 +19,7 @@
#import "RLMRealm+Sync.h"
#import "RLMObjectBase.h"
#import "RLMQueryUtil.hpp"
#import "RLMObjectSchema.h"
#import "RLMRealm_Private.hpp"
#import "RLMResults_Private.hpp"
...
...
@@ -26,30 +27,56 @@
#import "RLMSyncSession.h"
#import "results.hpp"
#import "sync/partial_sync.hpp"
#import "shared_realm.hpp"
#import "sync/partial_sync.hpp"
#import "sync/subscription_state.hpp"
using
namespace
realm
;
@implementation
RLMRealm
(
Sync
)
-
(
void
)
subscribeToObjects
:(
Class
)
type
where
:(
NSString
*
)
query
callback
:(
RLMPartialSyncFetchCallback
)
callback
{
NSString
*
className
=
[
type
className
];
auto
cb
=
[
=
](
Results
results
,
std
::
exception_ptr
err
)
{
if
(
err
)
{
[
self
verifyThread
];
RLMClassInfo
&
info
=
_info
[[
type
className
]];
Query
q
=
RLMPredicateToQuery
([
NSPredicate
predicateWithFormat
:
query
],
info
.
rlmObjectSchema
,
self
.
schema
,
self
.
group
);
struct
Holder
{
partial_sync
::
Subscription
subscription
;
partial_sync
::
SubscriptionNotificationToken
token
;
Holder
(
partial_sync
::
Subscription
&&
s
)
:
subscription
(
std
::
move
(
s
))
{
}
};
auto
state
=
std
::
make_shared
<
Holder
>
(
partial_sync
::
subscribe
(
Results
(
_realm
,
std
::
move
(
q
)),
util
::
none
));
state
->
token
=
state
->
subscription
.
add_notification_callback
([
=
]()
mutable
{
if
(
!
callback
)
{
return
;
}
switch
(
state
->
subscription
.
state
())
{
case
partial_sync
::
SubscriptionState
::
Invalidated
:
case
partial_sync
::
SubscriptionState
::
Pending
:
case
partial_sync
::
SubscriptionState
::
Creating
:
return
;
case
partial_sync
::
SubscriptionState
::
Error
:
try
{
rethrow_exception
(
err
);
rethrow_exception
(
state
->
subscription
.
error
()
);
}
catch
(...)
{
NSError
*
error
=
nil
;
RLMRealmTranslateException
(
&
error
);
callback
(
nil
,
error
);
}
return
;
break
;
case
partial_sync
::
SubscriptionState
::
Complete
:
callback
([
RLMResults
emptyDetachedResults
],
nil
);
break
;
}
callback
([
RLMResults
resultsWithObjectInfo
:
_info
[
className
]
results
:
std
::
move
(
results
)],
nil
);
};
partial_sync
::
register_query
(
_realm
,
className
.
UTF8String
,
query
.
UTF8String
,
std
::
move
(
cb
));
callback
=
nil
;
state
->
token
=
{};
});
}
-
(
RLMSyncSession
*
)
syncSession
{
...
...
WhatsOpen/Pods/Realm/Realm/RLMRealm.mm
View file @
23c1cdb1
...
...
@@ -460,6 +460,10 @@ REALM_NOINLINE static void translateSharedGroupOpenException(RLMRealmConfigurati
if
(
!
readOnly
)
{
// initializing the schema started a read transaction, so end it
[
realm
invalidate
];
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".management"
);
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".lock"
);
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".note"
);
}
}
...
...
@@ -470,10 +474,6 @@ REALM_NOINLINE static void translateSharedGroupOpenException(RLMRealmConfigurati
if
(
!
readOnly
)
{
realm
->
_realm
->
m_binding_context
=
RLMCreateBindingContext
(
realm
);
realm
->
_realm
->
m_binding_context
->
realm
=
realm
->
_realm
;
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".management"
);
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".lock"
);
RLMAddSkipBackupAttributeToItemAtPath
(
config
.
path
+
".note"
);
}
return
RLMAutorelease
(
realm
);
...
...
WhatsOpen/Pods/Realm/Realm/RLMResults.mm
View file @
23c1cdb1
...
...
@@ -111,19 +111,29 @@ void RLMThrowResultsError(NSString *aggregateMethod) {
}
}
-
(
instancetype
)
initWithObjectInfo
:(
RLMClassInfo
&
)
info
results
:(
realm
::
Results
&&
)
results
{
if
(
self
=
[
super
init
])
{
_results
=
std
::
move
(
results
);
_realm
=
info
.
realm
;
_info
=
&
info
;
}
return
self
;
}
+
(
instancetype
)
resultsWithObjectInfo
:(
RLMClassInfo
&
)
info
results
:(
realm
::
Results
)
results
{
RLMResults
*
ar
=
[[
self
alloc
]
initPrivate
];
ar
->
_results
=
std
::
move
(
results
);
ar
->
_realm
=
info
.
realm
;
ar
->
_info
=
&
info
;
return
ar
;
results
:(
realm
::
Results
&&
)
results
{
return
[[
self
alloc
]
initWithObjectInfo
:
info
results
:
std
::
move
(
results
)];
}
+
(
instancetype
)
emptyDetachedResults
{
return
[[
self
alloc
]
initPrivate
];
}
-
(
instancetype
)
subresultsWithResults
:(
realm
::
Results
)
results
{
return
[
self
.
class
resultsWithObjectInfo
:
*
_info
results
:
std
::
move
(
results
)];
}
static
inline
void
RLMResultsValidateInWriteTransaction
(
__unsafe_unretained
RLMResults
*
const
ar
)
{
ar
->
_realm
->
_realm
->
verify_thread
();
ar
->
_realm
->
_realm
->
verify_in_write
();
...
...
@@ -349,7 +359,7 @@ static inline void RLMResultsValidateInWriteTransaction(__unsafe_unretained RLMR
@throw
RLMException
(
@"Querying is currently only implemented for arrays of Realm Objects"
);
}
auto
query
=
RLMPredicateToQuery
(
predicate
,
_info
->
rlmObjectSchema
,
_realm
.
schema
,
_realm
.
group
);
return
[
RLMResults
resultsWithObjectInfo
:
*
_info
r
esults
:
_results
.
filter
(
std
::
move
(
query
))];
return
[
self
subresultsWithR
esults
:
_results
.
filter
(
std
:
:
move
(
query
))];
});
}
...
...
@@ -365,8 +375,7 @@ static inline void RLMResultsValidateInWriteTransaction(__unsafe_unretained RLMR
if
(
_results
.
get_mode
()
==
Results
::
Mode
::
Empty
)
{
return
self
;
}
return
[
RLMResults
resultsWithObjectInfo
:
*
_info
results:
_results
.
sort
(
RLMSortDescriptorsToKeypathArray
(
properties
))];
return
[
self
subresultsWithResults
:
_results
.
sort
(
RLMSortDescriptorsToKeypathArray
(
properties
))];
});
}
...
...
@@ -387,7 +396,7 @@ static inline void RLMResultsValidateInWriteTransaction(__unsafe_unretained RLMR
keyPathsVector
.
push_back
(
keyPath
.
UTF8String
);
}
return
[
RLMResults
resultsWithObjectInfo
:
*
_info
r
esults
:
_results
.
distinct
(
keyPathsVector
)];
return
[
self
subresultsWithR
esults
:
_results
.
distinct
(
keyPathsVector
)];
});
}
...
...
WhatsOpen/Pods/Realm/Realm/RLMSyncConfiguration.mm
View file @
23c1cdb1
...
...
@@ -53,14 +53,11 @@ RLMSyncSystemErrorKind errorKindForSyncError(SyncError error) {
return
RLMSyncSystemErrorKindUnknown
;
}
}
}
static
BOOL
isValidRealmURL
(
NSURL
*
url
)
{
BOOL
isValidRealmURL
(
NSURL
*
url
)
{
NSString
*
scheme
=
[
url
scheme
];
if
(
!
[
scheme
isEqualToString
:
@"realm"
]
&&
!
[
scheme
isEqualToString
:
@"realms"
])
{
return
NO
;
}
return
YES
;
return
[
scheme
isEqualToString
:
@"realm"
]
||
[
scheme
isEqualToString
:
@"realms"
];
}
}
@interface
RLMSyncConfiguration
()
{
...
...
@@ -109,6 +106,28 @@ static BOOL isValidRealmURL(NSURL *url) {
_config
->
is_partial
=
(
bool
)
isPartial
;
}
-
(
NSURL
*
)
pinnedCertificateURL
{
if
(
auto
&
path
=
_config
->
ssl_trust_certificate_path
)
{
return
[
NSURL
fileURLWithPath
:
RLMStringDataToNSString
(
*
path
)];
}
return
nil
;
}
-
(
void
)
setPinnedCertificateURL
:(
NSURL
*
)
pinnedCertificateURL
{
if
(
pinnedCertificateURL
)
{
if
([
pinnedCertificateURL
respondsToSelector
:
@selector
(
UTF8String
)])
{
_config
->
ssl_trust_certificate_path
=
std
::
string
([(
id
)
pinnedCertificateURL
UTF8String
]);
}
else
{
_config
->
ssl_trust_certificate_path
=
std
::
string
(
pinnedCertificateURL
.
path
.
UTF8String
);
}
}
else
{
_config
->
ssl_trust_certificate_path
=
util
::
none
;
}
}
-
(
BOOL
)
isPartial
{
return
(
BOOL
)
_config
->
is_partial
;
}
...
...
@@ -171,7 +190,8 @@ static BOOL isValidRealmURL(NSURL *url) {
isPartial
:(
BOOL
)
isPartial
urlPrefix
:(
NSString
*
)
urlPrefix
stopPolicy
:(
RLMSyncStopPolicy
)
stopPolicy
enableSSLValidation
:(
BOOL
)
enableSSLValidation
{
enableSSLValidation
:(
BOOL
)
enableSSLValidation
certificatePath
:(
nullable
NSURL
*
)
certificatePath
{
auto
config
=
[
self
initWithUser
:
user
realmURL:
url
customFileURL:
nil
...
...
@@ -180,6 +200,7 @@ static BOOL isValidRealmURL(NSURL *url) {
errorHandler:
nullptr
];
config
.
urlPrefix
=
urlPrefix
;
config
.
enableSSLValidation
=
enableSSLValidation
;
config
.
pinnedCertificateURL
=
certificatePath
;
return
config
;
}
...
...
WhatsOpen/Pods/Realm/Realm/RLMSyncManager.mm
View file @
23c1cdb1
...
...
@@ -29,6 +29,10 @@
#import "sync/sync_manager.hpp"
#import "sync/sync_session.hpp"
#if !defined(REALM_COCOA_VERSION)
#import "RLMVersion.h"
#endif
using
namespace
realm
;
using
Level
=
realm
::
util
::
Logger
::
Level
;
...
...
@@ -110,7 +114,13 @@ static RLMSyncManager *s_sharedManager = nil;
bool
should_encrypt
=
!
getenv
(
"REALM_DISABLE_METADATA_ENCRYPTION"
)
&&
!
RLMIsRunningInPlayground
();
auto
mode
=
should_encrypt
?
SyncManager
:
:
MetadataMode
::
Encryption
:
SyncManager
::
MetadataMode
::
NoEncryption
;
rootDirectory
=
rootDirectory
?:
[
NSURL
fileURLWithPath
:
RLMDefaultDirectoryForBundleIdentifier
(
nil
)];
SyncManager
::
shared
().
configure_file_system
(
rootDirectory
.
path
.
UTF8String
,
mode
,
none
,
true
);
@autoreleasepool
{
bool
isSwift
=
!!
NSClassFromString
(
@"RealmSwiftObjectUtil"
);
auto
userAgent
=
[[
NSMutableString
alloc
]
initWithFormat
:
@"Realm%@/%@"
,
isSwift
?
@"Swift"
:
@"ObjectiveC"
,
REALM_COCOA_VERSION
];
SyncManager
::
shared
().
configure
(
rootDirectory
.
path
.
UTF8String
,
mode
,
RLMStringDataWithNSString
(
userAgent
),
none
,
true
);
SyncManager
::
shared
().
set_user_agent
(
RLMStringDataWithNSString
(
self
.
appID
));
}
return
self
;
}
return
nil
;
...
...
@@ -123,6 +133,11 @@ static RLMSyncManager *s_sharedManager = nil;
return
_appID
;
}
-
(
void
)
setUserAgent
:(
NSString
*
)
userAgent
{
SyncManager
::
shared
().
set_user_agent
(
RLMStringDataWithNSString
(
userAgent
));
_userAgent
=
userAgent
;
}
#pragma mark - Passthrough properties
-
(
RLMSyncLogLevel
)
logLevel
{
...
...
@@ -206,6 +221,7 @@ static RLMSyncManager *s_sharedManager = nil;
RLMNetworkRequestOptions
*
options
=
[[
RLMNetworkRequestOptions
alloc
]
init
];
options
.
authorizationHeaderName
=
self
.
authorizationHeaderName
;
options
.
customHeaders
=
self
.
customRequestHeaders
;
options
.
pinnedCertificatePaths
=
self
.
pinnedCertificatePaths
;
return
options
;
}
...
...
WhatsOpen/Pods/Realm/Realm/RLMSyncSession.mm
View file @
23c1cdb1
...
...
@@ -80,6 +80,7 @@ using namespace realm;
@interface
RLMSyncSession
()
@property
(
class
,
nonatomic
,
readonly
)
dispatch_queue_t
notificationsQueue
;
@property
(
atomic
,
readwrite
)
RLMSyncConnectionState
connectionState
;
@end
@implementation
RLMSyncSession
...
...
@@ -93,9 +94,23 @@ using namespace realm;
return
queue
;
}
-
(
instancetype
)
initWithSyncSession
:(
std
::
shared_ptr
<
SyncSession
>
)
session
{
static
RLMSyncConnectionState
convertConnectionState
(
SyncSession
::
ConnectionState
state
)
{
switch
(
state
)
{
case
SyncSession
::
ConnectionState
::
Disconnected
:
return
RLMSyncConnectionStateDisconnected
;
case
SyncSession
::
ConnectionState
::
Connecting
:
return
RLMSyncConnectionStateConnecting
;
case
SyncSession
::
ConnectionState
::
Connected
:
return
RLMSyncConnectionStateConnected
;
}
}
-
(
instancetype
)
initWithSyncSession
:(
std
::
shared_ptr
<
SyncSession
>
const
&
)
session
{
if
(
self
=
[
super
init
])
{
_session
=
session
;
_connectionState
=
convertConnectionState
(
session
->
connection_state
());
// No need to save the token as RLMSyncSession always outlives the
// underlying SyncSession
session
->
register_connection_change_callback
([
=
](
auto
,
auto
newState
)
{
self
.
connectionState
=
convertConnectionState
(
newState
);
});
return
self
;
}
return
nil
;
...
...
@@ -103,10 +118,8 @@ using namespace realm;
-
(
RLMSyncConfiguration
*
)
configuration
{
if
(
auto
session
=
_session
.
lock
())
{
if
(
session
->
state
()
!=
SyncSession
::
PublicState
::
Error
)
{
return
[[
RLMSyncConfiguration
alloc
]
initWithRawConfig
:
session
->
config
()];
}
}
return
nil
;
}
...
...
@@ -121,10 +134,8 @@ using namespace realm;
-
(
RLMSyncUser
*
)
parentUser
{
if
(
auto
session
=
_session
.
lock
())
{
if
(
session
->
state
()
!=
SyncSession
::
PublicState
::
Error
)
{
return
[[
RLMSyncUser
alloc
]
initWithSyncUser
:
session
->
user
()];
}
}
return
nil
;
}
...
...
@@ -133,18 +144,25 @@ using namespace realm;
if
(
session
->
state
()
==
SyncSession
::
PublicState
::
Inactive
)
{
return
RLMSyncSessionStateInactive
;
}
if
(
session
->
state
()
!=
SyncSession
::
PublicState
::
Error
)
{
return
RLMSyncSessionStateActive
;
}
}
return
RLMSyncSessionStateInvalid
;
}
-
(
BOOL
)
waitForUploadCompletionOnQueue
:(
dispatch_queue_t
)
queue
callback
:(
void
(
^
)(
NSError
*
))
callback
{
-
(
void
)
suspend
{
if
(
auto
session
=
_session
.
lock
())
{
if
(
session
->
state
()
==
SyncSession
::
PublicState
::
Error
)
{
return
NO
;
session
->
log_out
();
}
}
-
(
void
)
resume
{
if
(
auto
session
=
_session
.
lock
())
{
session
->
revive_if_needed
();
}
}
-
(
BOOL
)
waitForUploadCompletionOnQueue
:(
dispatch_queue_t
)
queue
callback
:(
void
(
^
)(
NSError
*
))
callback
{
if
(
auto
session
=
_session
.
lock
())
{
queue
=
queue
?:
dispatch_get_main_queue
();
session
->
wait_for_upload_completion
([
=
](
std
::
error_code
err
)
{
NSError
*
error
=
(
err
==
std
::
error_code
{})
?
nil
:
make_sync_error
(
err
);
...
...
@@ -159,9 +177,6 @@ using namespace realm;
-
(
BOOL
)
waitForDownloadCompletionOnQueue
:(
dispatch_queue_t
)
queue
callback
:(
void
(
^
)(
NSError
*
))
callback
{
if
(
auto
session
=
_session
.
lock
())
{
if
(
session
->
state
()
==
SyncSession
::
PublicState
::
Error
)
{
return
NO
;
}
queue
=
queue
?:
dispatch_get_main_queue
();
session
->
wait_for_download_completion
([
=
](
std
::
error_code
err
)
{
NSError
*
error
=
(
err
==
std
::
error_code
{})
?
nil
:
make_sync_error
(
err
);
...
...
@@ -178,9 +193,6 @@ using namespace realm;
mode
:(
RLMSyncProgressMode
)
mode
block
:(
RLMProgressNotificationBlock
)
block
{
if
(
auto
session
=
_session
.
lock
())
{
if
(
session
->
state
()
==
SyncSession
::
PublicState
::
Error
)
{
return
nil
;
}
dispatch_queue_t
queue
=
RLMSyncSession
.
notificationsQueue
;
auto
notifier_direction
=
(
direction
==
RLMSyncProgressDirectionUpload
?
SyncSession
:
:
NotifierType
::
upload
...
...
@@ -209,8 +221,7 @@ using namespace realm;
if
(
!
config
)
{
return
nil
;
}
auto
path
=
SyncManager
::
shared
().
path_for_realm
(
*
config
->
user
,
config
->
realm_url
());
if
(
auto
session
=
config
->
user
->
session_for_on_disk_path
(
path
))
{
if
(
auto
session
=
config
->
user
->
session_for_on_disk_path
(
realm
->
_realm
->
config
().
path
))
{
return
[[
RLMSyncSession
alloc
]
initWithSyncSession
:
session
];
}
return
nil
;
...
...
WhatsOpen/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm
View file @
23c1cdb1
...
...
@@ -133,7 +133,6 @@ static const NSTimeInterval RLMRefreshBuffer = 10;
/// Handler for network requests whose responses successfully parse into an auth response model.
-
(
BOOL
)
_handleSuccessfulRequest
:(
RLMAuthResponseModel
*
)
model
{
// Success
std
::
shared_ptr
<
SyncSession
>
session
=
_session
.
lock
();
if
(
!
session
)
{
// The session is dead or in a fatal error state.
...
...
@@ -141,8 +140,7 @@ static const NSTimeInterval RLMRefreshBuffer = 10;
[
self
invalidate
];
return
NO
;
}
bool
success
=
session
->
state
()
!=
SyncSession
::
PublicState
::
Error
;
if
(
success
)
{
// Calculate the resolved path.
NSString
*
resolvedURLString
=
nil
;
RLMServerPath
resolvedPath
=
model
.
accessToken
.
tokenData
.
path
;
...
...
@@ -156,23 +154,17 @@ static const NSTimeInterval RLMRefreshBuffer = 10;
}
// Pass the token and resolved path to the underlying sync subsystem.
session
->
refresh_access_token
([
model
.
accessToken
.
token
UTF8String
],
{
resolvedURLString
.
UTF8String
});
success
=
session
->
state
()
!=
SyncSession
::
PublicState
::
Error
;
if
(
success
)
{
// Schedule a refresh. If we're successful we must already have `bind()`ed the session
// initially, so we can null out the strong pointer.
_strongSession
=
nullptr
;
NSDate
*
expires
=
[
NSDate
dateWithTimeIntervalSince1970
:
model
.
accessToken
.
tokenData
.
expires
];
[
self
scheduleRefreshTimer
:
expires
];
}
else
{
// The session is dead or in a fatal error state.
unregisterRefreshHandle
(
_user
,
_path
);
[
self
invalidate
];
}
}
if
(
self
.
completionBlock
)
{
self
.
completionBlock
(
success
?
nil
:
make_auth_error_client_issue
()
);
self
.
completionBlock
(
nil
);
}
return
success
;
return
true
;
}
/// Handler for network requests that failed before the JSON parsing stage.
...
...
WhatsOpen/Pods/Realm/Realm/RLMSyncSubscription.mm
View file @
23c1cdb1
...
...
@@ -18,17 +18,19 @@
#import "RLMSyncSubscription.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObject_Private.hpp"
#import "RLMProperty_Private.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMResults_Private.hpp"
#import "RLMUtil.hpp"
#import "object_store.hpp"
#import "sync/partial_sync.hpp"
using
namespace
realm
;
@interface
RLMSyncSubscription
()
-
(
instancetype
)
initWithName
:(
NSString
*
)
name
results
:(
Results
&
)
results
realm
:(
RLMRealm
*
)
realm
;
@property
(
nonatomic
,
readwrite
)
RLMSyncSubscriptionState
state
;
@property
(
nonatomic
,
readwrite
,
nullable
)
NSError
*
error
;
@end
...
...
@@ -39,17 +41,22 @@ using namespace realm;
RLMRealm
*
_realm
;
}
-
(
instancetype
)
initWithName
:(
NSString
*
)
name
results
:(
Results
&
)
results
realm
:(
RLMRealm
*
)
realm
{
-
(
instancetype
)
initWithName
:(
NSString
*
)
name
results
:(
Results
const
&
)
results
realm
:(
RLMRealm
*
)
realm
{
if
(
!
(
self
=
[
super
init
]))
return
nil
;
_name
=
[
name
copy
];
_realm
=
realm
;
try
{
_subscription
=
partial_sync
::
subscribe
(
results
,
name
?
util
:
:
make_optional
<
std
::
string
>
(
name
.
UTF8String
)
:
util
::
none
);
}
catch
(
std
::
exception
const
&
e
)
{
@throw
RLMException
(
e
);
}
self
.
state
=
(
RLMSyncSubscriptionState
)
_subscription
->
state
();
__weak
RLMSyncSubscription
*
weakSelf
=
self
;
__weak
auto
weakSelf
=
self
;
_token
=
_subscription
->
add_notification_callback
([
weakSelf
]
{
RLMSyncSubscription
*
self
=
weakSelf
;
auto
self
=
weakSelf
;
if
(
!
self
)
return
;
...
...
@@ -66,12 +73,24 @@ using namespace realm;
self
.
error
=
nsError
;
}
}
else
if
(
self
.
error
!=
nil
)
else
if
(
self
.
error
)
{
self
.
error
=
nil
;
}
auto
status
=
(
RLMSyncSubscriptionState
)
self
->
_subscription
->
state
();
if
(
status
!=
self
.
state
)
self
.
state
=
(
RLMSyncSubscriptionState
)
status
;
if
(
status
!=
self
.
state
)
{
if
(
status
==
RLMSyncSubscriptionStateCreating
)
{
// If a subscription is deleted without going through this
// object's unsubscribe() method the subscription will transition
// back to Creating rather than Invalidated since it doesn't
// have a good way to track that it previously existed
if
(
self
.
state
!=
RLMSyncSubscriptionStateInvalidated
)
self
.
state
=
RLMSyncSubscriptionStateInvalidated
;
}
else
{
self
.
state
=
status
;
}
}
});
return
self
;
...
...
@@ -80,26 +99,173 @@ using namespace realm;
-
(
void
)
unsubscribe
{
partial_sync
::
unsubscribe
(
*
_subscription
);
}
@end
@interface
RLMSyncSubscriptionObject
:
RLMObjectBase
@end
@implementation
RLMSyncSubscriptionObject
{
util
::
Optional
<
NotificationToken
>
_token
;
Object
_obj
;
}
-
(
NSString
*
)
name
{
return
_row
.
is_attached
()
?
RLMStringDataToNSString
(
_row
.
get_string
(
_row
.
get_column_index
(
"name"
)))
:
nil
;
}
-
(
RLMSyncSubscriptionState
)
state
{
if
(
!
_row
.
is_attached
())
{
return
RLMSyncSubscriptionStateInvalidated
;
}
return
(
RLMSyncSubscriptionState
)
_row
.
get_int
(
_row
.
get_column_index
(
"status"
));
}
-
(
NSError
*
)
error
{
if
(
!
_row
.
is_attached
())
{
return
nil
;
}
StringData
err
=
_row
.
get_string
(
_row
.
get_column_index
(
"error_message"
));
if
(
!
err
.
size
())
{
return
nil
;
}
return
[
NSError
errorWithDomain
:
RLMErrorDomain
code:
RLMErrorFail
userInfo:
@{
NSLocalizedDescriptionKey
:
RLMStringDataToNSString
(
err
)}];
}
-
(
NSString
*
)
descriptionWithMaxDepth
:(
NSUInteger
)
depth
{
if
(
depth
==
0
)
{
return
@"<Maximum depth exceeded>"
;
}
auto
objectType
=
_row
.
get_string
(
_row
.
get_column_index
(
"matches_property"
));
objectType
=
objectType
.
substr
(
0
,
objectType
.
size
()
-
strlen
(
"_matches"
));
return
[
NSString
stringWithFormat
:
@"RLMSyncSubscription {
\n\t
name = %@
\n\t
objectType = %@
\n\t
query = %@
\n\t
status = %@
\n\t
error = %@
\n
}"
,
self
.
name
,
RLMStringDataToNSString
(
objectType
),
RLMStringDataToNSString
(
_row
.
get_string
(
_row
.
get_column_index
(
"query"
))),
@
(
self
.
state
),
self
.
error
];
}
-
(
void
)
unsubscribe
{
if
(
_row
)
{
partial_sync
::
unsubscribe
(
Object
(
_realm
->
_realm
,
*
_info
->
objectSchema
,
_row
));
}
}
-
(
void
)
addObserver
:(
id
)
observer
forKeyPath
:(
NSString
*
)
keyPath
options
:(
NSKeyValueObservingOptions
)
options
context
:(
void
*
)
context
{
// Make the `state` property observable by using an object notifier to
// trigger changes. The normal KVO mechanisms don't work for this class due
// to it not being a normal part of the schema.
if
(
!
_token
)
{
struct
{
__weak
RLMSyncSubscriptionObject
*
weakSelf
;
void
before
(
realm
::
CollectionChangeSet
const
&
)
{
@autoreleasepool
{
[
weakSelf
willChangeValueForKey
:
@"state"
];
}
}
void
after
(
realm
::
CollectionChangeSet
const
&
)
{
@autoreleasepool
{
[
weakSelf
didChangeValueForKey
:
@"state"
];
}
}
void
error
(
std
::
exception_ptr
)
{}
}
callback
{
self
};
_obj
=
Object
(
_realm
->
_realm
,
*
_info
->
objectSchema
,
_row
);
_token
=
_obj
.
add_notification_callback
(
callback
);
}
[
super
addObserver
:
observer
forKeyPath
:
keyPath
options
:
options
context
:
context
];
}
@end