Merge pull request #291 from carambalabs/api/swift-3

Update the API to match the Swift 3 guidelines
This commit is contained in:
Pedro Piñera Buendía 2016-09-28 16:23:01 +02:00 committed by GitHub
commit b96bd43495
328 changed files with 1478 additions and 83056 deletions

2
.gitignore vendored
View File

@ -151,7 +151,7 @@ xcuserdata
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
Pods/
# Carthage
#

View File

@ -5,6 +5,7 @@ notifications:
before_install:
- gem install bundler
- bundle install
- bundle exec pod repo update --silent
- git remote set-url origin "https://${GITHUB_TOKEN}@github.com/carambalabs/SugarRecord.git"
script:
- bundle exec fastlane travis

View File

@ -151,14 +151,10 @@
23E15D5B1D7DDE700073CC71 /* RealmDefaultStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D451D7DDE700073CC71 /* RealmDefaultStorage.swift */; };
23E15D5C1D7DDE700073CC71 /* RealmDefaultStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D451D7DDE700073CC71 /* RealmDefaultStorage.swift */; };
23E15D5D1D7DDE700073CC71 /* RealmDefaultStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D451D7DDE700073CC71 /* RealmDefaultStorage.swift */; };
23E15D711D7DDE7B0073CC71 /* ContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* ContextParent.swift */; };
23E15D721D7DDE7B0073CC71 /* ContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* ContextParent.swift */; };
23E15D731D7DDE7B0073CC71 /* ContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* ContextParent.swift */; };
23E15D741D7DDE7B0073CC71 /* ContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* ContextParent.swift */; };
23E15D751D7DDE7B0073CC71 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D611D7DDE7B0073CC71 /* CoreData.swift */; };
23E15D761D7DDE7B0073CC71 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D611D7DDE7B0073CC71 /* CoreData.swift */; };
23E15D771D7DDE7B0073CC71 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D611D7DDE7B0073CC71 /* CoreData.swift */; };
23E15D781D7DDE7B0073CC71 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D611D7DDE7B0073CC71 /* CoreData.swift */; };
23E15D711D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */; };
23E15D721D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */; };
23E15D731D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */; };
23E15D741D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */; };
23E15D791D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D621D7DDE7B0073CC71 /* CoreDataChange.swift */; };
23E15D7A1D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D621D7DDE7B0073CC71 /* CoreDataChange.swift */; };
23E15D7B1D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D621D7DDE7B0073CC71 /* CoreDataChange.swift */; };
@ -167,26 +163,26 @@
23E15D7E1D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D631D7DDE7B0073CC71 /* CoreDataObservable.swift */; };
23E15D7F1D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D631D7DDE7B0073CC71 /* CoreDataObservable.swift */; };
23E15D801D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D631D7DDE7B0073CC71 /* CoreDataObservable.swift */; };
23E15D811D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */; };
23E15D821D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */; };
23E15D831D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */; };
23E15D841D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */; };
23E15D851D7DDE7B0073CC71 /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */; };
23E15D861D7DDE7B0073CC71 /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */; };
23E15D871D7DDE7B0073CC71 /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */; };
23E15D881D7DDE7B0073CC71 /* ObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */; };
23E15D891D7DDE7B0073CC71 /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* Options.swift */; };
23E15D8A1D7DDE7B0073CC71 /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* Options.swift */; };
23E15D8B1D7DDE7B0073CC71 /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* Options.swift */; };
23E15D8C1D7DDE7B0073CC71 /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* Options.swift */; };
23E15D8D1D7DDE7B0073CC71 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* Store.swift */; };
23E15D8E1D7DDE7B0073CC71 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* Store.swift */; };
23E15D8F1D7DDE7B0073CC71 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* Store.swift */; };
23E15D901D7DDE7B0073CC71 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* Store.swift */; };
23E15D911D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */; };
23E15D921D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */; };
23E15D931D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */; };
23E15D941D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */; };
23E15D811D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */; };
23E15D821D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */; };
23E15D831D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */; };
23E15D841D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */; };
23E15D851D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */; };
23E15D861D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */; };
23E15D871D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */; };
23E15D881D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */; };
23E15D891D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */; };
23E15D8A1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */; };
23E15D8B1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */; };
23E15D8C1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */; };
23E15D8D1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */; };
23E15D8E1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */; };
23E15D8F1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */; };
23E15D901D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */; };
23E15D911D7DDE7B0073CC71 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */; };
23E15D921D7DDE7B0073CC71 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */; };
23E15D931D7DDE7B0073CC71 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */; };
23E15D941D7DDE7B0073CC71 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */; };
23E15D951D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D6B1D7DDE7B0073CC71 /* NSManagedObject.swift */; };
23E15D961D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D6B1D7DDE7B0073CC71 /* NSManagedObject.swift */; };
23E15D971D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E15D6B1D7DDE7B0073CC71 /* NSManagedObject.swift */; };
@ -273,15 +269,14 @@
23E15D421D7DDE700073CC71 /* RealmEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmEntity.swift; sourceTree = "<group>"; };
23E15D431D7DDE700073CC71 /* Results.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Results.swift; sourceTree = "<group>"; };
23E15D451D7DDE700073CC71 /* RealmDefaultStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmDefaultStorage.swift; sourceTree = "<group>"; };
23E15D601D7DDE7B0073CC71 /* ContextParent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextParent.swift; sourceTree = "<group>"; };
23E15D611D7DDE7B0073CC71 /* CoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreData.swift; sourceTree = "<group>"; };
23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataContextParent.swift; sourceTree = "<group>"; };
23E15D621D7DDE7B0073CC71 /* CoreDataChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataChange.swift; sourceTree = "<group>"; };
23E15D631D7DDE7B0073CC71 /* CoreDataObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataObservable.swift; sourceTree = "<group>"; };
23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iCloudConfig.swift; sourceTree = "<group>"; };
23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectModel.swift; sourceTree = "<group>"; };
23E15D661D7DDE7B0073CC71 /* Options.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Options.swift; sourceTree = "<group>"; };
23E15D671D7DDE7B0073CC71 /* Store.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = "<group>"; };
23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataErrors.swift; sourceTree = "<group>"; };
23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataiCloudConfig.swift; sourceTree = "<group>"; };
23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataObjectModel.swift; sourceTree = "<group>"; };
23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataOptions.swift; sourceTree = "<group>"; };
23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStore.swift; sourceTree = "<group>"; };
23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataError.swift; sourceTree = "<group>"; };
23E15D6B1D7DDE7B0073CC71 /* NSManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSManagedObject.swift; sourceTree = "<group>"; };
23E15D6C1D7DDE7B0073CC71 /* NSManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSManagedObjectContext.swift; sourceTree = "<group>"; };
23E15D6D1D7DDE7B0073CC71 /* NSManagedObjectMemoryContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSManagedObjectMemoryContext.swift; sourceTree = "<group>"; };
@ -663,14 +658,13 @@
23E15D5F1D7DDE7B0073CC71 /* Entities */ = {
isa = PBXGroup;
children = (
23E15D601D7DDE7B0073CC71 /* ContextParent.swift */,
23E15D611D7DDE7B0073CC71 /* CoreData.swift */,
23E15D601D7DDE7B0073CC71 /* CoreDataContextParent.swift */,
23E15D621D7DDE7B0073CC71 /* CoreDataChange.swift */,
23E15D631D7DDE7B0073CC71 /* CoreDataObservable.swift */,
23E15D641D7DDE7B0073CC71 /* iCloudConfig.swift */,
23E15D651D7DDE7B0073CC71 /* ObjectModel.swift */,
23E15D661D7DDE7B0073CC71 /* Options.swift */,
23E15D671D7DDE7B0073CC71 /* Store.swift */,
23E15D641D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift */,
23E15D651D7DDE7B0073CC71 /* CoreDataObjectModel.swift */,
23E15D661D7DDE7B0073CC71 /* CoreDataOptions.swift */,
23E15D671D7DDE7B0073CC71 /* CoreDataStore.swift */,
);
path = Entities;
sourceTree = "<group>";
@ -678,7 +672,7 @@
23E15D681D7DDE7B0073CC71 /* Errors */ = {
isa = PBXGroup;
children = (
23E15D691D7DDE7B0073CC71 /* CoreDataErrors.swift */,
23E15D691D7DDE7B0073CC71 /* CoreDataError.swift */,
);
path = Errors;
sourceTree = "<group>";
@ -1037,11 +1031,11 @@
files = (
23E15D9D1D7DDE7B0073CC71 /* NSManagedObjectMemoryContext.swift in Sources */,
23E15CE51D7DDE660073CC71 /* StorageError.swift in Sources */,
23E15D911D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */,
23E15D911D7DDE7B0073CC71 /* CoreDataError.swift in Sources */,
23E15D7D1D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */,
23E15D351D7DDE660073CC71 /* VersionProvider.swift in Sources */,
23E15CF51D7DDE660073CC71 /* Logger.swift in Sources */,
23E15D711D7DDE7B0073CC71 /* ContextParent.swift in Sources */,
23E15D711D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */,
23E15CD51D7DDE660073CC71 /* RequestObservable.swift in Sources */,
23E15D151D7DDE660073CC71 /* NSSortDescriptorConvertible.swift in Sources */,
23E15CFD1D7DDE660073CC71 /* Context.swift in Sources */,
@ -1053,13 +1047,12 @@
23E15D951D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */,
23E15DA11D7DDE7B0073CC71 /* CoreDataDefaultStorage.swift in Sources */,
23E15CED1D7DDE660073CC71 /* RequestExtension.swift in Sources */,
23E15D891D7DDE7B0073CC71 /* Options.swift in Sources */,
23E15D751D7DDE7B0073CC71 /* CoreData.swift in Sources */,
23E15D891D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */,
23E15D1D1D7DDE660073CC71 /* Requestable.swift in Sources */,
23E15D811D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */,
23E15D811D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */,
23E15DA51D7DDE7B0073CC71 /* CoreDataiCloudStorage.swift in Sources */,
23E15D8D1D7DDE7B0073CC71 /* Store.swift in Sources */,
23E15D851D7DDE7B0073CC71 /* ObjectModel.swift in Sources */,
23E15D8D1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */,
23E15D851D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */,
23E15CDD1D7DDE660073CC71 /* Storage.swift in Sources */,
23E15D2D1D7DDE660073CC71 /* VersionController.swift in Sources */,
23E15D791D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */,
@ -1072,11 +1065,11 @@
files = (
23E15D9E1D7DDE7B0073CC71 /* NSManagedObjectMemoryContext.swift in Sources */,
23E15CE71D7DDE660073CC71 /* StorageError.swift in Sources */,
23E15D921D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */,
23E15D921D7DDE7B0073CC71 /* CoreDataError.swift in Sources */,
23E15D7E1D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */,
23E15D371D7DDE660073CC71 /* VersionProvider.swift in Sources */,
23E15CF71D7DDE660073CC71 /* Logger.swift in Sources */,
23E15D721D7DDE7B0073CC71 /* ContextParent.swift in Sources */,
23E15D721D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */,
23E15CD71D7DDE660073CC71 /* RequestObservable.swift in Sources */,
23E15D171D7DDE660073CC71 /* NSSortDescriptorConvertible.swift in Sources */,
23E15CFF1D7DDE660073CC71 /* Context.swift in Sources */,
@ -1088,12 +1081,11 @@
23E15D961D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */,
23E15DA21D7DDE7B0073CC71 /* CoreDataDefaultStorage.swift in Sources */,
23E15CEF1D7DDE660073CC71 /* RequestExtension.swift in Sources */,
23E15D8A1D7DDE7B0073CC71 /* Options.swift in Sources */,
23E15D761D7DDE7B0073CC71 /* CoreData.swift in Sources */,
23E15D8A1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */,
23E15D1F1D7DDE660073CC71 /* Requestable.swift in Sources */,
23E15D821D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */,
23E15D8E1D7DDE7B0073CC71 /* Store.swift in Sources */,
23E15D861D7DDE7B0073CC71 /* ObjectModel.swift in Sources */,
23E15D821D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */,
23E15D8E1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */,
23E15D861D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */,
23E15CDF1D7DDE660073CC71 /* Storage.swift in Sources */,
23E15D2F1D7DDE660073CC71 /* VersionController.swift in Sources */,
23E15D7A1D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */,
@ -1106,11 +1098,11 @@
files = (
23E15D9F1D7DDE7B0073CC71 /* NSManagedObjectMemoryContext.swift in Sources */,
23E15CE91D7DDE660073CC71 /* StorageError.swift in Sources */,
23E15D931D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */,
23E15D931D7DDE7B0073CC71 /* CoreDataError.swift in Sources */,
23E15D7F1D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */,
23E15D391D7DDE660073CC71 /* VersionProvider.swift in Sources */,
23E15CF91D7DDE660073CC71 /* Logger.swift in Sources */,
23E15D731D7DDE7B0073CC71 /* ContextParent.swift in Sources */,
23E15D731D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */,
23E15CD91D7DDE660073CC71 /* RequestObservable.swift in Sources */,
23E15D191D7DDE660073CC71 /* NSSortDescriptorConvertible.swift in Sources */,
23E15D011D7DDE660073CC71 /* Context.swift in Sources */,
@ -1122,12 +1114,11 @@
23E15D971D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */,
23E15DA31D7DDE7B0073CC71 /* CoreDataDefaultStorage.swift in Sources */,
23E15CF11D7DDE660073CC71 /* RequestExtension.swift in Sources */,
23E15D8B1D7DDE7B0073CC71 /* Options.swift in Sources */,
23E15D771D7DDE7B0073CC71 /* CoreData.swift in Sources */,
23E15D8B1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */,
23E15D211D7DDE660073CC71 /* Requestable.swift in Sources */,
23E15D831D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */,
23E15D8F1D7DDE7B0073CC71 /* Store.swift in Sources */,
23E15D871D7DDE7B0073CC71 /* ObjectModel.swift in Sources */,
23E15D831D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */,
23E15D8F1D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */,
23E15D871D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */,
23E15CE11D7DDE660073CC71 /* Storage.swift in Sources */,
23E15D311D7DDE660073CC71 /* VersionController.swift in Sources */,
23E15D7B1D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */,
@ -1140,11 +1131,11 @@
files = (
23E15DA01D7DDE7B0073CC71 /* NSManagedObjectMemoryContext.swift in Sources */,
23E15CEB1D7DDE660073CC71 /* StorageError.swift in Sources */,
23E15D941D7DDE7B0073CC71 /* CoreDataErrors.swift in Sources */,
23E15D941D7DDE7B0073CC71 /* CoreDataError.swift in Sources */,
23E15D801D7DDE7B0073CC71 /* CoreDataObservable.swift in Sources */,
23E15D3B1D7DDE660073CC71 /* VersionProvider.swift in Sources */,
23E15CFB1D7DDE660073CC71 /* Logger.swift in Sources */,
23E15D741D7DDE7B0073CC71 /* ContextParent.swift in Sources */,
23E15D741D7DDE7B0073CC71 /* CoreDataContextParent.swift in Sources */,
23E15CDB1D7DDE660073CC71 /* RequestObservable.swift in Sources */,
23E15D1B1D7DDE660073CC71 /* NSSortDescriptorConvertible.swift in Sources */,
23E15D031D7DDE660073CC71 /* Context.swift in Sources */,
@ -1156,13 +1147,12 @@
23E15D981D7DDE7B0073CC71 /* NSManagedObject.swift in Sources */,
23E15DA41D7DDE7B0073CC71 /* CoreDataDefaultStorage.swift in Sources */,
23E15CF31D7DDE660073CC71 /* RequestExtension.swift in Sources */,
23E15D8C1D7DDE7B0073CC71 /* Options.swift in Sources */,
23E15D781D7DDE7B0073CC71 /* CoreData.swift in Sources */,
23E15D8C1D7DDE7B0073CC71 /* CoreDataOptions.swift in Sources */,
23E15D231D7DDE660073CC71 /* Requestable.swift in Sources */,
23E15D841D7DDE7B0073CC71 /* iCloudConfig.swift in Sources */,
23E15D841D7DDE7B0073CC71 /* CoreDataiCloudConfig.swift in Sources */,
23E15DA81D7DDE7B0073CC71 /* CoreDataiCloudStorage.swift in Sources */,
23E15D901D7DDE7B0073CC71 /* Store.swift in Sources */,
23E15D881D7DDE7B0073CC71 /* ObjectModel.swift in Sources */,
23E15D901D7DDE7B0073CC71 /* CoreDataStore.swift in Sources */,
23E15D881D7DDE7B0073CC71 /* CoreDataObjectModel.swift in Sources */,
23E15CE31D7DDE660073CC71 /* Storage.swift in Sources */,
23E15D331D7DDE660073CC71 /* VersionController.swift in Sources */,
23E15D7C1D7DDE7B0073CC71 /* CoreDataChange.swift in Sources */,

View File

@ -1,6 +1,6 @@
use_frameworks!
target 'Examples' do
target 'SugarRecord_Example' do
pod 'SnapKit'
pod 'SugarRecord', :path => "../"
pod 'SugarRecord/CoreData', :path => "../"
@ -8,13 +8,13 @@ target 'Examples' do
pod 'SugarRecord/Realm', :path => "../"
end
target 'Tests' do
target 'SugarRecord_Tests' do
pod 'SugarRecord', :path => "../"
pod 'SugarRecord/CoreData', :path => "../"
pod 'SugarRecord/CoreData+iCloud', :path => "../"
pod 'SugarRecord/Realm', :path => "../"
pod "Quick", :git => "https://github.com/quick/quick.git", :branch => "swift-3.0"
pod "Nimble", "~> 5.0"
pod 'Quick', "~> 0.10"
pod 'Nimble', '~> 5.0'
pod "OHHTTPStubs"
pod 'OHHTTPStubs/Swift'
end

View File

@ -15,7 +15,7 @@ PODS:
- OHHTTPStubs/OHPathHelpers (5.2.1)
- OHHTTPStubs/Swift (5.2.1):
- OHHTTPStubs/Core
- Quick (0.9.3)
- Quick (0.10.0)
- Realm (1.1.0):
- Realm/Headers (= 1.1.0)
- Realm/Headers (1.1.0)
@ -23,15 +23,15 @@ PODS:
- Realm (= 1.1.0)
- Result (3.0.0)
- SnapKit (3.0.1)
- SugarRecord (2.3.1):
- SugarRecord/CoreData (= 2.3.1)
- SugarRecord/CoreData+iCloud (= 2.3.1)
- SugarRecord/Realm (= 2.3.1)
- SugarRecord/CoreData (2.3.1):
- SugarRecord (3.0.0-alpha.1):
- SugarRecord/CoreData (= 3.0.0-alpha.1)
- SugarRecord/CoreData+iCloud (= 3.0.0-alpha.1)
- SugarRecord/Realm (= 3.0.0-alpha.1)
- SugarRecord/CoreData (3.0.0-alpha.1):
- Result (~> 3.0)
- SugarRecord/CoreData+iCloud (2.3.1):
- SugarRecord/CoreData+iCloud (3.0.0-alpha.1):
- Result (~> 3.0)
- SugarRecord/Realm (2.3.1):
- SugarRecord/Realm (3.0.0-alpha.1):
- RealmSwift (~> 1.1)
- Result (~> 3.0)
@ -39,7 +39,7 @@ DEPENDENCIES:
- Nimble (~> 5.0)
- OHHTTPStubs
- OHHTTPStubs/Swift
- Quick (from `https://github.com/quick/quick.git`, branch `swift-3.0`)
- Quick (~> 0.10)
- SnapKit
- SugarRecord (from `../`)
- SugarRecord/CoreData (from `../`)
@ -47,27 +47,19 @@ DEPENDENCIES:
- SugarRecord/Realm (from `../`)
EXTERNAL SOURCES:
Quick:
:branch: swift-3.0
:git: https://github.com/quick/quick.git
SugarRecord:
:path: "../"
CHECKOUT OPTIONS:
Quick:
:commit: 36ebbc75e093c7553a5145ed5dd21484364cd78d
:git: https://github.com/quick/quick.git
SPEC CHECKSUMS:
Nimble: 56fc9f5020effa2206de22c3dd910f4fb011b92f
OHHTTPStubs: 3a42f25c00563b71355ac73112ba2324e9e6cef4
Quick: 31fb576b6cbb6b028cc5e0016e4366accbb346f5
Quick: 5d290df1c69d5ee2f0729956dcf0fd9a30447eaa
Realm: ceecf1a4540c4ce9efe196fe73fa9855bce05bd8
RealmSwift: 838058b2db95b12cb86bd0cf209df642c33fb60a
Result: 1b3e431f37cbcd3ad89c6aa9ab0ae55515fae3b6
SnapKit: f818b8326d45b4e1c777d0ab27b5c0a3624bfdeb
SugarRecord: 7c972754f31c77561828534c3779166f4334ebd6
SugarRecord: 13f9d029c077dea63c7f7240dd401ac4af15a84c
PODFILE CHECKSUM: dd311db187c6a1e0623852ea09855f7131cbe784
PODFILE CHECKSUM: 93e4a0d6049261cca889912a17deebad59571a81
COCOAPODS: 1.1.0.rc.2

View File

@ -0,0 +1,985 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
23E13E5B1D96896300204C82 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E341D96896300204C82 /* CoreData.swift */; };
23E13E5C1D96896300204C82 /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E351D96896300204C82 /* Realm.swift */; };
23E13E5D1D96896300204C82 /* Track+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E381D96896300204C82 /* Track+CoreDataProperties.swift */; };
23E13E5E1D96896300204C82 /* Track.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E391D96896300204C82 /* Track.swift */; };
23E13E5F1D96896300204C82 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E3B1D96896300204C82 /* Issue.swift */; };
23E13E601D96896300204C82 /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E3C1D96896300204C82 /* Repository.swift */; };
23E13E611D96896300204C82 /* DataModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E3E1D96896300204C82 /* DataModel.xcdatamodeld */; };
23E13E621D96896300204C82 /* CoreDataChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E431D96896300204C82 /* CoreDataChangeTests.swift */; };
23E13E631D96896300204C82 /* CoreDataObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E441D96896300204C82 /* CoreDataObservableTests.swift */; };
23E13E641D96896300204C82 /* ObjectModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E451D96896300204C82 /* ObjectModelTests.swift */; };
23E13E651D96896300204C82 /* OptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E461D96896300204C82 /* OptionsTests.swift */; };
23E13E661D96896300204C82 /* StoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E471D96896300204C82 /* StoreTests.swift */; };
23E13E671D96896300204C82 /* CoreDataDefaultStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E491D96896300204C82 /* CoreDataDefaultStorageTests.swift */; };
23E13E681D96896300204C82 /* RequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E4C1D96896300204C82 /* RequestTests.swift */; };
23E13E691D96896300204C82 /* DirUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E4E1D96896300204C82 /* DirUtilsTests.swift */; };
23E13E6A1D96896300204C82 /* VersionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E501D96896300204C82 /* VersionControllerTests.swift */; };
23E13E6B1D96896300204C82 /* VersionProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E511D96896300204C82 /* VersionProviderTests.swift */; };
23E13E6C1D96896300204C82 /* RealmObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E551D96896300204C82 /* RealmObservableTests.swift */; };
23E13E6D1D96896300204C82 /* RealmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E571D96896300204C82 /* RealmTests.swift */; };
23E13E6E1D96896300204C82 /* ResultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E581D96896300204C82 /* ResultsTests.swift */; };
23E13E6F1D96896300204C82 /* RealmDefaultStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E5A1D96896300204C82 /* RealmDefaultStorageTests.swift */; };
23E13E8F1D96899000204C82 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23E13E721D96899000204C82 /* Assets.xcassets */; };
23E13E901D96899000204C82 /* Basic.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E741D96899000204C82 /* Basic.xcdatamodeld */; };
23E13E911D96899000204C82 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23E13E771D96899000204C82 /* LaunchScreen.storyboard */; };
23E13E921D96899000204C82 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E7A1D96899000204C82 /* AppDelegate.swift */; };
23E13E931D96899000204C82 /* CoreDataBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E7E1D96899000204C82 /* CoreDataBasicView.swift */; };
23E13E941D96899000204C82 /* BasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E801D96899000204C82 /* BasicObject.swift */; };
23E13E951D96899000204C82 /* CoreDataBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E811D96899000204C82 /* CoreDataBasicEntity.swift */; };
23E13E961D96899000204C82 /* RealmBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E851D96899000204C82 /* RealmBasicView.swift */; };
23E13E971D96899000204C82 /* RealmBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E871D96899000204C82 /* RealmBasicEntity.swift */; };
23E13E981D96899000204C82 /* RealmBasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E881D96899000204C82 /* RealmBasicObject.swift */; };
23E13E991D96899000204C82 /* Directory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E8B1D96899000204C82 /* Directory.swift */; };
23E13E9A1D96899000204C82 /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E8C1D96899000204C82 /* Random.swift */; };
23E13E9B1D96899000204C82 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E13E8E1D96899000204C82 /* ViewController.swift */; };
7F0014DAE56FEBE9A77EB8F3 /* Pods_SugarRecord_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE4511BDA74E45A8EA0229D9 /* Pods_SugarRecord_Tests.framework */; };
A682778445C166ABA1550ECF /* Pods_SugarRecord_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB6674BDC2C223325C9246F4 /* Pods_SugarRecord_Example.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 607FACCF1AFB9204008FA782;
remoteInfo = SugarRecord;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
199B6E9AFF9F22F151FCACD5 /* Pods-SugarRecord_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SugarRecord_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SugarRecord_Example/Pods-SugarRecord_Example.debug.xcconfig"; sourceTree = "<group>"; };
23E13E341D96896300204C82 /* CoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreData.swift; sourceTree = "<group>"; };
23E13E351D96896300204C82 /* Realm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = "<group>"; };
23E13E381D96896300204C82 /* Track+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Track+CoreDataProperties.swift"; sourceTree = "<group>"; };
23E13E391D96896300204C82 /* Track.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Track.swift; sourceTree = "<group>"; };
23E13E3B1D96896300204C82 /* Issue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = "<group>"; };
23E13E3C1D96896300204C82 /* Repository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Repository.swift; sourceTree = "<group>"; };
23E13E3F1D96896300204C82 /* DataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = DataModel.xcdatamodel; sourceTree = "<group>"; };
23E13E431D96896300204C82 /* CoreDataChangeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataChangeTests.swift; sourceTree = "<group>"; };
23E13E441D96896300204C82 /* CoreDataObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataObservableTests.swift; sourceTree = "<group>"; };
23E13E451D96896300204C82 /* ObjectModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectModelTests.swift; sourceTree = "<group>"; };
23E13E461D96896300204C82 /* OptionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionsTests.swift; sourceTree = "<group>"; };
23E13E471D96896300204C82 /* StoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreTests.swift; sourceTree = "<group>"; };
23E13E491D96896300204C82 /* CoreDataDefaultStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataDefaultStorageTests.swift; sourceTree = "<group>"; };
23E13E4C1D96896300204C82 /* RequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestTests.swift; sourceTree = "<group>"; };
23E13E4E1D96896300204C82 /* DirUtilsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DirUtilsTests.swift; sourceTree = "<group>"; };
23E13E501D96896300204C82 /* VersionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionControllerTests.swift; sourceTree = "<group>"; };
23E13E511D96896300204C82 /* VersionProviderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionProviderTests.swift; sourceTree = "<group>"; };
23E13E551D96896300204C82 /* RealmObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmObservableTests.swift; sourceTree = "<group>"; };
23E13E571D96896300204C82 /* RealmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmTests.swift; sourceTree = "<group>"; };
23E13E581D96896300204C82 /* ResultsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultsTests.swift; sourceTree = "<group>"; };
23E13E5A1D96896300204C82 /* RealmDefaultStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmDefaultStorageTests.swift; sourceTree = "<group>"; };
23E13E721D96899000204C82 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
23E13E751D96899000204C82 /* Basic.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Basic.xcdatamodel; sourceTree = "<group>"; };
23E13E771D96899000204C82 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
23E13E7A1D96899000204C82 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
23E13E7E1D96899000204C82 /* CoreDataBasicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataBasicView.swift; sourceTree = "<group>"; };
23E13E801D96899000204C82 /* BasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicObject.swift; sourceTree = "<group>"; };
23E13E811D96899000204C82 /* CoreDataBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataBasicEntity.swift; sourceTree = "<group>"; };
23E13E851D96899000204C82 /* RealmBasicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicView.swift; sourceTree = "<group>"; };
23E13E871D96899000204C82 /* RealmBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicEntity.swift; sourceTree = "<group>"; };
23E13E881D96899000204C82 /* RealmBasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicObject.swift; sourceTree = "<group>"; };
23E13E8B1D96899000204C82 /* Directory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Directory.swift; sourceTree = "<group>"; };
23E13E8C1D96899000204C82 /* Random.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Random.swift; sourceTree = "<group>"; };
23E13E8E1D96899000204C82 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
43D59494AB8B01F49D62B037 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
54DE24CF394C35117CF642A6 /* Pods-SugarRecord_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SugarRecord_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SugarRecord_Tests/Pods-SugarRecord_Tests.debug.xcconfig"; sourceTree = "<group>"; };
5B476131E81A65EF61C0905C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
607FACD01AFB9204008FA782 /* SugarRecord_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SugarRecord_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607FACE51AFB9204008FA782 /* SugarRecord_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SugarRecord_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
65A181DD622A1F2F3D27044A /* SugarRecord.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = SugarRecord.podspec; path = ../SugarRecord.podspec; sourceTree = "<group>"; };
92C812F114142E61803D9DEF /* Pods-SugarRecord_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SugarRecord_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-SugarRecord_Example/Pods-SugarRecord_Example.release.xcconfig"; sourceTree = "<group>"; };
BB6674BDC2C223325C9246F4 /* Pods_SugarRecord_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SugarRecord_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DE4511BDA74E45A8EA0229D9 /* Pods_SugarRecord_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SugarRecord_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EF1427C1C51BC3D125AAFF0F /* Pods-SugarRecord_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SugarRecord_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SugarRecord_Tests/Pods-SugarRecord_Tests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
607FACCD1AFB9204008FA782 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A682778445C166ABA1550ECF /* Pods_SugarRecord_Example.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE21AFB9204008FA782 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7F0014DAE56FEBE9A77EB8F3 /* Pods_SugarRecord_Tests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
23E13E331D96896300204C82 /* Helpers */ = {
isa = PBXGroup;
children = (
23E13E341D96896300204C82 /* CoreData.swift */,
23E13E351D96896300204C82 /* Realm.swift */,
);
name = Helpers;
path = ../../Tests/Helpers;
sourceTree = "<group>";
};
23E13E361D96896300204C82 /* Models */ = {
isa = PBXGroup;
children = (
23E13E371D96896300204C82 /* CoreData */,
23E13E3A1D96896300204C82 /* Realm */,
);
name = Models;
path = ../../Tests/Models;
sourceTree = "<group>";
};
23E13E371D96896300204C82 /* CoreData */ = {
isa = PBXGroup;
children = (
23E13E381D96896300204C82 /* Track+CoreDataProperties.swift */,
23E13E391D96896300204C82 /* Track.swift */,
);
path = CoreData;
sourceTree = "<group>";
};
23E13E3A1D96896300204C82 /* Realm */ = {
isa = PBXGroup;
children = (
23E13E3B1D96896300204C82 /* Issue.swift */,
23E13E3C1D96896300204C82 /* Repository.swift */,
);
path = Realm;
sourceTree = "<group>";
};
23E13E3D1D96896300204C82 /* Resources */ = {
isa = PBXGroup;
children = (
23E13E3E1D96896300204C82 /* DataModel.xcdatamodeld */,
);
name = Resources;
path = ../../Tests/Resources;
sourceTree = "<group>";
};
23E13E401D96896300204C82 /* Source */ = {
isa = PBXGroup;
children = (
23E13E411D96896300204C82 /* CoreData */,
23E13E4A1D96896300204C82 /* Foundation */,
23E13E521D96896300204C82 /* Reactive */,
23E13E531D96896300204C82 /* Realm */,
);
name = Source;
path = ../../Tests/Source;
sourceTree = "<group>";
};
23E13E411D96896300204C82 /* CoreData */ = {
isa = PBXGroup;
children = (
23E13E421D96896300204C82 /* Entities */,
23E13E481D96896300204C82 /* Storage */,
);
path = CoreData;
sourceTree = "<group>";
};
23E13E421D96896300204C82 /* Entities */ = {
isa = PBXGroup;
children = (
23E13E431D96896300204C82 /* CoreDataChangeTests.swift */,
23E13E441D96896300204C82 /* CoreDataObservableTests.swift */,
23E13E451D96896300204C82 /* ObjectModelTests.swift */,
23E13E461D96896300204C82 /* OptionsTests.swift */,
23E13E471D96896300204C82 /* StoreTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23E13E481D96896300204C82 /* Storage */ = {
isa = PBXGroup;
children = (
23E13E491D96896300204C82 /* CoreDataDefaultStorageTests.swift */,
);
path = Storage;
sourceTree = "<group>";
};
23E13E4A1D96896300204C82 /* Foundation */ = {
isa = PBXGroup;
children = (
23E13E4B1D96896300204C82 /* Entities */,
23E13E4D1D96896300204C82 /* Utils */,
23E13E4F1D96896300204C82 /* Version */,
);
path = Foundation;
sourceTree = "<group>";
};
23E13E4B1D96896300204C82 /* Entities */ = {
isa = PBXGroup;
children = (
23E13E4C1D96896300204C82 /* RequestTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23E13E4D1D96896300204C82 /* Utils */ = {
isa = PBXGroup;
children = (
23E13E4E1D96896300204C82 /* DirUtilsTests.swift */,
);
path = Utils;
sourceTree = "<group>";
};
23E13E4F1D96896300204C82 /* Version */ = {
isa = PBXGroup;
children = (
23E13E501D96896300204C82 /* VersionControllerTests.swift */,
23E13E511D96896300204C82 /* VersionProviderTests.swift */,
);
path = Version;
sourceTree = "<group>";
};
23E13E521D96896300204C82 /* Reactive */ = {
isa = PBXGroup;
children = (
);
path = Reactive;
sourceTree = "<group>";
};
23E13E531D96896300204C82 /* Realm */ = {
isa = PBXGroup;
children = (
23E13E541D96896300204C82 /* Entities */,
23E13E561D96896300204C82 /* Extensions */,
23E13E591D96896300204C82 /* Storages */,
);
path = Realm;
sourceTree = "<group>";
};
23E13E541D96896300204C82 /* Entities */ = {
isa = PBXGroup;
children = (
23E13E551D96896300204C82 /* RealmObservableTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23E13E561D96896300204C82 /* Extensions */ = {
isa = PBXGroup;
children = (
23E13E571D96896300204C82 /* RealmTests.swift */,
23E13E581D96896300204C82 /* ResultsTests.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
23E13E591D96896300204C82 /* Storages */ = {
isa = PBXGroup;
children = (
23E13E5A1D96896300204C82 /* RealmDefaultStorageTests.swift */,
);
path = Storages;
sourceTree = "<group>";
};
23E13E701D96899000204C82 /* Resources */ = {
isa = PBXGroup;
children = (
23E13E711D96899000204C82 /* Assets */,
23E13E731D96899000204C82 /* DataModels */,
23E13E761D96899000204C82 /* Storyboards */,
);
path = Resources;
sourceTree = "<group>";
};
23E13E711D96899000204C82 /* Assets */ = {
isa = PBXGroup;
children = (
23E13E721D96899000204C82 /* Assets.xcassets */,
);
path = Assets;
sourceTree = "<group>";
};
23E13E731D96899000204C82 /* DataModels */ = {
isa = PBXGroup;
children = (
23E13E741D96899000204C82 /* Basic.xcdatamodeld */,
);
path = DataModels;
sourceTree = "<group>";
};
23E13E761D96899000204C82 /* Storyboards */ = {
isa = PBXGroup;
children = (
23E13E771D96899000204C82 /* LaunchScreen.storyboard */,
);
path = Storyboards;
sourceTree = "<group>";
};
23E13E781D96899000204C82 /* Source */ = {
isa = PBXGroup;
children = (
23E13E791D96899000204C82 /* App */,
23E13E7B1D96899000204C82 /* Examples */,
23E13E8A1D96899000204C82 /* Helpers */,
23E13E8D1D96899000204C82 /* Main */,
);
path = Source;
sourceTree = "<group>";
};
23E13E791D96899000204C82 /* App */ = {
isa = PBXGroup;
children = (
23E13E7A1D96899000204C82 /* AppDelegate.swift */,
);
path = App;
sourceTree = "<group>";
};
23E13E7B1D96899000204C82 /* Examples */ = {
isa = PBXGroup;
children = (
23E13E7C1D96899000204C82 /* CoreData */,
23E13E831D96899000204C82 /* Realm */,
);
path = Examples;
sourceTree = "<group>";
};
23E13E7C1D96899000204C82 /* CoreData */ = {
isa = PBXGroup;
children = (
23E13E7D1D96899000204C82 /* Basic */,
23E13E7F1D96899000204C82 /* Models */,
23E13E821D96899000204C82 /* Observable */,
);
path = CoreData;
sourceTree = "<group>";
};
23E13E7D1D96899000204C82 /* Basic */ = {
isa = PBXGroup;
children = (
23E13E7E1D96899000204C82 /* CoreDataBasicView.swift */,
);
path = Basic;
sourceTree = "<group>";
};
23E13E7F1D96899000204C82 /* Models */ = {
isa = PBXGroup;
children = (
23E13E801D96899000204C82 /* BasicObject.swift */,
23E13E811D96899000204C82 /* CoreDataBasicEntity.swift */,
);
path = Models;
sourceTree = "<group>";
};
23E13E821D96899000204C82 /* Observable */ = {
isa = PBXGroup;
children = (
);
path = Observable;
sourceTree = "<group>";
};
23E13E831D96899000204C82 /* Realm */ = {
isa = PBXGroup;
children = (
23E13E841D96899000204C82 /* Basic */,
23E13E861D96899000204C82 /* Models */,
23E13E891D96899000204C82 /* Observable */,
);
path = Realm;
sourceTree = "<group>";
};
23E13E841D96899000204C82 /* Basic */ = {
isa = PBXGroup;
children = (
23E13E851D96899000204C82 /* RealmBasicView.swift */,
);
path = Basic;
sourceTree = "<group>";
};
23E13E861D96899000204C82 /* Models */ = {
isa = PBXGroup;
children = (
23E13E871D96899000204C82 /* RealmBasicEntity.swift */,
23E13E881D96899000204C82 /* RealmBasicObject.swift */,
);
path = Models;
sourceTree = "<group>";
};
23E13E891D96899000204C82 /* Observable */ = {
isa = PBXGroup;
children = (
);
path = Observable;
sourceTree = "<group>";
};
23E13E8A1D96899000204C82 /* Helpers */ = {
isa = PBXGroup;
children = (
23E13E8B1D96899000204C82 /* Directory.swift */,
23E13E8C1D96899000204C82 /* Random.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
23E13E8D1D96899000204C82 /* Main */ = {
isa = PBXGroup;
children = (
23E13E8E1D96899000204C82 /* ViewController.swift */,
);
path = Main;
sourceTree = "<group>";
};
51C9EF80959BF8FABCA8F5A9 /* Pods */ = {
isa = PBXGroup;
children = (
199B6E9AFF9F22F151FCACD5 /* Pods-SugarRecord_Example.debug.xcconfig */,
92C812F114142E61803D9DEF /* Pods-SugarRecord_Example.release.xcconfig */,
54DE24CF394C35117CF642A6 /* Pods-SugarRecord_Tests.debug.xcconfig */,
EF1427C1C51BC3D125AAFF0F /* Pods-SugarRecord_Tests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
607FACC71AFB9204008FA782 = {
isa = PBXGroup;
children = (
607FACF51AFB993E008FA782 /* Podspec Metadata */,
607FACD21AFB9204008FA782 /* Example for SugarRecord */,
607FACE81AFB9204008FA782 /* Tests */,
607FACD11AFB9204008FA782 /* Products */,
51C9EF80959BF8FABCA8F5A9 /* Pods */,
CEEE802555381F009B6ADB04 /* Frameworks */,
);
sourceTree = "<group>";
};
607FACD11AFB9204008FA782 /* Products */ = {
isa = PBXGroup;
children = (
607FACD01AFB9204008FA782 /* SugarRecord_Example.app */,
607FACE51AFB9204008FA782 /* SugarRecord_Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
607FACD21AFB9204008FA782 /* Example for SugarRecord */ = {
isa = PBXGroup;
children = (
23E13E701D96899000204C82 /* Resources */,
23E13E781D96899000204C82 /* Source */,
607FACD31AFB9204008FA782 /* Supporting Files */,
);
name = "Example for SugarRecord";
path = SugarRecord;
sourceTree = "<group>";
};
607FACD31AFB9204008FA782 /* Supporting Files */ = {
isa = PBXGroup;
children = (
607FACD41AFB9204008FA782 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
607FACE81AFB9204008FA782 /* Tests */ = {
isa = PBXGroup;
children = (
23E13E331D96896300204C82 /* Helpers */,
23E13E361D96896300204C82 /* Models */,
23E13E3D1D96896300204C82 /* Resources */,
23E13E401D96896300204C82 /* Source */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
path = Tests;
sourceTree = "<group>";
};
607FACE91AFB9204008FA782 /* Supporting Files */ = {
isa = PBXGroup;
children = (
607FACEA1AFB9204008FA782 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
isa = PBXGroup;
children = (
65A181DD622A1F2F3D27044A /* SugarRecord.podspec */,
43D59494AB8B01F49D62B037 /* README.md */,
5B476131E81A65EF61C0905C /* LICENSE */,
);
name = "Podspec Metadata";
sourceTree = "<group>";
};
CEEE802555381F009B6ADB04 /* Frameworks */ = {
isa = PBXGroup;
children = (
BB6674BDC2C223325C9246F4 /* Pods_SugarRecord_Example.framework */,
DE4511BDA74E45A8EA0229D9 /* Pods_SugarRecord_Tests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
607FACCF1AFB9204008FA782 /* SugarRecord_Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SugarRecord_Example" */;
buildPhases = (
01C1BC6375B2AB4AFA13BBA1 /* [CP] Check Pods Manifest.lock */,
607FACCC1AFB9204008FA782 /* Sources */,
607FACCD1AFB9204008FA782 /* Frameworks */,
607FACCE1AFB9204008FA782 /* Resources */,
5CC50519DB34147A00106131 /* [CP] Embed Pods Frameworks */,
A8B8DCCFD7667D0B80C5AF17 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = SugarRecord_Example;
productName = SugarRecord;
productReference = 607FACD01AFB9204008FA782 /* SugarRecord_Example.app */;
productType = "com.apple.product-type.application";
};
607FACE41AFB9204008FA782 /* SugarRecord_Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SugarRecord_Tests" */;
buildPhases = (
C80BC0F277849B3F17D1036F /* [CP] Check Pods Manifest.lock */,
607FACE11AFB9204008FA782 /* Sources */,
607FACE21AFB9204008FA782 /* Frameworks */,
607FACE31AFB9204008FA782 /* Resources */,
FE8764C997ACB32CEF47985C /* [CP] Embed Pods Frameworks */,
A8EAB62C7C1162F4D92E413F /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
607FACE71AFB9204008FA782 /* PBXTargetDependency */,
);
name = SugarRecord_Tests;
productName = Tests;
productReference = 607FACE51AFB9204008FA782 /* SugarRecord_Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
607FACC81AFB9204008FA782 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = CocoaPods;
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
LastSwiftMigration = 0800;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
LastSwiftMigration = 0800;
};
};
};
buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SugarRecord" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 607FACC71AFB9204008FA782;
productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
607FACCF1AFB9204008FA782 /* SugarRecord_Example */,
607FACE41AFB9204008FA782 /* SugarRecord_Tests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
607FACCE1AFB9204008FA782 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23E13E8F1D96899000204C82 /* Assets.xcassets in Resources */,
23E13E911D96899000204C82 /* LaunchScreen.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE31AFB9204008FA782 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
01C1BC6375B2AB4AFA13BBA1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
5CC50519DB34147A00106131 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SugarRecord_Example/Pods-SugarRecord_Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
A8B8DCCFD7667D0B80C5AF17 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SugarRecord_Example/Pods-SugarRecord_Example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
A8EAB62C7C1162F4D92E413F /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SugarRecord_Tests/Pods-SugarRecord_Tests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
C80BC0F277849B3F17D1036F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
FE8764C997ACB32CEF47985C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SugarRecord_Tests/Pods-SugarRecord_Tests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
607FACCC1AFB9204008FA782 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23E13E931D96899000204C82 /* CoreDataBasicView.swift in Sources */,
23E13E941D96899000204C82 /* BasicObject.swift in Sources */,
23E13E9A1D96899000204C82 /* Random.swift in Sources */,
23E13E921D96899000204C82 /* AppDelegate.swift in Sources */,
23E13E9B1D96899000204C82 /* ViewController.swift in Sources */,
23E13E981D96899000204C82 /* RealmBasicObject.swift in Sources */,
23E13E901D96899000204C82 /* Basic.xcdatamodeld in Sources */,
23E13E951D96899000204C82 /* CoreDataBasicEntity.swift in Sources */,
23E13E971D96899000204C82 /* RealmBasicEntity.swift in Sources */,
23E13E961D96899000204C82 /* RealmBasicView.swift in Sources */,
23E13E991D96899000204C82 /* Directory.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE11AFB9204008FA782 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23E13E6C1D96896300204C82 /* RealmObservableTests.swift in Sources */,
23E13E631D96896300204C82 /* CoreDataObservableTests.swift in Sources */,
23E13E681D96896300204C82 /* RequestTests.swift in Sources */,
23E13E621D96896300204C82 /* CoreDataChangeTests.swift in Sources */,
23E13E5F1D96896300204C82 /* Issue.swift in Sources */,
23E13E6A1D96896300204C82 /* VersionControllerTests.swift in Sources */,
23E13E5B1D96896300204C82 /* CoreData.swift in Sources */,
23E13E641D96896300204C82 /* ObjectModelTests.swift in Sources */,
23E13E671D96896300204C82 /* CoreDataDefaultStorageTests.swift in Sources */,
23E13E6D1D96896300204C82 /* RealmTests.swift in Sources */,
23E13E5C1D96896300204C82 /* Realm.swift in Sources */,
23E13E611D96896300204C82 /* DataModel.xcdatamodeld in Sources */,
23E13E5D1D96896300204C82 /* Track+CoreDataProperties.swift in Sources */,
23E13E691D96896300204C82 /* DirUtilsTests.swift in Sources */,
23E13E6E1D96896300204C82 /* ResultsTests.swift in Sources */,
23E13E6F1D96896300204C82 /* RealmDefaultStorageTests.swift in Sources */,
23E13E6B1D96896300204C82 /* VersionProviderTests.swift in Sources */,
23E13E651D96896300204C82 /* OptionsTests.swift in Sources */,
23E13E5E1D96896300204C82 /* Track.swift in Sources */,
23E13E601D96896300204C82 /* Repository.swift in Sources */,
23E13E661D96896300204C82 /* StoreTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 607FACCF1AFB9204008FA782 /* SugarRecord_Example */;
targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
607FACED1AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
607FACEE1AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
607FACF01AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 199B6E9AFF9F22F151FCACD5 /* Pods-SugarRecord_Example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SugarRecord/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
607FACF11AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 92C812F114142E61803D9DEF /* Pods-SugarRecord_Example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SugarRecord/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
607FACF31AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 54DE24CF394C35117CF642A6 /* Pods-SugarRecord_Tests.debug.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
607FACF41AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EF1427C1C51BC3D125AAFF0F /* Pods-SugarRecord_Tests.release.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SugarRecord" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACED1AFB9204008FA782 /* Debug */,
607FACEE1AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SugarRecord_Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACF01AFB9204008FA782 /* Debug */,
607FACF11AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SugarRecord_Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACF31AFB9204008FA782 /* Debug */,
607FACF41AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
23E13E3E1D96896300204C82 /* DataModel.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
23E13E3F1D96896300204C82 /* DataModel.xcdatamodel */,
);
currentVersion = 23E13E3F1D96896300204C82 /* DataModel.xcdatamodel */;
path = DataModel.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
23E13E741D96899000204C82 /* Basic.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
23E13E751D96899000204C82 /* Basic.xcdatamodel */,
);
currentVersion = 23E13E751D96899000204C82 /* Basic.xcdatamodel */;
path = Basic.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = 607FACC81AFB9204008FA782 /* Project object */;
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23C453141D7789A900483DB4"
BuildableName = "Examples.app"
BlueprintName = "Examples"
ReferencedContainer = "container:Examples.xcodeproj">
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "SugarRecord_Example.app"
BlueprintName = "SugarRecord_Example"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@ -28,14 +28,24 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACE41AFB9204008FA782"
BuildableName = "SugarRecord_Tests.xctest"
BlueprintName = "SugarRecord_Tests"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23C453141D7789A900483DB4"
BuildableName = "Examples.app"
BlueprintName = "Examples"
ReferencedContainer = "container:Examples.xcodeproj">
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "SugarRecord_Example.app"
BlueprintName = "SugarRecord_Example"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
@ -55,10 +65,10 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23C453141D7789A900483DB4"
BuildableName = "Examples.app"
BlueprintName = "Examples"
ReferencedContainer = "container:Examples.xcodeproj">
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "SugarRecord_Example.app"
BlueprintName = "SugarRecord_Example"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
@ -74,10 +84,10 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23C453141D7789A900483DB4"
BuildableName = "Examples.app"
BlueprintName = "Examples"
ReferencedContainer = "container:Examples.xcodeproj">
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "SugarRecord_Example.app"
BlueprintName = "SugarRecord_Example"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>

View File

@ -16,10 +16,10 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23EA8C971D6E1550008333A4"
BuildableName = "Tests.xctest"
BlueprintName = "Tests"
ReferencedContainer = "container:Examples.xcodeproj">
BlueprintIdentifier = "607FACE41AFB9204008FA782"
BuildableName = "SugarRecord_Tests.xctest"
BlueprintName = "SugarRecord_Tests"
ReferencedContainer = "container:SugarRecord.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>

View File

@ -2,7 +2,7 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Examples.xcodeproj">
location = "group:SugarRecord.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">

View File

@ -32,7 +32,6 @@
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -7,9 +7,9 @@ class CoreDataBasicView: UIViewController, UITableViewDelegate, UITableViewDataS
// MARK: - Attributes
lazy var db: CoreDataDefaultStorage = {
let store = CoreData.Store.Named("cd_basic")
let store = CoreDataStore.named("cd_basic")
let bundle = Bundle(for: CoreDataBasicView.classForCoder())
let model = CoreData.ObjectModel.Merged([bundle])
let model = CoreDataObjectModel.merged([bundle])
let defaultStorage = try! CoreDataDefaultStorage(store: store, model: model)
return defaultStorage
}()
@ -123,6 +123,6 @@ class CoreDataBasicView: UIViewController, UITableViewDelegate, UITableViewDataS
// MARK: - Private
fileprivate func updateData() {
self.entities = try! db.fetch(Request<BasicObject>()).map(CoreDataBasicEntity.init)
self.entities = try! db.fetch(FetchRequest<BasicObject>()).map(CoreDataBasicEntity.init)
}
}

View File

@ -122,6 +122,6 @@ class RealmBasicView: UIViewController, UITableViewDelegate, UITableViewDataSour
// MARK: - Private
fileprivate func updateData() {
self.entities = try! db.fetch(Request<RealmBasicObject>()).map(RealmBasicEntity.init)
self.entities = try! db.fetch(FetchRequest<RealmBasicObject>()).map(RealmBasicEntity.init)
}
}

View File

@ -1,934 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
2355ADF91D91C0D300836EF6 /* CoreDataObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F38C1D77945A0086ADC7 /* CoreDataObservableTests.swift */; };
23C453481D778CE000483DB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23C453291D778CE000483DB4 /* Assets.xcassets */; };
23C453491D778CE000483DB4 /* Basic.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 23C4532B1D778CE000483DB4 /* Basic.xcdatamodeld */; };
23C4534A1D778CE000483DB4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23C4532E1D778CE000483DB4 /* LaunchScreen.storyboard */; };
23C4534B1D778CE000483DB4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453311D778CE000483DB4 /* AppDelegate.swift */; };
23C4534C1D778CE000483DB4 /* CoreDataBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453351D778CE000483DB4 /* CoreDataBasicView.swift */; };
23C4534D1D778CE000483DB4 /* BasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453371D778CE000483DB4 /* BasicObject.swift */; };
23C4534E1D778CE000483DB4 /* CoreDataBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453381D778CE000483DB4 /* CoreDataBasicEntity.swift */; };
23C453501D778CE000483DB4 /* RealmBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C4533D1D778CE000483DB4 /* RealmBasicView.swift */; };
23C453511D778CE000483DB4 /* RealmBasicEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C4533F1D778CE000483DB4 /* RealmBasicEntity.swift */; };
23C453521D778CE000483DB4 /* RealmBasicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453401D778CE000483DB4 /* RealmBasicObject.swift */; };
23C453541D778CE000483DB4 /* Directory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453441D778CE000483DB4 /* Directory.swift */; };
23C453551D778CE000483DB4 /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453451D778CE000483DB4 /* Random.swift */; };
23C453561D778CE000483DB4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C453471D778CE000483DB4 /* ViewController.swift */; };
23C6F3A41D77945A0086ADC7 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F37C1D77945A0086ADC7 /* CoreData.swift */; };
23C6F3A51D77945A0086ADC7 /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F37D1D77945A0086ADC7 /* Realm.swift */; };
23C6F3A61D77945A0086ADC7 /* Track+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3801D77945A0086ADC7 /* Track+CoreDataProperties.swift */; };
23C6F3A71D77945A0086ADC7 /* Track.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3811D77945A0086ADC7 /* Track.swift */; };
23C6F3A81D77945A0086ADC7 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3831D77945A0086ADC7 /* Issue.swift */; };
23C6F3A91D77945A0086ADC7 /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3841D77945A0086ADC7 /* Repository.swift */; };
23C6F3AA1D77945A0086ADC7 /* DataModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3861D77945A0086ADC7 /* DataModel.xcdatamodeld */; };
23C6F3AB1D77945A0086ADC7 /* CoreDataChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F38B1D77945A0086ADC7 /* CoreDataChangeTests.swift */; };
23C6F3AD1D77945A0086ADC7 /* ObjectModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F38D1D77945A0086ADC7 /* ObjectModelTests.swift */; };
23C6F3AE1D77945A0086ADC7 /* OptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F38E1D77945A0086ADC7 /* OptionsTests.swift */; };
23C6F3AF1D77945A0086ADC7 /* StoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F38F1D77945A0086ADC7 /* StoreTests.swift */; };
23C6F3B01D77945A0086ADC7 /* CoreDataDefaultStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3911D77945A0086ADC7 /* CoreDataDefaultStorageTests.swift */; };
23C6F3B11D77945A0086ADC7 /* RequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3941D77945A0086ADC7 /* RequestTests.swift */; };
23C6F3B21D77945A0086ADC7 /* DirUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3961D77945A0086ADC7 /* DirUtilsTests.swift */; };
23C6F3B31D77945A0086ADC7 /* VersionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3981D77945A0086ADC7 /* VersionControllerTests.swift */; };
23C6F3B41D77945A0086ADC7 /* VersionProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3991D77945A0086ADC7 /* VersionProviderTests.swift */; };
23C6F3B61D77945A0086ADC7 /* RealmObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F39E1D77945A0086ADC7 /* RealmObservableTests.swift */; };
23C6F3B71D77945A0086ADC7 /* RealmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3A01D77945A0086ADC7 /* RealmTests.swift */; };
23C6F3B81D77945A0086ADC7 /* ResultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3A11D77945A0086ADC7 /* ResultsTests.swift */; };
23C6F3B91D77945A0086ADC7 /* RealmDefaultStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23C6F3A31D77945A0086ADC7 /* RealmDefaultStorageTests.swift */; };
77E7620FDA08FDB760020698 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69A5A24E621A39568E861BD3 /* Pods_Tests.framework */; };
CA389ACF0976C09199339883 /* Pods_Examples.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF27D17BD889796347061DB /* Pods_Examples.framework */; };
D452E5FE2867BD0C350E8513 /* Pods_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB7678692882EFC39927FB5 /* Pods_iOS.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0513623BA0E3B353159F3CE0 /* Pods-Examples.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Examples.release.xcconfig"; path = "Pods/Target Support Files/Pods-Examples/Pods-Examples.release.xcconfig"; sourceTree = "<group>"; };
0A4E7F9F3F335546243A9A30 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = "<group>"; };
1CB7678692882EFC39927FB5 /* Pods_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
23C4530F1D77899A00483DB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
23C453151D7789A900483DB4 /* Examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Examples.app; sourceTree = BUILT_PRODUCTS_DIR; };
23C453291D778CE000483DB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
23C4532C1D778CE000483DB4 /* Basic.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Basic.xcdatamodel; sourceTree = "<group>"; };
23C4532E1D778CE000483DB4 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
23C453311D778CE000483DB4 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
23C453351D778CE000483DB4 /* CoreDataBasicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataBasicView.swift; sourceTree = "<group>"; };
23C453371D778CE000483DB4 /* BasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicObject.swift; sourceTree = "<group>"; };
23C453381D778CE000483DB4 /* CoreDataBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataBasicEntity.swift; sourceTree = "<group>"; };
23C4533D1D778CE000483DB4 /* RealmBasicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicView.swift; sourceTree = "<group>"; };
23C4533F1D778CE000483DB4 /* RealmBasicEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicEntity.swift; sourceTree = "<group>"; };
23C453401D778CE000483DB4 /* RealmBasicObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBasicObject.swift; sourceTree = "<group>"; };
23C453441D778CE000483DB4 /* Directory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Directory.swift; sourceTree = "<group>"; };
23C453451D778CE000483DB4 /* Random.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Random.swift; sourceTree = "<group>"; };
23C453471D778CE000483DB4 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
23C453571D778D0C00483DB4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
23C6F37C1D77945A0086ADC7 /* CoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreData.swift; sourceTree = "<group>"; };
23C6F37D1D77945A0086ADC7 /* Realm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = "<group>"; };
23C6F3801D77945A0086ADC7 /* Track+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Track+CoreDataProperties.swift"; sourceTree = "<group>"; };
23C6F3811D77945A0086ADC7 /* Track.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Track.swift; sourceTree = "<group>"; };
23C6F3831D77945A0086ADC7 /* Issue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = "<group>"; };
23C6F3841D77945A0086ADC7 /* Repository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Repository.swift; sourceTree = "<group>"; };
23C6F3871D77945A0086ADC7 /* DataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = DataModel.xcdatamodel; sourceTree = "<group>"; };
23C6F38B1D77945A0086ADC7 /* CoreDataChangeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataChangeTests.swift; sourceTree = "<group>"; };
23C6F38C1D77945A0086ADC7 /* CoreDataObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataObservableTests.swift; sourceTree = "<group>"; };
23C6F38D1D77945A0086ADC7 /* ObjectModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectModelTests.swift; sourceTree = "<group>"; };
23C6F38E1D77945A0086ADC7 /* OptionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionsTests.swift; sourceTree = "<group>"; };
23C6F38F1D77945A0086ADC7 /* StoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreTests.swift; sourceTree = "<group>"; };
23C6F3911D77945A0086ADC7 /* CoreDataDefaultStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataDefaultStorageTests.swift; sourceTree = "<group>"; };
23C6F3941D77945A0086ADC7 /* RequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestTests.swift; sourceTree = "<group>"; };
23C6F3961D77945A0086ADC7 /* DirUtilsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DirUtilsTests.swift; sourceTree = "<group>"; };
23C6F3981D77945A0086ADC7 /* VersionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionControllerTests.swift; sourceTree = "<group>"; };
23C6F3991D77945A0086ADC7 /* VersionProviderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionProviderTests.swift; sourceTree = "<group>"; };
23C6F39E1D77945A0086ADC7 /* RealmObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmObservableTests.swift; sourceTree = "<group>"; };
23C6F3A01D77945A0086ADC7 /* RealmTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmTests.swift; sourceTree = "<group>"; };
23C6F3A11D77945A0086ADC7 /* ResultsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultsTests.swift; sourceTree = "<group>"; };
23C6F3A31D77945A0086ADC7 /* RealmDefaultStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmDefaultStorageTests.swift; sourceTree = "<group>"; };
23EA8C981D6E1550008333A4 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
29FE2CCE96C3CB24F2954B8A /* Pods-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-iOS/Pods-iOS.release.xcconfig"; sourceTree = "<group>"; };
3146263D2EBCDCBA7B053003 /* Pods-Examples.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Examples.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Examples/Pods-Examples.debug.xcconfig"; sourceTree = "<group>"; };
3AF27D17BD889796347061DB /* Pods_Examples.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Examples.framework; sourceTree = BUILT_PRODUCTS_DIR; };
56F8AD4459C8BF60E44649EB /* Pods-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-iOS/Pods-iOS.debug.xcconfig"; sourceTree = "<group>"; };
69A5A24E621A39568E861BD3 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9C00DE6B27B62138ECC957C2 /* Pods-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-tvOS/Pods-tvOS.release.xcconfig"; sourceTree = "<group>"; };
A721A8DA47893D4922DCEDA7 /* Pods_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B3D47AFEF33877E2B95F776A /* Pods-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-macOS/Pods-macOS.debug.xcconfig"; sourceTree = "<group>"; };
B4CC78A1AB6E2B57F1B74D12 /* Pods-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-macOS/Pods-macOS.release.xcconfig"; sourceTree = "<group>"; };
D906ABF7477EE74C82C50B21 /* Pods_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DE497EE20078D7F8132B41D0 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = "<group>"; };
FC3C2387D4FB229468B6F59B /* Pods-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tvOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-tvOS/Pods-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
23C453121D7789A900483DB4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CA389ACF0976C09199339883 /* Pods_Examples.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
23EA8C951D6E1550008333A4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D452E5FE2867BD0C350E8513 /* Pods_iOS.framework in Frameworks */,
77E7620FDA08FDB760020698 /* Pods_Tests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
23C4530E1D77899A00483DB4 /* iOS */ = {
isa = PBXGroup;
children = (
23C6F37B1D77945A0086ADC7 /* Helpers */,
23C6F37E1D77945A0086ADC7 /* Models */,
23C6F3851D77945A0086ADC7 /* Resources */,
23C6F3881D77945A0086ADC7 /* Source */,
23C4530F1D77899A00483DB4 /* Info.plist */,
);
path = iOS;
sourceTree = "<group>";
};
23C453161D7789A900483DB4 /* Examples */ = {
isa = PBXGroup;
children = (
23C453571D778D0C00483DB4 /* Info.plist */,
23C453271D778CE000483DB4 /* Resources */,
23C4532F1D778CE000483DB4 /* Source */,
);
path = Examples;
sourceTree = "<group>";
};
23C453271D778CE000483DB4 /* Resources */ = {
isa = PBXGroup;
children = (
23C453281D778CE000483DB4 /* Assets */,
23C4532A1D778CE000483DB4 /* DataModels */,
23C4532D1D778CE000483DB4 /* Storyboards */,
);
path = Resources;
sourceTree = "<group>";
};
23C453281D778CE000483DB4 /* Assets */ = {
isa = PBXGroup;
children = (
23C453291D778CE000483DB4 /* Assets.xcassets */,
);
path = Assets;
sourceTree = "<group>";
};
23C4532A1D778CE000483DB4 /* DataModels */ = {
isa = PBXGroup;
children = (
23C4532B1D778CE000483DB4 /* Basic.xcdatamodeld */,
);
path = DataModels;
sourceTree = "<group>";
};
23C4532D1D778CE000483DB4 /* Storyboards */ = {
isa = PBXGroup;
children = (
23C4532E1D778CE000483DB4 /* LaunchScreen.storyboard */,
);
path = Storyboards;
sourceTree = "<group>";
};
23C4532F1D778CE000483DB4 /* Source */ = {
isa = PBXGroup;
children = (
23C453301D778CE000483DB4 /* App */,
23C453321D778CE000483DB4 /* Examples */,
23C453431D778CE000483DB4 /* Helpers */,
23C453461D778CE000483DB4 /* Main */,
);
path = Source;
sourceTree = "<group>";
};
23C453301D778CE000483DB4 /* App */ = {
isa = PBXGroup;
children = (
23C453311D778CE000483DB4 /* AppDelegate.swift */,
);
path = App;
sourceTree = "<group>";
};
23C453321D778CE000483DB4 /* Examples */ = {
isa = PBXGroup;
children = (
23C453331D778CE000483DB4 /* CoreData */,
23C4533B1D778CE000483DB4 /* Realm */,
);
path = Examples;
sourceTree = "<group>";
};
23C453331D778CE000483DB4 /* CoreData */ = {
isa = PBXGroup;
children = (
23C453341D778CE000483DB4 /* Basic */,
23C453361D778CE000483DB4 /* Models */,
);
path = CoreData;
sourceTree = "<group>";
};
23C453341D778CE000483DB4 /* Basic */ = {
isa = PBXGroup;
children = (
23C453351D778CE000483DB4 /* CoreDataBasicView.swift */,
);
path = Basic;
sourceTree = "<group>";
};
23C453361D778CE000483DB4 /* Models */ = {
isa = PBXGroup;
children = (
23C453371D778CE000483DB4 /* BasicObject.swift */,
23C453381D778CE000483DB4 /* CoreDataBasicEntity.swift */,
);
path = Models;
sourceTree = "<group>";
};
23C4533B1D778CE000483DB4 /* Realm */ = {
isa = PBXGroup;
children = (
23C4533C1D778CE000483DB4 /* Basic */,
23C4533E1D778CE000483DB4 /* Models */,
);
path = Realm;
sourceTree = "<group>";
};
23C4533C1D778CE000483DB4 /* Basic */ = {
isa = PBXGroup;
children = (
23C4533D1D778CE000483DB4 /* RealmBasicView.swift */,
);
path = Basic;
sourceTree = "<group>";
};
23C4533E1D778CE000483DB4 /* Models */ = {
isa = PBXGroup;
children = (
23C4533F1D778CE000483DB4 /* RealmBasicEntity.swift */,
23C453401D778CE000483DB4 /* RealmBasicObject.swift */,
);
path = Models;
sourceTree = "<group>";
};
23C453431D778CE000483DB4 /* Helpers */ = {
isa = PBXGroup;
children = (
23C453441D778CE000483DB4 /* Directory.swift */,
23C453451D778CE000483DB4 /* Random.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
23C453461D778CE000483DB4 /* Main */ = {
isa = PBXGroup;
children = (
23C453471D778CE000483DB4 /* ViewController.swift */,
);
path = Main;
sourceTree = "<group>";
};
23C6F37B1D77945A0086ADC7 /* Helpers */ = {
isa = PBXGroup;
children = (
23C6F37C1D77945A0086ADC7 /* CoreData.swift */,
23C6F37D1D77945A0086ADC7 /* Realm.swift */,
);
name = Helpers;
path = ../../Tests/Helpers;
sourceTree = "<group>";
};
23C6F37E1D77945A0086ADC7 /* Models */ = {
isa = PBXGroup;
children = (
23C6F37F1D77945A0086ADC7 /* CoreData */,
23C6F3821D77945A0086ADC7 /* Realm */,
);
name = Models;
path = ../../Tests/Models;
sourceTree = "<group>";
};
23C6F37F1D77945A0086ADC7 /* CoreData */ = {
isa = PBXGroup;
children = (
23C6F3801D77945A0086ADC7 /* Track+CoreDataProperties.swift */,
23C6F3811D77945A0086ADC7 /* Track.swift */,
);
path = CoreData;
sourceTree = "<group>";
};
23C6F3821D77945A0086ADC7 /* Realm */ = {
isa = PBXGroup;
children = (
23C6F3831D77945A0086ADC7 /* Issue.swift */,
23C6F3841D77945A0086ADC7 /* Repository.swift */,
);
path = Realm;
sourceTree = "<group>";
};
23C6F3851D77945A0086ADC7 /* Resources */ = {
isa = PBXGroup;
children = (
23C6F3861D77945A0086ADC7 /* DataModel.xcdatamodeld */,
);
name = Resources;
path = ../../Tests/Resources;
sourceTree = "<group>";
};
23C6F3881D77945A0086ADC7 /* Source */ = {
isa = PBXGroup;
children = (
23C6F3891D77945A0086ADC7 /* CoreData */,
23C6F3921D77945A0086ADC7 /* Foundation */,
23C6F39C1D77945A0086ADC7 /* Realm */,
);
name = Source;
path = ../../Tests/Source;
sourceTree = "<group>";
};
23C6F3891D77945A0086ADC7 /* CoreData */ = {
isa = PBXGroup;
children = (
23C6F38A1D77945A0086ADC7 /* Entities */,
23C6F3901D77945A0086ADC7 /* Storage */,
);
path = CoreData;
sourceTree = "<group>";
};
23C6F38A1D77945A0086ADC7 /* Entities */ = {
isa = PBXGroup;
children = (
23C6F38B1D77945A0086ADC7 /* CoreDataChangeTests.swift */,
23C6F38C1D77945A0086ADC7 /* CoreDataObservableTests.swift */,
23C6F38D1D77945A0086ADC7 /* ObjectModelTests.swift */,
23C6F38E1D77945A0086ADC7 /* OptionsTests.swift */,
23C6F38F1D77945A0086ADC7 /* StoreTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23C6F3901D77945A0086ADC7 /* Storage */ = {
isa = PBXGroup;
children = (
23C6F3911D77945A0086ADC7 /* CoreDataDefaultStorageTests.swift */,
);
path = Storage;
sourceTree = "<group>";
};
23C6F3921D77945A0086ADC7 /* Foundation */ = {
isa = PBXGroup;
children = (
23C6F3931D77945A0086ADC7 /* Entities */,
23C6F3951D77945A0086ADC7 /* Utils */,
23C6F3971D77945A0086ADC7 /* Version */,
);
path = Foundation;
sourceTree = "<group>";
};
23C6F3931D77945A0086ADC7 /* Entities */ = {
isa = PBXGroup;
children = (
23C6F3941D77945A0086ADC7 /* RequestTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23C6F3951D77945A0086ADC7 /* Utils */ = {
isa = PBXGroup;
children = (
23C6F3961D77945A0086ADC7 /* DirUtilsTests.swift */,
);
path = Utils;
sourceTree = "<group>";
};
23C6F3971D77945A0086ADC7 /* Version */ = {
isa = PBXGroup;
children = (
23C6F3981D77945A0086ADC7 /* VersionControllerTests.swift */,
23C6F3991D77945A0086ADC7 /* VersionProviderTests.swift */,
);
path = Version;
sourceTree = "<group>";
};
23C6F39C1D77945A0086ADC7 /* Realm */ = {
isa = PBXGroup;
children = (
23C6F39D1D77945A0086ADC7 /* Entities */,
23C6F39F1D77945A0086ADC7 /* Extensions */,
23C6F3A21D77945A0086ADC7 /* Storages */,
);
path = Realm;
sourceTree = "<group>";
};
23C6F39D1D77945A0086ADC7 /* Entities */ = {
isa = PBXGroup;
children = (
23C6F39E1D77945A0086ADC7 /* RealmObservableTests.swift */,
);
path = Entities;
sourceTree = "<group>";
};
23C6F39F1D77945A0086ADC7 /* Extensions */ = {
isa = PBXGroup;
children = (
23C6F3A01D77945A0086ADC7 /* RealmTests.swift */,
23C6F3A11D77945A0086ADC7 /* ResultsTests.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
23C6F3A21D77945A0086ADC7 /* Storages */ = {
isa = PBXGroup;
children = (
23C6F3A31D77945A0086ADC7 /* RealmDefaultStorageTests.swift */,
);
path = Storages;
sourceTree = "<group>";
};
23D592541C2834DC00441B41 = {
isa = PBXGroup;
children = (
23C4530E1D77899A00483DB4 /* iOS */,
23C453161D7789A900483DB4 /* Examples */,
23D5925E1C2834DC00441B41 /* Products */,
80909552933F169F81F9A0A6 /* Pods */,
470583AED253A9BE7D6438D6 /* Frameworks */,
);
sourceTree = "<group>";
};
23D5925E1C2834DC00441B41 /* Products */ = {
isa = PBXGroup;
children = (
23EA8C981D6E1550008333A4 /* Tests.xctest */,
23C453151D7789A900483DB4 /* Examples.app */,
);
name = Products;
sourceTree = "<group>";
};
470583AED253A9BE7D6438D6 /* Frameworks */ = {
isa = PBXGroup;
children = (
3AF27D17BD889796347061DB /* Pods_Examples.framework */,
1CB7678692882EFC39927FB5 /* Pods_iOS.framework */,
D906ABF7477EE74C82C50B21 /* Pods_macOS.framework */,
A721A8DA47893D4922DCEDA7 /* Pods_tvOS.framework */,
69A5A24E621A39568E861BD3 /* Pods_Tests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
80909552933F169F81F9A0A6 /* Pods */ = {
isa = PBXGroup;
children = (
3146263D2EBCDCBA7B053003 /* Pods-Examples.debug.xcconfig */,
0513623BA0E3B353159F3CE0 /* Pods-Examples.release.xcconfig */,
56F8AD4459C8BF60E44649EB /* Pods-iOS.debug.xcconfig */,
29FE2CCE96C3CB24F2954B8A /* Pods-iOS.release.xcconfig */,
B3D47AFEF33877E2B95F776A /* Pods-macOS.debug.xcconfig */,
B4CC78A1AB6E2B57F1B74D12 /* Pods-macOS.release.xcconfig */,
FC3C2387D4FB229468B6F59B /* Pods-tvOS.debug.xcconfig */,
9C00DE6B27B62138ECC957C2 /* Pods-tvOS.release.xcconfig */,
0A4E7F9F3F335546243A9A30 /* Pods-Tests.debug.xcconfig */,
DE497EE20078D7F8132B41D0 /* Pods-Tests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
23C453141D7789A900483DB4 /* Examples */ = {
isa = PBXNativeTarget;
buildConfigurationList = 23C453241D7789A900483DB4 /* Build configuration list for PBXNativeTarget "Examples" */;
buildPhases = (
EB3CC9AFA76F34A0B0284644 /* [CP] Check Pods Manifest.lock */,
23C453111D7789A900483DB4 /* Sources */,
23C453121D7789A900483DB4 /* Frameworks */,
23C453131D7789A900483DB4 /* Resources */,
7D0019523F8A2FB88CBF7792 /* [CP] Embed Pods Frameworks */,
2323E6308DDA8D362D321E7B /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Examples;
productName = Examples;
productReference = 23C453151D7789A900483DB4 /* Examples.app */;
productType = "com.apple.product-type.application";
};
23EA8C971D6E1550008333A4 /* Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 23EA8CA11D6E1550008333A4 /* Build configuration list for PBXNativeTarget "Tests" */;
buildPhases = (
2E37201D6F17CD30684D3A46 /* [CP] Check Pods Manifest.lock */,
23EA8C941D6E1550008333A4 /* Sources */,
23EA8C951D6E1550008333A4 /* Frameworks */,
23EA8C961D6E1550008333A4 /* Resources */,
80D084EE2F81BC3572425C17 /* [CP] Embed Pods Frameworks */,
80E0A87FEE7FEFF76DCD03A2 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Tests;
productName = Tests;
productReference = 23EA8C981D6E1550008333A4 /* Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
23D592551C2834DC00441B41 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = SwiftReactive;
TargetAttributes = {
23C453141D7789A900483DB4 = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 0800;
};
23EA8C971D6E1550008333A4 = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 0800;
TestTargetID = 23D5925C1C2834DC00441B41;
};
};
};
buildConfigurationList = 23D592581C2834DC00441B41 /* Build configuration list for PBXProject "Examples" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 23D592541C2834DC00441B41;
productRefGroup = 23D5925E1C2834DC00441B41 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
23EA8C971D6E1550008333A4 /* Tests */,
23C453141D7789A900483DB4 /* Examples */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
23C453131D7789A900483DB4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23C453481D778CE000483DB4 /* Assets.xcassets in Resources */,
23C4534A1D778CE000483DB4 /* LaunchScreen.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
23EA8C961D6E1550008333A4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
2323E6308DDA8D362D321E7B /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Examples/Pods-Examples-resources.sh\"\n";
showEnvVarsInLog = 0;
};
2E37201D6F17CD30684D3A46 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
7D0019523F8A2FB88CBF7792 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Examples/Pods-Examples-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
80D084EE2F81BC3572425C17 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
80E0A87FEE7FEFF76DCD03A2 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
EB3CC9AFA76F34A0B0284644 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
23C453111D7789A900483DB4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23C453521D778CE000483DB4 /* RealmBasicObject.swift in Sources */,
23C453511D778CE000483DB4 /* RealmBasicEntity.swift in Sources */,
23C4534C1D778CE000483DB4 /* CoreDataBasicView.swift in Sources */,
23C4534D1D778CE000483DB4 /* BasicObject.swift in Sources */,
23C453501D778CE000483DB4 /* RealmBasicView.swift in Sources */,
23C4534B1D778CE000483DB4 /* AppDelegate.swift in Sources */,
23C453561D778CE000483DB4 /* ViewController.swift in Sources */,
23C453551D778CE000483DB4 /* Random.swift in Sources */,
23C453541D778CE000483DB4 /* Directory.swift in Sources */,
23C453491D778CE000483DB4 /* Basic.xcdatamodeld in Sources */,
23C4534E1D778CE000483DB4 /* CoreDataBasicEntity.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
23EA8C941D6E1550008333A4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
23C6F3B11D77945A0086ADC7 /* RequestTests.swift in Sources */,
23C6F3AB1D77945A0086ADC7 /* CoreDataChangeTests.swift in Sources */,
23C6F3A81D77945A0086ADC7 /* Issue.swift in Sources */,
23C6F3B31D77945A0086ADC7 /* VersionControllerTests.swift in Sources */,
23C6F3A41D77945A0086ADC7 /* CoreData.swift in Sources */,
23C6F3AD1D77945A0086ADC7 /* ObjectModelTests.swift in Sources */,
23C6F3B01D77945A0086ADC7 /* CoreDataDefaultStorageTests.swift in Sources */,
23C6F3A51D77945A0086ADC7 /* Realm.swift in Sources */,
23C6F3AA1D77945A0086ADC7 /* DataModel.xcdatamodeld in Sources */,
23C6F3B71D77945A0086ADC7 /* RealmTests.swift in Sources */,
23C6F3A61D77945A0086ADC7 /* Track+CoreDataProperties.swift in Sources */,
23C6F3B21D77945A0086ADC7 /* DirUtilsTests.swift in Sources */,
23C6F3B41D77945A0086ADC7 /* VersionProviderTests.swift in Sources */,
23C6F3B91D77945A0086ADC7 /* RealmDefaultStorageTests.swift in Sources */,
23C6F3AE1D77945A0086ADC7 /* OptionsTests.swift in Sources */,
2355ADF91D91C0D300836EF6 /* CoreDataObservableTests.swift in Sources */,
23C6F3B81D77945A0086ADC7 /* ResultsTests.swift in Sources */,
23C6F3A71D77945A0086ADC7 /* Track.swift in Sources */,
23C6F3A91D77945A0086ADC7 /* Repository.swift in Sources */,
23C6F3AF1D77945A0086ADC7 /* StoreTests.swift in Sources */,
23C6F3B61D77945A0086ADC7 /* RealmObservableTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
23C453251D7789A900483DB4 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3146263D2EBCDCBA7B053003 /* Pods-Examples.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
INFOPLIST_FILE = Examples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = in.caramba.Examples;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
23C453261D7789A900483DB4 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0513623BA0E3B353159F3CE0 /* Pods-Examples.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
INFOPLIST_FILE = Examples/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = in.caramba.Examples;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
23D5926D1C2834DC00441B41 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
23D5926E1C2834DC00441B41 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
23EA8C9F1D6E1550008333A4 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0A4E7F9F3F335546243A9A30 /* Pods-Tests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
INFOPLIST_FILE = iOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.sugarrecord.Tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Examples.app/Examples";
};
name = Debug;
};
23EA8CA01D6E1550008333A4 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = DE497EE20078D7F8132B41D0 /* Pods-Tests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
INFOPLIST_FILE = iOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.sugarrecord.Tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Examples.app/Examples";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
23C453241D7789A900483DB4 /* Build configuration list for PBXNativeTarget "Examples" */ = {
isa = XCConfigurationList;
buildConfigurations = (
23C453251D7789A900483DB4 /* Debug */,
23C453261D7789A900483DB4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
23D592581C2834DC00441B41 /* Build configuration list for PBXProject "Examples" */ = {
isa = XCConfigurationList;
buildConfigurations = (
23D5926D1C2834DC00441B41 /* Debug */,
23D5926E1C2834DC00441B41 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
23EA8CA11D6E1550008333A4 /* Build configuration list for PBXNativeTarget "Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
23EA8C9F1D6E1550008333A4 /* Debug */,
23EA8CA01D6E1550008333A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
23C4532B1D778CE000483DB4 /* Basic.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
23C4532C1D778CE000483DB4 /* Basic.xcdatamodel */,
);
currentVersion = 23C4532C1D778CE000483DB4 /* Basic.xcdatamodel */;
path = Basic.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
23C6F3861D77945A0086ADC7 /* DataModel.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
23C6F3871D77945A0086ADC7 /* DataModel.xcdatamodel */,
);
currentVersion = 23C6F3871D77945A0086ADC7 /* DataModel.xcdatamodel */;
path = DataModel.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = 23D592551C2834DC00441B41 /* Project object */;
}

View File

@ -1,77 +0,0 @@
{
"name": "SugarRecord",
"version": "2.3.1",
"summary": "CoreData & Realmwrapper written on Swift",
"homepage": "https://github.com/carambalabs/SugarRecord",
"license": "MIT",
"authors": {
"Pedro": "pepibumur@gmail.com"
},
"source": {
"git": "https://github.com/carambalabs/SugarRecord.git",
"tag": "2.3.1"
},
"social_media_url": "https://twitter.com/carambalabs",
"requires_arc": true,
"platforms": {
"ios": "8.0",
"osx": "10.10"
},
"subspecs": [
{
"name": "CoreData",
"source_files": [
"SugarRecord/Source/Foundation/**/*.{swift}",
"SugarRecord/Source/CoreData/**/*.{swift}"
],
"exclude_files": [
"SugarRecord/Source/CoreData/Entities/iCloudConfig.swift",
"SugarRecord/Source/CoreData/Storages/CoreDataiCloudStorage.swift"
],
"frameworks": [
"CoreData"
],
"dependencies": {
"Result": [
"~> 3.0"
]
},
"platforms": {
"ios": "8.0",
"osx": "10.10",
"watchos": "2.0",
"tvos": "9.0"
}
},
{
"name": "CoreData+iCloud",
"source_files": [
"SugarRecord/Source/Foundation/**/*.{swift}",
"SugarRecord/Source/CoreData/**/*.{swift}"
],
"frameworks": [
"CoreData"
],
"dependencies": {
"Result": [
"~> 3.0"
]
}
},
{
"name": "Realm",
"source_files": [
"SugarRecord/Source/Foundation/**/*.{swift}",
"SugarRecord/Source/Realm/**/*.{swift}"
],
"dependencies": {
"RealmSwift": [
"~> 1.1"
],
"Result": [
"~> 3.0"
]
}
}
]
}

View File

@ -1,73 +0,0 @@
PODS:
- Nimble (5.0.0)
- OHHTTPStubs (5.2.1):
- OHHTTPStubs/Default (= 5.2.1)
- OHHTTPStubs/Core (5.2.1)
- OHHTTPStubs/Default (5.2.1):
- OHHTTPStubs/Core
- OHHTTPStubs/JSON
- OHHTTPStubs/NSURLSession
- OHHTTPStubs/OHPathHelpers
- OHHTTPStubs/JSON (5.2.1):
- OHHTTPStubs/Core
- OHHTTPStubs/NSURLSession (5.2.1):
- OHHTTPStubs/Core
- OHHTTPStubs/OHPathHelpers (5.2.1)
- OHHTTPStubs/Swift (5.2.1):
- OHHTTPStubs/Core
- Quick (0.9.3)
- Realm (1.1.0):
- Realm/Headers (= 1.1.0)
- Realm/Headers (1.1.0)
- RealmSwift (1.1.0):
- Realm (= 1.1.0)
- Result (3.0.0)
- SnapKit (3.0.1)
- SugarRecord (2.3.1):
- SugarRecord/CoreData (= 2.3.1)
- SugarRecord/CoreData+iCloud (= 2.3.1)
- SugarRecord/Realm (= 2.3.1)
- SugarRecord/CoreData (2.3.1):
- Result (~> 3.0)
- SugarRecord/CoreData+iCloud (2.3.1):
- Result (~> 3.0)
- SugarRecord/Realm (2.3.1):
- RealmSwift (~> 1.1)
- Result (~> 3.0)
DEPENDENCIES:
- Nimble (~> 5.0)
- OHHTTPStubs
- OHHTTPStubs/Swift
- Quick (from `https://github.com/quick/quick.git`, branch `swift-3.0`)
- SnapKit
- SugarRecord (from `../`)
- SugarRecord/CoreData (from `../`)
- SugarRecord/CoreData+iCloud (from `../`)
- SugarRecord/Realm (from `../`)
EXTERNAL SOURCES:
Quick:
:branch: swift-3.0
:git: https://github.com/quick/quick.git
SugarRecord:
:path: "../"
CHECKOUT OPTIONS:
Quick:
:commit: 36ebbc75e093c7553a5145ed5dd21484364cd78d
:git: https://github.com/quick/quick.git
SPEC CHECKSUMS:
Nimble: 56fc9f5020effa2206de22c3dd910f4fb011b92f
OHHTTPStubs: 3a42f25c00563b71355ac73112ba2324e9e6cef4
Quick: 31fb576b6cbb6b028cc5e0016e4366accbb346f5
Realm: ceecf1a4540c4ce9efe196fe73fa9855bce05bd8
RealmSwift: 838058b2db95b12cb86bd0cf209df642c33fb60a
Result: 1b3e431f37cbcd3ad89c6aa9ab0ae55515fae3b6
SnapKit: f818b8326d45b4e1c777d0ab27b5c0a3624bfdeb
SugarRecord: 7c972754f31c77561828534c3779166f4334ebd6
PODFILE CHECKSUM: dd311db187c6a1e0623852ea09855f7131cbe784
COCOAPODS: 1.1.0.rc.2

File diff suppressed because it is too large Load Diff

View File

@ -1,269 +0,0 @@
TABLE OF CONTENTS
1. Apache License version 2.0
2. Realm Components
3. Export Compliance
-------------------------------------------------------------------------------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
REALM COMPONENTS
This software contains components with separate copyright and license terms.
Your use of these components is subject to the terms and conditions of the
following licenses.
For the Realm Core component
Realm Core Binary License
Copyright (c) 2011-2014 Realm Inc All rights reserved
Redistribution and use in binary form, with or without modification, is
permitted provided that the following conditions are met:
1. You agree not to attempt to decompile, disassemble, reverse engineer or
otherwise discover the source code from which the binary code was derived.
You may, however, access and obtain a separate license for most of the
source code from which this Software was created, at
http://realm.io/pricing/.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
EXPORT COMPLIANCE
You understand that the Software may contain cryptographic functions that may be
subject to export restrictions, and you represent and warrant that you are not
located in a country that is subject to United States export restriction or embargo,
including Cuba, Iran, North Korea, Sudan, Syria or the Crimea region, and that you
are not on the Department of Commerce list of Denied Persons, Unverified Parties,
or affiliated with a Restricted Entity.
You agree to comply with all export, re-export and import restrictions and
regulations of the Department of Commerce or other agency or authority of the
United States or other applicable countries. You also agree not to transfer, or
authorize the transfer of, directly or indirectly, the Software to any prohibited
country, including Cuba, Iran, North Korea, Sudan, Syria or the Crimea region,
or to any person or organization on or affiliated with the Department of
Commerce lists of Denied Persons, Unverified Parties or Restricted Entities, or
otherwise in violation of any such restrictions or regulations.

View File

@ -1,72 +0,0 @@
![Realm](https://github.com/realm/realm-cocoa/raw/master/logo.png)
Realm is a mobile database that runs directly inside phones, tablets or wearables.
This repository holds the source code for the iOS, OS X, watchOS & tvOS versions of Realm Swift & Realm Objective-C.
## Features
* **Mobile-first:** Realm is the first database built from the ground up to run directly inside phones, tablets and wearables.
* **Simple:** Data is directly [exposed as objects](https://realm.io/docs/objc/latest/#models) and [queryable by code](https://realm.io/docs/objc/latest/#queries), removing the need for ORM's riddled with performance & maintenance issues. Most of our users pick it up intuitively, getting simple apps up & running in minutes.
* **Modern:** Realm supports relationships, generics, vectorization and even Swift.
* **Fast:** Realm is faster than even raw SQLite on common operations, while maintaining an extremely rich feature set.
## Getting Started
Please see the detailed instructions in our docs to add [Realm Objective-C](https://realm.io/docs/objc/latest/#installation) _or_ [Realm Swift](https://realm.io/docs/swift/latest/#installation) to your Xcode project.
## Documentation
### Realm Objective-C
The documentation can be found at [realm.io/docs/objc/latest](https://realm.io/docs/objc/latest).
The API reference is located at [realm.io/docs/objc/latest/api](https://realm.io/docs/objc/latest/api).
### Realm Swift
The documentation can be found at [realm.io/docs/swift/latest](https://realm.io/docs/swift/latest).
The API reference is located at [realm.io/docs/swift/latest/api](https://realm.io/docs/swift/latest/api).
## Getting Help
- **Need help with your code?**: Look for previous questions on the [#realm tag](https://stackoverflow.com/questions/tagged/realm?sort=newest) — or [ask a new question](https://stackoverflow.com/questions/ask?tags=realm). We actively monitor & answer questions on SO!
- **Have a bug to report?** [Open an issue](https://github.com/realm/realm-cocoa/issues/new). If possible, include the version of Realm, a full log, the Realm file, and a project that shows the issue.
- **Have a feature request?** [Open an issue](https://github.com/realm/realm-cocoa/issues/new). Tell us what the feature should do, and why you want the feature.
- Sign up for our [**Community Newsletter**](http://eepurl.com/VEKCn) to get regular tips, learn about other use-cases and get alerted of blogposts and tutorials about Realm.
## Building Realm
In case you don't want to use the precompiled version, you can build Realm yourself from source.
Prerequisites:
* Building Realm requires Xcode 7.3.
* Building Realm documentation requires [jazzy](https://github.com/realm/jazzy)
Once you have all the necessary prerequisites, building Realm.framework just takes a single command: `sh build.sh build`. You'll need an internet connection the first time you build Realm to download the core binary.
Run `sh build.sh help` to see all the actions you can perform (build ios/osx, generate docs, test, etc.).
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for more details!
This project adheres to the [Contributor Covenant Code of Conduct](https://realm.io/conduct).
By participating, you are expected to uphold this code. Please report
unacceptable behavior to [info@realm.io](mailto:info@realm.io).
## License
Realm Objective-C & Realm Swift are published under the Apache 2.0 license.
The underlying core is available under the [Realm Core Binary License](https://github.com/realm/realm-cocoa/blob/master/LICENSE#L210-L243) while we [work to open-source it under the Apache 2.0 license](https://realm.io/docs/objc/latest/#faq).
**This product is not being made available to any person located in Cuba, Iran,
North Korea, Sudan, Syria or the Crimea region, or to any other person that is
not eligible to receive the product under U.S. law.**
## Feedback
**_If you use Realm and are happy with it, all we ask is that you please consider sending out a tweet mentioning [@realm](https://twitter.com/realm) or email [help@realm.io](mailto:help@realm.io) to share your thoughts!_**
**_And if you don't like it, please let us know what you would like improved, so we can fix it!_**
![analytics](https://ga-beacon.appspot.com/UA-50247013-2/realm-cocoa/README?pixel)

View File

@ -1,800 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMAccessor.h"
#import "RLMArray_Private.hpp"
#import "RLMListBase.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObject_Private.hpp"
#import "RLMObservation.hpp"
#import "RLMProperty_Private.h"
#import "RLMRealm_Private.hpp"
#import "RLMResults_Private.h"
#import "RLMSchema_Private.h"
#import "RLMUtil.hpp"
#import "results.hpp"
#import "property.hpp"
#import <objc/runtime.h>
#import <realm/descriptor.hpp>
typedef NS_ENUM(char, RLMAccessorCode) {
RLMAccessorCodeByte,
RLMAccessorCodeShort,
RLMAccessorCodeInt,
RLMAccessorCodeLong,
RLMAccessorCodeLongLong,
RLMAccessorCodeFloat,
RLMAccessorCodeDouble,
RLMAccessorCodeBool,
RLMAccessorCodeString,
RLMAccessorCodeDate,
RLMAccessorCodeData,
RLMAccessorCodeLink,
RLMAccessorCodeArray,
RLMAccessorCodeLinkingObjects,
RLMAccessorCodeAny,
RLMAccessorCodeIntObject,
RLMAccessorCodeFloatObject,
RLMAccessorCodeDoubleObject,
RLMAccessorCodeBoolObject,
};
template<typename T>
static T get(__unsafe_unretained RLMObjectBase *const obj, NSUInteger index) {
RLMVerifyAttached(obj);
return obj->_row.get_table()->get<T>(obj->_info->objectSchema->persisted_properties[index].table_column, obj->_row.get_index());
}
template<typename T>
static NSNumber *getBoxed(__unsafe_unretained RLMObjectBase *const obj, NSUInteger index) {
RLMVerifyAttached(obj);
auto col = obj->_info->objectSchema->persisted_properties[index].table_column;
if (obj->_row.is_null(col)) {
return nil;
}
return @(obj->_row.get_table()->get<T>(col, obj->_row.get_index()));
}
// long getter/setter
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, long long val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_int(colIndex, val);
}
// float getter/setter
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, float val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_float(colIndex, val);
}
// double getter/setter
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, double val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_double(colIndex, val);
}
// bool getter/setter
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, BOOL val) {
RLMVerifyInWriteTransaction(obj);
obj->_row.set_bool(colIndex, val);
}
// string getter/setter
static inline NSString *RLMGetString(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) {
return RLMStringDataToNSString(get<realm::StringData>(obj, colIndex));
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSString *const val) {
RLMVerifyInWriteTransaction(obj);
try {
obj->_row.set_string(colIndex, RLMStringDataWithNSString(val));
}
catch (std::exception const& e) {
@throw RLMException(e);
}
}
// date getter/setter
static inline NSDate *RLMGetDate(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) {
return RLMTimestampToNSDate(get<realm::Timestamp>(obj, colIndex));
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSDate *const date) {
RLMVerifyInWriteTransaction(obj);
if (date) {
obj->_row.set_timestamp(colIndex, RLMTimestampForNSDate(date));
}
else {
obj->_row.set_null(colIndex);
}
}
// data getter/setter
static inline NSData *RLMGetData(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) {
return RLMBinaryDataToNSData(get<realm::BinaryData>(obj, colIndex));
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSData *const data) {
RLMVerifyInWriteTransaction(obj);
try {
obj->_row.set_binary(colIndex, RLMBinaryDataForNSData(data));
}
catch (std::exception const& e) {
@throw RLMException(e);
}
}
static inline RLMObjectBase *RLMGetLinkedObjectForValue(__unsafe_unretained RLMRealm *const realm,
__unsafe_unretained NSString *const className,
__unsafe_unretained id const value,
RLMCreationOptions creationOptions) NS_RETURNS_RETAINED;
static inline RLMObjectBase *RLMGetLinkedObjectForValue(__unsafe_unretained RLMRealm *const realm,
__unsafe_unretained NSString *const className,
__unsafe_unretained id const value,
RLMCreationOptions creationOptions) {
RLMObjectBase *link = RLMDynamicCast<RLMObjectBase>(value);
if (!link || ![link->_objectSchema.className isEqualToString:className]) {
// create from non-rlmobject
return RLMCreateObjectInRealmWithValue(realm, className, value, creationOptions & RLMCreationOptionsCreateOrUpdate);
}
if (link.isInvalidated) {
@throw RLMException(@"Adding a deleted or invalidated object to a Realm is not permitted");
}
if (link->_realm == realm) {
return link;
}
if (creationOptions & RLMCreationOptionsPromoteUnmanaged) {
if (!link->_realm) {
RLMAddObjectToRealm(link, realm, creationOptions & RLMCreationOptionsCreateOrUpdate);
return link;
}
@throw RLMException(@"Can not add objects from a different Realm");
}
// copy from another realm or copy from unmanaged
return RLMCreateObjectInRealmWithValue(realm, className, link, creationOptions & RLMCreationOptionsCreateOrUpdate);
}
// link getter/setter
static inline RLMObjectBase *RLMGetLink(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) {
RLMVerifyAttached(obj);
auto col = obj->_info->objectSchema->persisted_properties[colIndex].table_column;
if (obj->_row.is_null_link(col)) {
return nil;
}
NSUInteger index = obj->_row.get_link(col);
return RLMCreateObjectAccessor(obj->_realm, obj->_info->linkTargetType(colIndex), index);
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained RLMObjectBase *const val) {
RLMVerifyInWriteTransaction(obj);
if (!val) {
obj->_row.nullify_link(colIndex);
return;
}
RLMObjectBase *link = RLMGetLinkedObjectForValue(obj->_realm, val->_objectSchema.className,
val, RLMCreationOptionsPromoteUnmanaged);
// make sure it is the correct type
if (link->_row.get_table() != obj->_row.get_table()->get_link_target(colIndex)) {
@throw RLMException(@"Can't set object of type '%@' to property of type '%@'",
val->_objectSchema.className,
obj->_info->propertyForTableColumn(colIndex).objectClassName);
}
obj->_row.set_link(colIndex, link->_row.get_index());
}
// array getter/setter
static inline RLMArray *RLMGetArray(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) {
RLMVerifyAttached(obj);
auto prop = obj->_info->rlmObjectSchema.properties[colIndex];
return [[RLMArrayLinkView alloc] initWithParent:obj property:prop];
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained id<NSFastEnumeration> const array) {
RLMVerifyInWriteTransaction(obj);
realm::LinkViewRef linkView = obj->_row.get_linklist(colIndex);
// remove all old
// FIXME: make sure delete rules don't purge objects
linkView->clear();
for (RLMObjectBase *link in array) {
RLMObjectBase * addedLink = RLMGetLinkedObjectForValue(obj->_realm, link->_objectSchema.className, link, RLMCreationOptionsPromoteUnmanaged);
linkView->add(addedLink->_row.get_index());
}
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained NSNumber<RLMInt> *const intObject) {
RLMVerifyInWriteTransaction(obj);
if (intObject) {
obj->_row.set_int(colIndex, intObject.longLongValue);
}
else {
obj->_row.set_null(colIndex);
}
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained NSNumber<RLMFloat> *const floatObject) {
RLMVerifyInWriteTransaction(obj);
if (floatObject) {
obj->_row.set_float(colIndex, floatObject.floatValue);
}
else {
obj->_row.set_null(colIndex);
}
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained NSNumber<RLMDouble> *const doubleObject) {
RLMVerifyInWriteTransaction(obj);
if (doubleObject) {
obj->_row.set_double(colIndex, doubleObject.doubleValue);
}
else {
obj->_row.set_null(colIndex);
}
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex,
__unsafe_unretained NSNumber<RLMBool> *const boolObject) {
RLMVerifyInWriteTransaction(obj);
if (boolObject) {
obj->_row.set_bool(colIndex, boolObject.boolValue);
}
else {
obj->_row.set_null(colIndex);
}
}
static inline RLMLinkingObjects *RLMGetLinkingObjects(__unsafe_unretained RLMObjectBase *const obj,
__unsafe_unretained RLMProperty *const property) {
auto& objectInfo = obj->_realm->_info[property.objectClassName];
auto linkingProperty = objectInfo.objectSchema->property_for_name(property.linkOriginPropertyName.UTF8String);
auto backlinkView = obj->_row.get_table()->get_backlink_view(obj->_row.get_index(), objectInfo.table(), linkingProperty->table_column);
realm::Results results(obj->_realm->_realm, std::move(backlinkView));
return [RLMLinkingObjects resultsWithObjectInfo:objectInfo results:std::move(results)];
}
// any getter/setter
static inline id RLMGetAnyProperty(__unsafe_unretained RLMObjectBase *const obj, NSUInteger col_ndx) {
RLMVerifyAttached(obj);
return RLMMixedToObjc(obj->_row.get_mixed(col_ndx));
}
static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger, __unsafe_unretained id) {
RLMVerifyInWriteTransaction(obj);
@throw RLMException(@"Modifying Mixed properties is not supported");
}
// dynamic getter with column closure
static IMP RLMAccessorGetter(RLMProperty *prop, RLMAccessorCode accessorCode) {
NSUInteger index = prop.index;
switch (accessorCode) {
case RLMAccessorCodeByte:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return (char)get<int64_t>(obj, index);
});
case RLMAccessorCodeShort:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return (short)get<int64_t>(obj, index);
});
case RLMAccessorCodeInt:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return (int)get<int64_t>(obj, index);
});
case RLMAccessorCodeLongLong:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return get<int64_t>(obj, index);
});
case RLMAccessorCodeLong:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return (long)get<int64_t>(obj, index);
});
case RLMAccessorCodeFloat:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return get<float>(obj, index);
});
case RLMAccessorCodeDouble:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return get<double>(obj, index);
});
case RLMAccessorCodeBool:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return get<bool>(obj, index);
});
case RLMAccessorCodeString:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetString(obj, index);
});
case RLMAccessorCodeDate:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetDate(obj, index);
});
case RLMAccessorCodeData:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetData(obj, index);
});
case RLMAccessorCodeLink:
return imp_implementationWithBlock(^id(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetLink(obj, index);
});
case RLMAccessorCodeArray:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetArray(obj, index);
});
case RLMAccessorCodeAny:
@throw RLMException(@"Cannot create accessor class for schema with Mixed properties");
case RLMAccessorCodeIntObject:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return getBoxed<int64_t>(obj, index);
});
case RLMAccessorCodeFloatObject:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return getBoxed<float>(obj, index);
});
case RLMAccessorCodeDoubleObject:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return getBoxed<double>(obj, index);
});
case RLMAccessorCodeBoolObject:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return getBoxed<bool>(obj, index);
});
case RLMAccessorCodeLinkingObjects:
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) {
return RLMGetLinkingObjects(obj, prop);
});
}
}
template<typename Function>
static void RLMWrapSetter(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained NSString *const name, Function&& f) {
if (RLMObservationInfo *info = RLMGetObservationInfo(obj->_observationInfo, obj->_row.get_index(), *obj->_info)) {
info->willChange(name);
f();
info->didChange(name);
}
else {
f();
}
}
template<typename ArgType, typename StorageType=ArgType>
static IMP RLMMakeSetter(RLMProperty *prop) {
NSUInteger index = prop.index;
NSString *name = prop.name;
if (prop.isPrimary) {
return imp_implementationWithBlock(^(__unused RLMObjectBase *obj, __unused ArgType val) {
@throw RLMException(@"Primary key can't be changed after an object is inserted.");
});
}
return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj, ArgType val) {
RLMWrapSetter(obj, name, [&] {
RLMSetValue(obj, obj->_info->objectSchema->persisted_properties[index].table_column, static_cast<StorageType>(val));
});
});
}
// dynamic setter with column closure
static IMP RLMAccessorSetter(RLMProperty *prop, RLMAccessorCode accessorCode) {
switch (accessorCode) {
case RLMAccessorCodeByte: return RLMMakeSetter<char, long long>(prop);
case RLMAccessorCodeShort: return RLMMakeSetter<short, long long>(prop);
case RLMAccessorCodeInt: return RLMMakeSetter<int, long long>(prop);
case RLMAccessorCodeLong: return RLMMakeSetter<long, long long>(prop);
case RLMAccessorCodeLongLong: return RLMMakeSetter<long long>(prop);
case RLMAccessorCodeFloat: return RLMMakeSetter<float>(prop);
case RLMAccessorCodeDouble: return RLMMakeSetter<double>(prop);
case RLMAccessorCodeBool: return RLMMakeSetter<BOOL>(prop);
case RLMAccessorCodeString: return RLMMakeSetter<NSString *>(prop);
case RLMAccessorCodeDate: return RLMMakeSetter<NSDate *>(prop);
case RLMAccessorCodeData: return RLMMakeSetter<NSData *>(prop);
case RLMAccessorCodeLink: return RLMMakeSetter<RLMObjectBase *>(prop);
case RLMAccessorCodeArray: return RLMMakeSetter<RLMArray *>(prop);
case RLMAccessorCodeAny: return RLMMakeSetter<id>(prop);
case RLMAccessorCodeIntObject: return RLMMakeSetter<NSNumber<RLMInt> *>(prop);
case RLMAccessorCodeFloatObject: return RLMMakeSetter<NSNumber<RLMFloat> *>(prop);
case RLMAccessorCodeDoubleObject: return RLMMakeSetter<NSNumber<RLMDouble> *>(prop);
case RLMAccessorCodeBoolObject: return RLMMakeSetter<NSNumber<RLMBool> *>(prop);
case RLMAccessorCodeLinkingObjects: return nil;
}
}
// call getter for superclass for property at colIndex
static id RLMSuperGet(RLMObjectBase *obj, NSString *propName) {
typedef id (*getter_type)(RLMObjectBase *, SEL);
RLMProperty *prop = obj->_objectSchema[propName];
Class superClass = class_getSuperclass(obj.class);
getter_type superGetter = (getter_type)[superClass instanceMethodForSelector:prop.getterSel];
return superGetter(obj, prop.getterSel);
}
// call setter for superclass for property at colIndex
static void RLMSuperSet(RLMObjectBase *obj, NSString *propName, id val) {
typedef void (*setter_type)(RLMObjectBase *, SEL, RLMArray *ar);
RLMProperty *prop = obj->_objectSchema[propName];
Class superClass = class_getSuperclass(obj.class);
setter_type superSetter = (setter_type)[superClass instanceMethodForSelector:prop.setterSel];
superSetter(obj, prop.setterSel, val);
}
// getter/setter for unmanaged object
static IMP RLMAccessorUnmanagedGetter(RLMProperty *prop, RLMAccessorCode accessorCode) {
// only override getters for RLMArray and linking objects properties
if (accessorCode == RLMAccessorCodeArray) {
NSString *objectClassName = prop.objectClassName;
NSString *propName = prop.name;
return imp_implementationWithBlock(^(RLMObjectBase *obj) {
id val = RLMSuperGet(obj, propName);
if (!val) {
val = [[RLMArray alloc] initWithObjectClassName:objectClassName];
RLMSuperSet(obj, propName, val);
}
return val;
});
}
else if (accessorCode == RLMAccessorCodeLinkingObjects) {
return imp_implementationWithBlock(^(RLMObjectBase *){
return [RLMResults emptyDetachedResults];
});
}
return nil;
}
static IMP RLMAccessorUnmanagedSetter(RLMProperty *prop, RLMAccessorCode accessorCode) {
// only override getters for RLMArray and linking objects properties
if (accessorCode == RLMAccessorCodeArray) {
NSString *propName = prop.name;
NSString *objectClassName = prop.objectClassName;
return imp_implementationWithBlock(^(RLMObjectBase *obj, id<NSFastEnumeration> ar) {
// make copy when setting (as is the case for all other variants)
RLMArray *unmanagedAr = [[RLMArray alloc] initWithObjectClassName:objectClassName];
[unmanagedAr addObjects:ar];
RLMSuperSet(obj, propName, unmanagedAr);
});
}
return nil;
}
// macros/helpers to generate objc type strings for registering methods
#define GETTER_TYPES(C) C "@:"
#define SETTER_TYPES(C) "v@:" C
// getter type strings
// NOTE: this typecode is really the the first charachter of the objc/runtime.h type
// the @ type maps to multiple core types (string, date, array, mixed, any which are id in objc)
static const char *getterTypeStringForObjcCode(char code) {
switch (code) {
case 's': return GETTER_TYPES("s");
case 'i': return GETTER_TYPES("i");
case 'l': return GETTER_TYPES("l");
case 'q': return GETTER_TYPES("q");
case 'f': return GETTER_TYPES("f");
case 'd': return GETTER_TYPES("d");
case 'B': return GETTER_TYPES("B");
case 'c': return GETTER_TYPES("c");
case '@': return GETTER_TYPES("@");
default: @throw RLMException(@"Invalid accessor code");
}
}
// setter type strings
// NOTE: this typecode is really the the first charachter of the objc/runtime.h type
// the @ type maps to multiple core types (string, date, array, mixed, any which are id in objc)
static const char *setterTypeStringForObjcCode(char code) {
switch (code) {
case 's': return SETTER_TYPES("s");
case 'i': return SETTER_TYPES("i");
case 'l': return SETTER_TYPES("l");
case 'q': return SETTER_TYPES("q");
case 'f': return SETTER_TYPES("f");
case 'd': return SETTER_TYPES("d");
case 'B': return SETTER_TYPES("B");
case 'c': return SETTER_TYPES("c");
case '@': return SETTER_TYPES("@");
default: @throw RLMException(@"Invalid accessor code");
}
}
// get accessor lookup code based on objc type and rlm type
static RLMAccessorCode accessorCodeForType(char objcTypeCode, RLMPropertyType rlmType) {
switch (objcTypeCode) {
case 't': return RLMAccessorCodeArray;
case '@': // custom accessors for strings and subtables
switch (rlmType) { // custom accessor codes for types that map to objc objects
case RLMPropertyTypeObject: return RLMAccessorCodeLink;
case RLMPropertyTypeString: return RLMAccessorCodeString;
case RLMPropertyTypeArray: return RLMAccessorCodeArray;
case RLMPropertyTypeDate: return RLMAccessorCodeDate;
case RLMPropertyTypeData: return RLMAccessorCodeData;
case RLMPropertyTypeAny: return RLMAccessorCodeAny;
case RLMPropertyTypeBool: return RLMAccessorCodeBoolObject;
case RLMPropertyTypeDouble: return RLMAccessorCodeDoubleObject;
case RLMPropertyTypeFloat: return RLMAccessorCodeFloatObject;
case RLMPropertyTypeInt: return RLMAccessorCodeIntObject;
case RLMPropertyTypeLinkingObjects: return RLMAccessorCodeLinkingObjects;
}
case 'c':
switch (rlmType) {
case RLMPropertyTypeInt: return RLMAccessorCodeByte;
case RLMPropertyTypeBool: return RLMAccessorCodeBool;
default:
@throw RLMException(@"Unexpected property type for Objective-C type code");
}
case 'B': return RLMAccessorCodeBool;
case 's': return RLMAccessorCodeShort;
case 'i': return RLMAccessorCodeInt;
case 'l': return RLMAccessorCodeLong;
case 'q': return RLMAccessorCodeLongLong;
case 'f': return RLMAccessorCodeFloat;
case 'd': return RLMAccessorCodeDouble;
default:
@throw RLMException(@"Invalid type for objc typecode");
}
}
// implement the class method className on accessors to return the className of the
// base object
void RLMReplaceClassNameMethod(Class accessorClass, NSString *className) {
Class metaClass = object_getClass(accessorClass);
IMP imp = imp_implementationWithBlock(^(Class){ return className; });
class_addMethod(metaClass, @selector(className), imp, "@@:");
}
// implement the shared schema method
void RLMReplaceSharedSchemaMethod(Class accessorClass, RLMObjectSchema *schema) {
Class metaClass = object_getClass(accessorClass);
IMP imp = imp_implementationWithBlock(^(Class cls) {
if (cls == accessorClass) {
return schema;
}
// If we aren't being called directly on the class this was overriden
// for, the class is either a subclass which we haven't initialized yet,
// or it's a runtime-generated class which should use the parent's
// schema. We check for the latter by checking if the immediate
// descendent of the desired class is a class generated by us (there
// may be further subclasses not generated by us for things like KVO).
Class parent = class_getSuperclass(cls);
while (parent != accessorClass) {
cls = parent;
parent = class_getSuperclass(cls);
}
if (RLMIsGeneratedClass(cls)) {
return schema;
}
return [RLMSchema sharedSchemaForClass:cls];
});
class_addMethod(metaClass, @selector(sharedSchema), imp, "@@:");
}
static NSMutableSet *s_generatedClasses = [NSMutableSet new];
static void RLMMarkClassAsGenerated(Class cls) {
@synchronized (s_generatedClasses) {
[s_generatedClasses addObject:cls];
}
}
bool RLMIsGeneratedClass(Class cls) {
@synchronized (s_generatedClasses) {
return [s_generatedClasses containsObject:cls];
}
}
static Class RLMCreateAccessorClass(Class objectClass,
RLMObjectSchema *schema,
NSString *accessorClassPrefix,
IMP (*getterGetter)(RLMProperty *, RLMAccessorCode),
IMP (*setterGetter)(RLMProperty *, RLMAccessorCode)) {
// throw if no schema, prefix, or object class
if (!objectClass || !schema || !accessorClassPrefix) {
@throw RLMException(@"Missing arguments");
}
if (!RLMIsObjectOrSubclass(objectClass)) {
@throw RLMException(@"objectClass must derive from RLMObject or Object");
}
// create and register proxy class which derives from object class
NSString *accessorClassName = [accessorClassPrefix stringByAppendingString:schema.className];
Class accClass = objc_getClass(accessorClassName.UTF8String);
if (!accClass) {
accClass = objc_allocateClassPair(objectClass, accessorClassName.UTF8String, 0);
objc_registerClassPair(accClass);
}
// override getters/setters for each propery
NSArray *allProperties = [schema.properties arrayByAddingObjectsFromArray:schema.computedProperties];
for (RLMProperty *prop in allProperties) {
RLMAccessorCode accessorCode = accessorCodeForType(prop.objcType, prop.type);
if (prop.getterSel && getterGetter) {
IMP getterImp = getterGetter(prop, accessorCode);
if (getterImp) {
class_replaceMethod(accClass, prop.getterSel, getterImp, getterTypeStringForObjcCode(prop.objcType));
}
}
if (prop.setterSel && setterGetter) {
IMP setterImp = setterGetter(prop, accessorCode);
if (setterImp) {
class_replaceMethod(accClass, prop.setterSel, setterImp, setterTypeStringForObjcCode(prop.objcType));
}
}
}
RLMMarkClassAsGenerated(accClass);
return accClass;
}
Class RLMAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema, NSString *prefix) {
return RLMCreateAccessorClass(objectClass, schema, prefix, RLMAccessorGetter, RLMAccessorSetter);
}
Class RLMUnmanagedAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema) {
return RLMCreateAccessorClass(objectClass, schema, @"RLMUnmanaged_",
RLMAccessorUnmanagedGetter, RLMAccessorUnmanagedSetter);
}
void RLMDynamicValidatedSet(RLMObjectBase *obj, NSString *propName, id val) {
RLMObjectSchema *schema = obj->_objectSchema;
RLMProperty *prop = schema[propName];
if (!prop) {
@throw RLMException(@"Invalid property name '%@' for class '%@'.", propName, obj->_objectSchema.className);
}
if (prop.isPrimary) {
@throw RLMException(@"Primary key can't be changed to '%@' after an object is inserted.", val);
}
if (!RLMIsObjectValidForProperty(val, prop)) {
@throw RLMException(@"Invalid property value '%@' for property '%@' of class '%@'", val, propName, obj->_objectSchema.className);
}
RLMDynamicSet(obj, prop, RLMCoerceToNil(val), RLMCreationOptionsPromoteUnmanaged);
}
// Precondition: the property is not a primary key
void RLMDynamicSet(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained RLMProperty *const prop,
__unsafe_unretained id const val, RLMCreationOptions creationOptions) {
REALM_ASSERT_DEBUG(!prop.isPrimary);
auto col = obj->_info->tableColumn(prop);
RLMWrapSetter(obj, prop.name, [&] {
switch (accessorCodeForType(prop.objcType, prop.type)) {
case RLMAccessorCodeByte:
case RLMAccessorCodeShort:
case RLMAccessorCodeInt:
case RLMAccessorCodeLong:
case RLMAccessorCodeLongLong:
RLMSetValue(obj, col, [val longLongValue]);
break;
case RLMAccessorCodeFloat:
RLMSetValue(obj, col, [val floatValue]);
break;
case RLMAccessorCodeDouble:
RLMSetValue(obj, col, [val doubleValue]);
break;
case RLMAccessorCodeBool:
RLMSetValue(obj, col, [val boolValue]);
break;
case RLMAccessorCodeIntObject:
RLMSetValue(obj, col, (NSNumber<RLMInt> *)val);
break;
case RLMAccessorCodeFloatObject:
RLMSetValue(obj, col, (NSNumber<RLMFloat> *)val);
break;
case RLMAccessorCodeDoubleObject:
RLMSetValue(obj, col, (NSNumber<RLMDouble> *)val);
break;
case RLMAccessorCodeBoolObject:
RLMSetValue(obj, col, (NSNumber<RLMBool> *)val);
break;
case RLMAccessorCodeString:
RLMSetValue(obj, col, (NSString *)val);
break;
case RLMAccessorCodeDate:
RLMSetValue(obj, col, (NSDate *)val);
break;
case RLMAccessorCodeData:
RLMSetValue(obj, col, (NSData *)val);
break;
case RLMAccessorCodeLink: {
if (!val || val == NSNull.null) {
RLMSetValue(obj, col, (RLMObjectBase *)nil);
}
else {
RLMSetValue(obj, col, RLMGetLinkedObjectForValue(obj->_realm, prop.objectClassName, val, creationOptions));
}
break;
}
case RLMAccessorCodeArray:
if (!val || val == NSNull.null) {
RLMSetValue(obj, col, (id<NSFastEnumeration>)nil);
}
else {
id<NSFastEnumeration> rawLinks = val;
NSMutableArray *links = [NSMutableArray array];
for (id rawLink in rawLinks) {
[links addObject:RLMGetLinkedObjectForValue(obj->_realm, prop.objectClassName, rawLink, creationOptions)];
}
RLMSetValue(obj, col, links);
}
break;
case RLMAccessorCodeAny:
RLMSetValue(obj, col, val);
break;
case RLMAccessorCodeLinkingObjects:
@throw RLMException(@"Linking objects properties are read-only");
}
});
}
id RLMDynamicGet(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained RLMProperty *const prop) {
auto index = prop.index;
switch (accessorCodeForType(prop.objcType, prop.type)) {
case RLMAccessorCodeIntObject:
case RLMAccessorCodeByte:
case RLMAccessorCodeShort:
case RLMAccessorCodeInt:
case RLMAccessorCodeLong:
case RLMAccessorCodeLongLong: return getBoxed<int64_t>(obj, index);
case RLMAccessorCodeFloatObject:
case RLMAccessorCodeFloat: return getBoxed<float>(obj, index);
case RLMAccessorCodeDoubleObject:
case RLMAccessorCodeDouble: return getBoxed<double>(obj, index);
case RLMAccessorCodeBoolObject:
case RLMAccessorCodeBool: return getBoxed<bool>(obj, index);
case RLMAccessorCodeString: return RLMGetString(obj, index);
case RLMAccessorCodeDate: return RLMGetDate(obj, index);
case RLMAccessorCodeData: return RLMGetData(obj, index);
case RLMAccessorCodeLink: return RLMGetLink(obj, index);
case RLMAccessorCodeArray: return RLMGetArray(obj, index);
case RLMAccessorCodeAny: return RLMGetAnyProperty(obj, index);
case RLMAccessorCodeLinkingObjects: return RLMGetLinkingObjects(obj, prop);
}
}
id RLMDynamicGetByName(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained NSString *const propName, bool asList) {
RLMProperty *prop = obj->_objectSchema[propName];
if (!prop) {
@throw RLMException(@"Invalid property name '%@' for class '%@'.", propName, obj->_objectSchema.className);
}
if (asList && prop.type == RLMPropertyTypeArray && prop.swiftIvar) {
RLMListBase *list = object_getIvar(obj, prop.swiftIvar);
if (!list._rlmArray) {
list._rlmArray = RLMDynamicGet(obj, prop);
}
return list;
}
return RLMDynamicGet(obj, prop);
}

View File

@ -1,240 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
// Asynchronously submits build information to Realm if running in an iOS
// simulator or on OS X if a debugger is attached. Does nothing if running on an
// iOS / watchOS device or if a debugger is *not* attached.
//
// To be clear: this does *not* run when your app is in production or on
// your end-users devices; it will only run in the simulator or when a debugger
// is attached.
//
// Why are we doing this? In short, because it helps us build a better product
// for you. None of the data personally identifies you, your employer or your
// app, but it *will* help us understand what language you use, what iOS
// versions you target, etc. Having this info will help prioritizing our time,
// adding new features and deprecating old features. Collecting an anonymized
// bundle & anonymized MAC is the only way for us to count actual usage of the
// other metrics accurately. If we dont have a way to deduplicate the info
// reported, it will be useless, as a single developer building their Swift app
// 10 times would report 10 times more than a single Objective-C developer that
// only builds once, making the data all but useless.
// No one likes sharing data unless its necessary, we get it, and weve
// debated adding this for a long long time. Since Realm is a free product
// without an email signup, we feel this is a necessary step so we can collect
// relevant data to build a better product for you. If you truly, absolutely
// feel compelled to not send this data back to Realm, then you can set an env
// variable named REALM_DISABLE_ANALYTICS. Since Realm is free we believe
// letting these analytics run is a small price to pay for the product & support
// we give you.
//
// Currently the following information is reported:
// - What version of Realm is being used, and from which language (obj-c or Swift).
// - What version of OS X it's running on (in case Xcode aggressively drops
// support for older versions again, we need to know what we need to support).
// - The minimum iOS/OS X version that the application is targeting (again, to
// help us decide what versions we need to support).
// - An anonymous MAC address and bundle ID to aggregate the other information on.
// - What version of Swift is being used (if applicable).
#import "RLMAnalytics.hpp"
#import <Foundation/Foundation.h>
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_MAC || (TARGET_OS_WATCH && TARGET_OS_SIMULATOR) || (TARGET_OS_TV && TARGET_OS_SIMULATOR)
#import "RLMRealm.h"
#import "RLMUtil.hpp"
#import <array>
#import <sys/socket.h>
#import <sys/sysctl.h>
#import <net/if.h>
#import <net/if_dl.h>
#import <CommonCrypto/CommonDigest.h>
#ifndef REALM_COCOA_VERSION
#import "RLMVersion.h"
#endif
// Declared for RealmSwiftObjectUtil
@interface NSObject (SwiftVersion)
+ (NSString *)swiftVersion;
@end
// Wrapper for sysctl() that handles the memory management stuff
static auto RLMSysCtl(int *mib, u_int mibSize, size_t *bufferSize) {
std::unique_ptr<void, decltype(&free)> buffer(nullptr, &free);
int ret = sysctl(mib, mibSize, nullptr, bufferSize, nullptr, 0);
if (ret != 0) {
return buffer;
}
buffer.reset(malloc(*bufferSize));
if (!buffer) {
return buffer;
}
ret = sysctl(mib, mibSize, buffer.get(), bufferSize, nullptr, 0);
if (ret != 0) {
buffer.reset();
}
return buffer;
}
// Get the version of OS X we're running on (even in the simulator this gives
// the OS X version and not the simulated iOS version)
static NSString *RLMOSVersion() {
std::array<int, 2> mib = {CTL_KERN, KERN_OSRELEASE};
size_t bufferSize;
auto buffer = RLMSysCtl(&mib[0], mib.size(), &bufferSize);
if (!buffer) {
return nil;
}
return [[NSString alloc] initWithBytesNoCopy:buffer.release()
length:bufferSize - 1
encoding:NSUTF8StringEncoding
freeWhenDone:YES];
}
// Hash the data in the given buffer and convert it to a hex-format string
static NSString *RLMHashData(const void *bytes, size_t length) {
unsigned char buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(bytes, static_cast<CC_LONG>(length), buffer);
char formatted[CC_SHA256_DIGEST_LENGTH * 2 + 1];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) {
sprintf(formatted + i * 2, "%02x", buffer[i]);
}
return [[NSString alloc] initWithBytes:formatted
length:CC_SHA256_DIGEST_LENGTH * 2
encoding:NSUTF8StringEncoding];
}
// Returns the hash of the MAC address of the first network adaptor since the
// vendorIdentifier isn't constant between iOS simulators.
static NSString *RLMMACAddress() {
int en0 = static_cast<int>(if_nametoindex("en0"));
if (!en0) {
return nil;
}
std::array<int, 6> mib = {CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, en0};
size_t bufferSize;
auto buffer = RLMSysCtl(&mib[0], mib.size(), &bufferSize);
if (!buffer) {
return nil;
}
// sockaddr_dl struct is immediately after the if_msghdr struct in the buffer
auto sockaddr = reinterpret_cast<sockaddr_dl *>(static_cast<if_msghdr *>(buffer.get()) + 1);
auto mac = reinterpret_cast<const unsigned char *>(sockaddr->sdl_data + sockaddr->sdl_nlen);
return RLMHashData(mac, 6);
}
static NSDictionary *RLMAnalyticsPayload() {
NSBundle *appBundle = NSBundle.mainBundle;
NSString *hashedBundleID = appBundle.bundleIdentifier;
// Main bundle isn't always the one of interest (e.g. when running tests
// it's xctest rather than the app's bundle), so look for one with a bundle ID
if (!hashedBundleID) {
for (NSBundle *bundle in NSBundle.allBundles) {
if ((hashedBundleID = bundle.bundleIdentifier)) {
appBundle = bundle;
break;
}
}
}
// If we found a bundle ID anywhere, hash it as it could contain sensitive
// information (e.g. the name of an unnanounced product)
if (hashedBundleID) {
NSData *data = [hashedBundleID dataUsingEncoding:NSUTF8StringEncoding];
hashedBundleID = RLMHashData(data.bytes, data.length);
}
NSString *osVersionString = [[NSProcessInfo processInfo] operatingSystemVersionString];
Class swiftObjectUtilClass = NSClassFromString(@"RealmSwiftObjectUtil");
BOOL isSwift = swiftObjectUtilClass != nil;
NSString *swiftVersion = isSwift ? [swiftObjectUtilClass swiftVersion] : @"N/A";
static NSString *kUnknownString = @"unknown";
NSString *hashedMACAddress = RLMMACAddress() ?: kUnknownString;
return @{
@"event": @"Run",
@"properties": @{
// MixPanel properties
@"token": @"ce0fac19508f6c8f20066d345d360fd0",
// Anonymous identifiers to deduplicate events
@"distinct_id": hashedMACAddress,
@"Anonymized MAC Address": hashedMACAddress,
@"Anonymized Bundle ID": hashedBundleID ?: kUnknownString,
// Which version of Realm is being used
@"Binding": @"cocoa",
@"Language": isSwift ? @"swift" : @"objc",
@"Realm Version": REALM_COCOA_VERSION,
#if TARGET_OS_WATCH
@"Target OS Type": @"watchos",
#elif TARGET_OS_TV
@"Target OS Type": @"tvos",
#elif TARGET_OS_IPHONE
@"Target OS Type": @"ios",
#else
@"Target OS Type": @"osx",
#endif
@"Swift Version": swiftVersion,
// Current OS version the app is targetting
@"Target OS Version": osVersionString,
// Minimum OS version the app is targetting
@"Target OS Minimum Version": appBundle.infoDictionary[@"MinimumOSVersion"] ?: kUnknownString,
// Host OS version being built on
@"Host OS Type": @"osx",
@"Host OS Version": RLMOSVersion() ?: kUnknownString,
}
};
}
void RLMSendAnalytics() {
if (getenv("REALM_DISABLE_ANALYTICS") || !RLMIsDebuggerAttached() || RLMIsRunningInPlayground()) {
return;
}
NSData *payload = [NSJSONSerialization dataWithJSONObject:RLMAnalyticsPayload() options:0 error:nil];
NSString *url = [NSString stringWithFormat:@"https://api.mixpanel.com/track/?data=%@&ip=1", [payload base64EncodedStringWithOptions:0]];
// No error handling or anything because logging errors annoyed people for no
// real benefit, and it's not clear what else we could do
[[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url]] resume];
}
#else
void RLMSendAnalytics() {}
#endif

View File

@ -1,439 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMArray_Private.hpp"
#import "RLMObject_Private.h"
#import "RLMObjectStore.h"
#import "RLMObjectSchema.h"
#import "RLMQueryUtil.hpp"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
#import <realm/link_view.hpp>
// See -countByEnumeratingWithState:objects:count
@interface RLMArrayHolder : NSObject {
@public
std::unique_ptr<id[]> items;
}
@end
@implementation RLMArrayHolder
@end
@implementation RLMArray {
@public
// Backing array when this instance is unmanaged
NSMutableArray *_backingArray;
}
template<typename IndexSetFactory>
static void changeArray(__unsafe_unretained RLMArray *const ar,
NSKeyValueChange kind, dispatch_block_t f, IndexSetFactory&& is) {
if (!ar->_backingArray) {
ar->_backingArray = [NSMutableArray new];
}
if (RLMObjectBase *parent = ar->_parentObject) {
NSIndexSet *indexes = is();
[parent willChange:kind valuesAtIndexes:indexes forKey:ar->_key];
f();
[parent didChange:kind valuesAtIndexes:indexes forKey:ar->_key];
}
else {
f();
}
}
static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSUInteger index, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndex:index]; });
}
static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSRange range, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndexesInRange:range]; });
}
static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSIndexSet *is, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return is; });
}
- (instancetype)initWithObjectClassName:(__unsafe_unretained NSString *const)objectClassName {
self = [super init];
if (self) {
_objectClassName = objectClassName;
}
return self;
}
- (RLMRealm *)realm {
return nil;
}
//
// Generic implementations for all RLMArray variants
//
- (id)firstObject {
if (self.count) {
return [self objectAtIndex:0];
}
return nil;
}
- (id)lastObject {
NSUInteger count = self.count;
if (count) {
return [self objectAtIndex:count-1];
}
return nil;
}
- (void)addObjects:(id<NSFastEnumeration>)objects {
for (id obj in objects) {
[self addObject:obj];
}
}
- (void)addObject:(RLMObject *)object {
[self insertObject:object atIndex:self.count];
}
- (void)removeLastObject {
NSUInteger count = self.count;
if (count) {
[self removeObjectAtIndex:count-1];
}
}
- (id)objectAtIndexedSubscript:(NSUInteger)index {
return [self objectAtIndex:index];
}
- (void)setObject:(id)newValue atIndexedSubscript:(NSUInteger)index {
[self replaceObjectAtIndex:index withObject:newValue];
}
//
// Unmanaged RLMArray implementation
//
static void RLMValidateMatchingObjectType(RLMArray *array, RLMObject *object) {
if (!object) {
@throw RLMException(@"Object must not be nil");
}
if (!object->_objectSchema) {
@throw RLMException(@"Object cannot be inserted unless the schema is initialized. "
"This can happen if you try to insert objects into a RLMArray / List from a default value or from an overriden unmanaged initializer (`init()`).");
}
if (![array->_objectClassName isEqualToString:object->_objectSchema.className]) {
@throw RLMException(@"Object type '%@' does not match RLMArray type '%@'.",
object->_objectSchema.className, array->_objectClassName);
}
}
static void RLMValidateArrayBounds(__unsafe_unretained RLMArray *const ar,
NSUInteger index, bool allowOnePastEnd=false) {
NSUInteger max = ar->_backingArray.count + allowOnePastEnd;
if (index >= max) {
@throw RLMException(@"Index %llu is out of bounds (must be less than %llu).",
(unsigned long long)index, (unsigned long long)max);
}
}
- (id)objectAtIndex:(NSUInteger)index {
RLMValidateArrayBounds(self, index);
if (!_backingArray) {
_backingArray = [NSMutableArray new];
}
return [_backingArray objectAtIndex:index];
}
- (NSUInteger)count {
return _backingArray.count;
}
- (BOOL)isInvalidated {
return NO;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unused __unsafe_unretained id [])buffer count:(__unused NSUInteger)len {
if (state->state != 0) {
return 0;
}
// We need to enumerate a copy of the backing array so that it doesn't
// reflect changes made during enumeration. This copy has to be autoreleased
// (since there's nowhere for us to store a strong reference), and uses
// RLMArrayHolder rather than an NSArray because NSArray doesn't guarantee
// that it'll use a single contiguous block of memory, and if it doesn't
// we'd need to forward multiple calls to this method to the same NSArray,
// which would require holding a reference to it somewhere.
__autoreleasing RLMArrayHolder *copy = [[RLMArrayHolder alloc] init];
copy->items = std::make_unique<id[]>(self.count);
NSUInteger i = 0;
for (id object in _backingArray) {
copy->items[i++] = object;
}
state->itemsPtr = (__unsafe_unretained id *)(void *)copy->items.get();
// needs to point to something valid, but the whole point of this is so
// that it can't be changed
state->mutationsPtr = state->extra;
state->state = i;
return i;
}
- (void)addObjectsFromArray:(NSArray *)array {
for (id obj in array) {
RLMValidateMatchingObjectType(self, obj);
}
changeArray(self, NSKeyValueChangeInsertion, NSMakeRange(_backingArray.count, array.count), ^{
[_backingArray addObjectsFromArray:array];
});
}
- (void)insertObject:(RLMObject *)anObject atIndex:(NSUInteger)index {
RLMValidateMatchingObjectType(self, anObject);
RLMValidateArrayBounds(self, index, true);
changeArray(self, NSKeyValueChangeInsertion, index, ^{
[_backingArray insertObject:anObject atIndex:index];
});
}
- (void)insertObjects:(id<NSFastEnumeration>)objects atIndexes:(NSIndexSet *)indexes {
changeArray(self, NSKeyValueChangeInsertion, indexes, ^{
NSUInteger currentIndex = [indexes firstIndex];
for (RLMObject *obj in objects) {
RLMValidateMatchingObjectType(self, obj);
[_backingArray insertObject:obj atIndex:currentIndex];
currentIndex = [indexes indexGreaterThanIndex:currentIndex];
}
});
}
- (void)removeObjectAtIndex:(NSUInteger)index {
RLMValidateArrayBounds(self, index);
changeArray(self, NSKeyValueChangeRemoval, index, ^{
[_backingArray removeObjectAtIndex:index];
});
}
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes {
changeArray(self, NSKeyValueChangeRemoval, indexes, ^{
[_backingArray removeObjectsAtIndexes:indexes];
});
}
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
RLMValidateMatchingObjectType(self, anObject);
RLMValidateArrayBounds(self, index);
changeArray(self, NSKeyValueChangeReplacement, index, ^{
[_backingArray replaceObjectAtIndex:index withObject:anObject];
});
}
- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex {
RLMValidateArrayBounds(self, sourceIndex);
RLMValidateArrayBounds(self, destinationIndex);
RLMObjectBase *original = _backingArray[sourceIndex];
auto start = std::min(sourceIndex, destinationIndex);
auto len = std::max(sourceIndex, destinationIndex) - start + 1;
changeArray(self, NSKeyValueChangeReplacement, {start, len}, ^{
[_backingArray removeObjectAtIndex:sourceIndex];
[_backingArray insertObject:original atIndex:destinationIndex];
});
}
- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 {
RLMValidateArrayBounds(self, index1);
RLMValidateArrayBounds(self, index2);
changeArray(self, NSKeyValueChangeReplacement, ^{
[_backingArray exchangeObjectAtIndex:index1 withObjectAtIndex:index2];
}, [=] {
NSMutableIndexSet *set = [[NSMutableIndexSet alloc] initWithIndex:index1];
[set addIndex:index2];
return set;
});
}
- (NSUInteger)indexOfObject:(RLMObject *)object {
RLMValidateMatchingObjectType(self, object);
NSUInteger index = 0;
for (RLMObject *cmp in _backingArray) {
if (RLMObjectBaseAreEqual(object, cmp)) {
return index;
}
index++;
}
return NSNotFound;
}
- (void)removeAllObjects {
changeArray(self, NSKeyValueChangeRemoval, NSMakeRange(0, _backingArray.count), ^{
[_backingArray removeAllObjects];
});
}
- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...
{
va_list args;
va_start(args, predicateFormat);
RLMResults *results = [self objectsWhere:predicateFormat args:args];
va_end(args);
return results;
}
- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args
{
return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}
- (id)valueForKeyPath:(NSString *)keyPath {
if (!_backingArray) {
return [super valueForKeyPath:keyPath];
}
// Although delegating to valueForKeyPath: here would allow to support
// nested key paths as well, limiting functionality gives consistency
// between unmanaged and managed arrays.
if ([keyPath characterAtIndex:0] == '@') {
NSRange operatorRange = [keyPath rangeOfString:@"." options:NSLiteralSearch];
if (operatorRange.location != NSNotFound) {
NSString *operatorKeyPath = [keyPath substringFromIndex:operatorRange.location + 1];
if ([operatorKeyPath rangeOfString:@"."].location != NSNotFound) {
@throw RLMException(@"Nested key paths are not supported yet for KVC collection operators.");
}
}
}
return [_backingArray valueForKeyPath:keyPath];
}
- (id)valueForKey:(NSString *)key {
if ([key isEqualToString:RLMInvalidatedKey]) {
return @NO; // Unmanaged arrays are never invalidated
}
if (!_backingArray) {
return @[];
}
return [_backingArray valueForKey:key];
}
- (void)setValue:(id)value forKey:(NSString *)key {
[_backingArray setValue:value forKey:key];
}
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate {
if (!_backingArray) {
return NSNotFound;
}
return [_backingArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger, BOOL *) {
return [predicate evaluateWithObject:obj];
}];
}
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
if (!_backingArray) {
_backingArray = [NSMutableArray new];
}
return [_backingArray objectsAtIndexes:indexes];
}
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
RLMValidateArrayObservationKey(keyPath, self);
[super addObserver:observer forKeyPath:keyPath options:options context:context];
}
//
// Methods unsupported on unmanaged RLMArray instances
//
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate
{
@throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm");
}
- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending
{
return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]];
}
- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties
{
@throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm");
}
// The compiler complains about the method's argument type not matching due to
// it not having the generic type attached, but it doesn't seem to be possible
// to actually include the generic type
// http://www.openradar.me/radar?id=6135653276319744
#pragma clang diagnostic ignored "-Wmismatched-parameter-types"
- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray *, RLMCollectionChange *, NSError *))block {
@throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm");
}
#pragma clang diagnostic pop
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...
{
va_list args;
va_start(args, predicateFormat);
NSUInteger index = [self indexOfObjectWhere:predicateFormat args:args];
va_end(args);
return index;
}
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args
{
return [self indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:predicateFormat
arguments:args]];
}
#pragma mark - Superclass Overrides
- (NSString *)description {
return [self descriptionWithMaxDepth:RLMDescriptionMaxDepth];
}
- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth {
return RLMDescriptionWithMaxDepth(@"RLMArray", self, depth);
}
@end
@interface RLMSortDescriptor ()
@property (nonatomic, strong) NSString *property;
@property (nonatomic, assign) BOOL ascending;
@end
@implementation RLMSortDescriptor
+ (instancetype)sortDescriptorWithProperty:(NSString *)propertyName ascending:(BOOL)ascending {
RLMSortDescriptor *desc = [[RLMSortDescriptor alloc] init];
desc->_property = propertyName;
desc->_ascending = ascending;
return desc;
}
- (instancetype)reversedSortDescriptor {
return [self.class sortDescriptorWithProperty:_property ascending:!_ascending];
}
@end

View File

@ -1,424 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMArray_Private.hpp"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObject_Private.hpp"
#import "RLMObservation.hpp"
#import "RLMProperty_Private.h"
#import "RLMQueryUtil.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMSchema.h"
#import "RLMUtil.hpp"
#import "list.hpp"
#import "results.hpp"
#import <realm/table_view.hpp>
#import <objc/runtime.h>
//
// RLMArray implementation
//
@implementation RLMArrayLinkView {
@public
realm::List _backingList;
RLMRealm *_realm;
RLMClassInfo *_objectInfo;
RLMClassInfo *_ownerInfo;
std::unique_ptr<RLMObservationInfo> _observationInfo;
}
- (RLMArrayLinkView *)initWithParent:(__unsafe_unretained RLMObjectBase *const)parentObject
property:(__unsafe_unretained RLMProperty *const)property {
self = [self initWithObjectClassName:property.objectClassName];
if (self) {
_realm = parentObject->_realm;
_backingList = realm::List(_realm->_realm, parentObject->_row.get_linklist(parentObject->_info->tableColumn(property)));
_objectInfo = &parentObject->_info->linkTargetType(property.index);
_ownerInfo = parentObject->_info;
_key = property.name;
}
return self;
}
void RLMValidateArrayObservationKey(__unsafe_unretained NSString *const keyPath,
__unsafe_unretained RLMArray *const array) {
if (![keyPath isEqualToString:RLMInvalidatedKey]) {
@throw RLMException(@"[<%@ %p> addObserver:forKeyPath:options:context:] is not supported. Key path: %@",
[array class], array, keyPath);
}
}
void RLMEnsureArrayObservationInfo(std::unique_ptr<RLMObservationInfo>& info,
__unsafe_unretained NSString *const keyPath,
__unsafe_unretained RLMArray *const array,
__unsafe_unretained id const observed) {
RLMValidateArrayObservationKey(keyPath, array);
if (!info && array.class == [RLMArrayLinkView class]) {
RLMArrayLinkView *lv = static_cast<RLMArrayLinkView *>(array);
info = std::make_unique<RLMObservationInfo>(*lv->_ownerInfo,
lv->_backingList.get_origin_row_index(),
observed);
}
}
//
// validation helpers
//
[[gnu::noinline]]
[[noreturn]]
static void throwError() {
try {
throw;
}
catch (realm::InvalidTransactionException const&) {
@throw RLMException(@"Cannot modify managed RLMArray outside of a write transaction");
}
catch (realm::IncorrectThreadException const&) {
@throw RLMException(@"Realm accessed from incorrect thread");
}
catch (realm::List::InvalidatedException const&) {
@throw RLMException(@"RLMArray has been invalidated or the containing object has been deleted");
}
catch (realm::List::OutOfBoundsIndexException const& e) {
@throw RLMException(@"Index %zu is out of bounds (must be less than %zu)",
e.requested, e.valid_count);
}
}
template<typename Function>
static auto translateErrors(Function&& f) {
try {
return f();
}
catch (...) {
throwError();
}
}
static void validateObjectToAdd(__unsafe_unretained RLMArrayLinkView *const ar,
__unsafe_unretained RLMObject *const obj) {
if (!obj) {
@throw RLMException(@"Cannot add `nil` to RLMArray<%@>", ar->_objectClassName);
}
NSString *objectClassName = obj->_objectSchema.className;
if (![objectClassName isEqualToString:ar->_objectClassName]) {
@throw RLMException(@"Cannot add object of type '%@' to RLMArray<%@>",
objectClassName, ar->_objectClassName);
}
if (obj->_realm != ar.realm) {
[ar.realm addObject:obj];
}
else if (obj->_realm && !obj->_row.is_attached()) {
@throw RLMException(@"Object has been deleted or invalidated.");
}
}
template<typename IndexSetFactory>
static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar,
NSKeyValueChange kind, dispatch_block_t f, IndexSetFactory&& is) {
translateErrors([&] { ar->_backingList.verify_in_transaction(); });
RLMObservationInfo *info = RLMGetObservationInfo(ar->_observationInfo.get(),
ar->_backingList.get_origin_row_index(),
*ar->_ownerInfo);
if (info) {
NSIndexSet *indexes = is();
info->willChange(ar->_key, kind, indexes);
try {
f();
}
catch (...) {
info->didChange(ar->_key, kind, indexes);
throwError();
}
info->didChange(ar->_key, kind, indexes);
}
else {
translateErrors([&] { f(); });
}
}
static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSUInteger index, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndex:index]; });
}
static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSRange range, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndexesInRange:range]; });
}
static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSIndexSet *is, dispatch_block_t f) {
changeArray(ar, kind, f, [=] { return is; });
}
//
// public method implementations
//
- (RLMRealm *)realm {
return _realm;
}
- (NSUInteger)count {
return translateErrors([&] { return _backingList.size(); });
}
- (BOOL)isInvalidated {
return translateErrors([&] { return !_backingList.is_valid(); });
}
- (RLMClassInfo *)objectInfo {
return _objectInfo;
}
- (BOOL)isEqual:(id)object {
if (RLMArrayLinkView *linkView = RLMDynamicCast<RLMArrayLinkView>(object)) {
return linkView->_backingList == _backingList;
}
return NO;
}
- (NSUInteger)hash {
return std::hash<realm::List>()(_backingList);
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(__unused __unsafe_unretained id [])buffer
count:(NSUInteger)len {
__autoreleasing RLMFastEnumerator *enumerator;
if (state->state == 0) {
translateErrors([&] { _backingList.verify_attached(); });
enumerator = [[RLMFastEnumerator alloc] initWithCollection:self objectSchema:*_objectInfo];
state->extra[0] = (long)enumerator;
state->extra[1] = self.count;
}
else {
enumerator = (__bridge id)(void *)state->extra[0];
}
return [enumerator countByEnumeratingWithState:state count:len];
}
- (id)objectAtIndex:(NSUInteger)index {
return RLMCreateObjectAccessor(_realm, *_objectInfo,
translateErrors([&] { return _backingList.get(index).get_index(); }));
}
static void RLMInsertObject(RLMArrayLinkView *ar, RLMObject *object, NSUInteger index) {
if (index == NSUIntegerMax) {
index = translateErrors([&] { return ar->_backingList.size(); });
}
validateObjectToAdd(ar, object);
changeArray(ar, NSKeyValueChangeInsertion, index, ^{
ar->_backingList.insert(index, object->_row.get_index());
});
}
- (void)addObject:(RLMObject *)object {
RLMInsertObject(self, object, NSUIntegerMax);
}
- (void)insertObject:(RLMObject *)object atIndex:(NSUInteger)index {
RLMInsertObject(self, object, index);
}
- (void)insertObjects:(id<NSFastEnumeration>)objects atIndexes:(NSIndexSet *)indexes {
changeArray(self, NSKeyValueChangeInsertion, indexes, ^{
NSUInteger index = [indexes firstIndex];
for (RLMObject *obj in objects) {
validateObjectToAdd(self, obj);
_backingList.insert(index, obj->_row.get_index());
index = [indexes indexGreaterThanIndex:index];
}
});
}
- (void)removeObjectAtIndex:(NSUInteger)index {
changeArray(self, NSKeyValueChangeRemoval, index, ^{
_backingList.remove(index);
});
}
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes {
changeArray(self, NSKeyValueChangeRemoval, indexes, ^{
[indexes enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger idx, BOOL *) {
_backingList.remove(idx);
}];
});
}
- (void)addObjectsFromArray:(NSArray *)array {
changeArray(self, NSKeyValueChangeInsertion, NSMakeRange(self.count, array.count), ^{
for (RLMObject *obj in array) {
validateObjectToAdd(self, obj);
_backingList.add(obj->_row.get_index());
}
});
}
- (void)removeAllObjects {
changeArray(self, NSKeyValueChangeRemoval, NSMakeRange(0, self.count), ^{
_backingList.remove_all();
});
}
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(RLMObject *)object {
validateObjectToAdd(self, object);
changeArray(self, NSKeyValueChangeReplacement, index, ^{
_backingList.set(index, object->_row.get_index());
});
}
- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex {
auto start = std::min(sourceIndex, destinationIndex);
auto len = std::max(sourceIndex, destinationIndex) - start + 1;
changeArray(self, NSKeyValueChangeReplacement, {start, len}, ^{
_backingList.move(sourceIndex, destinationIndex);
});
}
- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 {
changeArray(self, NSKeyValueChangeReplacement, ^{
_backingList.swap(index1, index2);
}, [=] {
NSMutableIndexSet *set = [[NSMutableIndexSet alloc] initWithIndex:index1];
[set addIndex:index2];
return set;
});
}
- (NSUInteger)indexOfObject:(RLMObject *)object {
if (object.invalidated) {
@throw RLMException(@"Object has been deleted or invalidated");
}
// check that object types align
if (![_objectClassName isEqualToString:object->_objectSchema.className]) {
@throw RLMException(@"Object of type (%@) does not match RLMArray type (%@)",
object->_objectSchema.className, _objectClassName);
}
return translateErrors([&] { return RLMConvertNotFound(_backingList.find(object->_row)); });
}
- (id)valueForKeyPath:(NSString *)keyPath {
if ([keyPath hasPrefix:@"@"]) {
// Delegate KVC collection operators to RLMResults
auto query = translateErrors([&] { return _backingList.get_query(); });
RLMResults *results = [RLMResults resultsWithObjectInfo:*_objectInfo
results:realm::Results(_realm->_realm, std::move(query))];
return [results valueForKeyPath:keyPath];
}
return [super valueForKeyPath:keyPath];
}
- (id)valueForKey:(NSString *)key {
// Ideally we'd use "@invalidated" for this so that "invalidated" would use
// normal array KVC semantics, but observing @things works very oddly (when
// it's part of a key path, it's triggered automatically when array index
// changes occur, and can't be sent explicitly, but works normally when it's
// the entire key path), and an RLMArrayLinkView *can't* have objects where
// invalidated is true, so we're not losing much.
if ([key isEqualToString:RLMInvalidatedKey]) {
return @(!_backingList.is_valid());
}
translateErrors([&] { _backingList.verify_attached(); });
return RLMCollectionValueForKey(self, key);
}
- (void)setValue:(id)value forKey:(NSString *)key {
translateErrors([&] { _backingList.verify_in_transaction(); });
RLMCollectionSetValueForKey(self, key, value);
}
- (void)deleteObjectsFromRealm {
// delete all target rows from the realm
RLMTrackDeletions(_realm, ^{
translateErrors([&] { _backingList.delete_all(); });
});
}
- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties {
auto order = RLMSortDescriptorFromDescriptors(*_objectInfo->table(), properties);
auto results = translateErrors([&] { return _backingList.sort(std::move(order)); });
return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)];
}
- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate {
auto query = RLMPredicateToQuery(predicate, _objectInfo->rlmObjectSchema, _realm.schema, _realm.group);
auto results = translateErrors([&] { return _backingList.filter(std::move(query)); });
return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)];
}
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate {
auto query = translateErrors([&] { return _backingList.get_query(); });
query.and_query(RLMPredicateToQuery(predicate, _objectInfo->rlmObjectSchema, _realm.schema, _realm.group));
#if REALM_VER_MAJOR >= 2
auto indexInTable = query.find();
if (indexInTable == realm::not_found) {
return NSNotFound;
}
auto row = query.get_table()->get(indexInTable);
return _backingList.find(row);
#else
return RLMConvertNotFound(query.find());
#endif
}
- (NSArray *)objectsAtIndexes:(__unused NSIndexSet *)indexes {
// FIXME: this is called by KVO when array changes are made. It's not clear
// why, and returning nil seems to work fine.
return nil;
}
- (void)addObserver:(id)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context {
RLMEnsureArrayObservationInfo(_observationInfo, keyPath, self, self);
[super addObserver:observer forKeyPath:keyPath options:options context:context];
}
- (NSUInteger)indexInSource:(NSUInteger)index {
return _backingList.get_unchecked(index);
}
- (realm::TableView)tableView {
return translateErrors([&] { return _backingList.get_query(); }).find_all();
}
// The compiler complains about the method's argument type not matching due to
// it not having the generic type attached, but it doesn't seem to be possible
// to actually include the generic type
// http://www.openradar.me/radar?id=6135653276319744
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-parameter-types"
- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray *, RLMCollectionChange *, NSError *))block {
[_realm verifyNotificationsAreSupported];
return RLMAddNotificationBlock(self, _backingList, block);
}
#pragma clang diagnostic pop
@end

View File

@ -1,344 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMCollection_Private.hpp"
#import "RLMArray_Private.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObject_Private.hpp"
#import "collection_notifications.hpp"
#import "list.hpp"
#import "results.hpp"
#import <realm/table_view.hpp>
static const int RLMEnumerationBufferSize = 16;
@implementation RLMFastEnumerator {
// The buffer supplied by fast enumeration does not retain the objects given
// to it, but because we create objects on-demand and don't want them
// autoreleased (a table can have more rows than the device has memory for
// accessor objects) we need a thing to retain them.
id _strongBuffer[RLMEnumerationBufferSize];
RLMRealm *_realm;
RLMClassInfo *_info;
// Collection being enumerated. Only one of these two will be valid: when
// possible we enumerate the collection directly, but when in a write
// transaction we instead create a frozen TableView and enumerate that
// instead so that mutating the collection during enumeration works.
id<RLMFastEnumerable> _collection;
realm::TableView _tableView;
}
- (instancetype)initWithCollection:(id<RLMFastEnumerable>)collection objectSchema:(RLMClassInfo&)info {
self = [super init];
if (self) {
_realm = collection.realm;
_info = &info;
if (_realm.inWriteTransaction) {
_tableView = [collection tableView];
}
else {
_collection = collection;
[_realm registerEnumerator:self];
}
}
return self;
}
- (void)dealloc {
if (_collection) {
[_realm unregisterEnumerator:self];
}
}
- (void)detach {
_tableView = [_collection tableView];
_collection = nil;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
count:(NSUInteger)len {
[_realm verifyThread];
if (!_tableView.is_attached() && !_collection) {
@throw RLMException(@"Collection is no longer valid");
}
// The fast enumeration buffer size is currently a hardcoded number in the
// compiler so this can't actually happen, but just in case it changes in
// the future...
if (len > RLMEnumerationBufferSize) {
len = RLMEnumerationBufferSize;
}
NSUInteger batchCount = 0, count = state->extra[1];
Class accessorClass = _info->rlmObjectSchema.accessorClass;
for (NSUInteger index = state->state; index < count && batchCount < len; ++index) {
RLMObject *accessor = RLMCreateManagedAccessor(accessorClass, _realm, _info);
if (_collection) {
accessor->_row = (*_info->table())[[_collection indexInSource:index]];
}
else if (_tableView.is_row_attached(index)) {
accessor->_row = (*_info->table())[_tableView.get_source_ndx(index)];
}
RLMInitializeSwiftAccessorGenerics(accessor);
_strongBuffer[batchCount] = accessor;
batchCount++;
}
for (NSUInteger i = batchCount; i < len; ++i) {
_strongBuffer[i] = nil;
}
if (batchCount == 0) {
// Release our data if we're done, as we're autoreleased and so may
// stick around for a while
_collection = nil;
if (_tableView.is_attached()) {
_tableView = {};
}
else {
[_realm unregisterEnumerator:self];
}
}
state->itemsPtr = (__unsafe_unretained id *)(void *)_strongBuffer;
state->state += batchCount;
state->mutationsPtr = state->extra+1;
return batchCount;
}
@end
NSArray *RLMCollectionValueForKey(id<RLMFastEnumerable> collection, NSString *key) {
size_t count = collection.count;
if (count == 0) {
return @[];
}
RLMRealm *realm = collection.realm;
RLMClassInfo *info = collection.objectInfo;
NSMutableArray *results = [NSMutableArray arrayWithCapacity:count];
if ([key isEqualToString:@"self"]) {
for (size_t i = 0; i < count; i++) {
size_t rowIndex = [collection indexInSource:i];
[results addObject:RLMCreateObjectAccessor(realm, *info, rowIndex) ?: NSNull.null];
}
return results;
}
RLMObject *accessor = RLMCreateManagedAccessor(info->rlmObjectSchema.accessorClass, realm, info);
realm::Table *table = info->table();
for (size_t i = 0; i < count; i++) {
size_t rowIndex = [collection indexInSource:i];
accessor->_row = (*table)[rowIndex];
RLMInitializeSwiftAccessorGenerics(accessor);
[results addObject:[accessor valueForKey:key] ?: NSNull.null];
}
return results;
}
void RLMCollectionSetValueForKey(id<RLMFastEnumerable> collection, NSString *key, id value) {
realm::TableView tv = [collection tableView];
if (tv.size() == 0) {
return;
}
RLMRealm *realm = collection.realm;
RLMClassInfo *info = collection.objectInfo;
RLMObject *accessor = RLMCreateManagedAccessor(info->rlmObjectSchema.accessorClass, realm, info);
for (size_t i = 0; i < tv.size(); i++) {
accessor->_row = tv[i];
RLMInitializeSwiftAccessorGenerics(accessor);
[accessor setValue:value forKey:key];
}
}
NSString *RLMDescriptionWithMaxDepth(NSString *name,
id<RLMCollection> collection,
NSUInteger depth) {
if (depth == 0) {
return @"<Maximum depth exceeded>";
}
const NSUInteger maxObjects = 100;
auto str = [NSMutableString stringWithFormat:@"%@ <%p> (\n", name, (void *)collection];
size_t index = 0, skipped = 0;
for (id obj in collection) {
NSString *sub;
if ([obj respondsToSelector:@selector(descriptionWithMaxDepth:)]) {
sub = [obj descriptionWithMaxDepth:depth - 1];
}
else {
sub = [obj description];
}
// Indent child objects
NSString *objDescription = [sub stringByReplacingOccurrencesOfString:@"\n"
withString:@"\n\t"];
[str appendFormat:@"\t[%zu] %@,\n", index++, objDescription];
if (index >= maxObjects) {
skipped = collection.count - maxObjects;
break;
}
}
// Remove last comma and newline characters
if (collection.count > 0) {
[str deleteCharactersInRange:NSMakeRange(str.length-2, 2)];
}
if (skipped) {
[str appendFormat:@"\n\t... %zu objects skipped.", skipped];
}
[str appendFormat:@"\n)"];
return str;
}
@implementation RLMCancellationToken {
realm::NotificationToken _token;
}
- (instancetype)initWithToken:(realm::NotificationToken)token {
self = [super init];
if (self) {
_token = std::move(token);
}
return self;
}
- (void)stop {
_token = {};
}
@end
@implementation RLMCollectionChange {
realm::CollectionChangeSet _indices;
}
- (instancetype)initWithChanges:(realm::CollectionChangeSet)indices {
self = [super init];
if (self) {
_indices = std::move(indices);
}
return self;
}
static NSArray *toArray(realm::IndexSet const& set) {
NSMutableArray *ret = [NSMutableArray new];
for (auto index : set.as_indexes()) {
[ret addObject:@(index)];
}
return ret;
}
- (NSArray *)insertions {
return toArray(_indices.insertions);
}
- (NSArray *)deletions {
return toArray(_indices.deletions);
}
- (NSArray *)modifications {
return toArray(_indices.modifications);
}
static NSArray *toIndexPathArray(realm::IndexSet const& set, NSUInteger section) {
NSMutableArray *ret = [NSMutableArray new];
NSUInteger path[2] = {section, 0};
for (auto index : set.as_indexes()) {
path[1] = index;
[ret addObject:[NSIndexPath indexPathWithIndexes:path length:2]];
}
return ret;
}
- (NSArray<NSIndexPath *> *)deletionsInSection:(NSUInteger)section {
return toIndexPathArray(_indices.deletions, section);
}
- (NSArray<NSIndexPath *> *)insertionsInSection:(NSUInteger)section {
return toIndexPathArray(_indices.insertions, section);
}
- (NSArray<NSIndexPath *> *)modificationsInSection:(NSUInteger)section {
return toIndexPathArray(_indices.modifications, section);
}
@end
template<typename Collection>
RLMNotificationToken *RLMAddNotificationBlock(id objcCollection,
Collection& collection,
void (^block)(id, RLMCollectionChange *, NSError *),
bool suppressInitialChange) {
struct IsValid {
static bool call(realm::List const& list) {
return list.is_valid();
}
static bool call(realm::Results const&) {
return true;
}
};
auto skip = suppressInitialChange ? std::make_shared<bool>(true) : nullptr;
auto cb = [=, &collection](realm::CollectionChangeSet const& changes,
std::exception_ptr err) {
if (err) {
try {
rethrow_exception(err);
}
catch (...) {
NSError *error = nil;
RLMRealmTranslateException(&error);
block(nil, nil, error);
return;
}
}
if (!IsValid::call(collection)) {
return;
}
if (skip && *skip) {
*skip = false;
block(objcCollection, nil, nil);
}
else if (changes.empty()) {
block(objcCollection, nil, nil);
}
else {
block(objcCollection, [[RLMCollectionChange alloc] initWithChanges:changes], nil);
}
};
return [[RLMCancellationToken alloc] initWithToken:collection.add_notification_callback(cb)];
}
// Explicitly instantiate the templated function for the two types we'll use it on
template RLMNotificationToken *RLMAddNotificationBlock<realm::List>(id, realm::List&, void (^)(id, RLMCollectionChange *, NSError *), bool);
template RLMNotificationToken *RLMAddNotificationBlock<realm::Results>(id, realm::Results&, void (^)(id, RLMCollectionChange *, NSError *), bool);

View File

@ -1,34 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMConstants.h>
RLMNotification const RLMRealmRefreshRequiredNotification = @"RLMRealmRefreshRequiredNotification";
RLMNotification const RLMRealmDidChangeNotification = @"RLMRealmDidChangeNotification";
NSString * const RLMErrorDomain = @"io.realm";
NSString * const RLMUnknownSystemErrorDomain = @"io.realm.unknown";
NSString * const RLMExceptionName = @"RLMException";
NSString * const RLMRealmVersionKey = @"RLMRealmVersion";
NSString * const RLMRealmCoreVersionKey = @"RLMRealmCoreVersion";
NSString * const RLMInvalidatedKey = @"invalidated";

View File

@ -1,60 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMListBase.h"
#import "RLMArray_Private.hpp"
#import "RLMObservation.hpp"
@interface RLMArray (KVO)
- (NSArray *)objectsAtIndexes:(__unused NSIndexSet *)indexes;
@end
@implementation RLMListBase {
std::unique_ptr<RLMObservationInfo> _observationInfo;
}
- (instancetype)initWithArray:(RLMArray *)array {
self = [super init];
if (self) {
__rlmArray = array;
}
return self;
}
- (id)valueForKey:(NSString *)key {
return [__rlmArray valueForKey:key];
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len {
return [__rlmArray countByEnumeratingWithState:state objects:buffer count:len];
}
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
return [__rlmArray objectsAtIndexes:indexes];
}
- (void)addObserver:(id)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context {
RLMEnsureArrayObservationInfo(_observationInfo, keyPath, __rlmArray, self);
[super addObserver:observer forKeyPath:keyPath options:options context:context];
}
@end

View File

@ -1,162 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMMigration_Private.h"
#import "RLMAccessor.h"
#import "RLMObject_Private.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMProperty_Private.h"
#import "RLMRealm_Dynamic.h"
#import "RLMRealm_Private.hpp"
#import "RLMResults_Private.h"
#import "RLMSchema_Private.hpp"
#import "RLMUtil.hpp"
#import "object_store.hpp"
#import "shared_realm.hpp"
#import "schema.hpp"
#import <realm/table.hpp>
using namespace realm;
// The source realm for a migration has to use a SharedGroup to be able to share
// the file with the destination realm, but we don't want to let the user call
// beginWriteTransaction on it as that would make no sense.
@interface RLMMigrationRealm : RLMRealm
@end
@implementation RLMMigrationRealm
- (BOOL)readonly {
return YES;
}
- (void)beginWriteTransaction {
@throw RLMException(@"Cannot modify the source Realm in a migration");
}
@end
@implementation RLMMigration {
realm::Schema *_schema;
}
- (instancetype)initWithRealm:(RLMRealm *)realm oldRealm:(RLMRealm *)oldRealm schema:(realm::Schema &)schema {
self = [super init];
if (self) {
_realm = realm;
_oldRealm = oldRealm;
_schema = &schema;
object_setClass(_oldRealm, RLMMigrationRealm.class);
}
return self;
}
- (RLMSchema *)oldSchema {
return self.oldRealm.schema;
}
- (RLMSchema *)newSchema {
return self.realm.schema;
}
- (void)enumerateObjects:(NSString *)className block:(RLMObjectMigrationBlock)block {
// get all objects
RLMResults *objects = [_realm.schema schemaForClassName:className] ? [_realm allObjects:className] : nil;
RLMResults *oldObjects = [_oldRealm.schema schemaForClassName:className] ? [_oldRealm allObjects:className] : nil;
if (objects && oldObjects) {
for (long i = oldObjects.count - 1; i >= 0; i--) {
@autoreleasepool {
block(oldObjects[i], objects[i]);
}
}
}
else if (objects) {
for (long i = objects.count - 1; i >= 0; i--) {
@autoreleasepool {
block(nil, objects[i]);
}
}
}
else if (oldObjects) {
for (long i = oldObjects.count - 1; i >= 0; i--) {
@autoreleasepool {
block(oldObjects[i], nil);
}
}
}
}
- (void)execute:(RLMMigrationBlock)block {
@autoreleasepool {
// disable all primary keys for migration and use DynamicObject for all types
for (RLMObjectSchema *objectSchema in _realm.schema.objectSchema) {
objectSchema.accessorClass = RLMDynamicObject.class;
objectSchema.primaryKeyProperty.isPrimary = NO;
}
for (RLMObjectSchema *objectSchema in _oldRealm.schema.objectSchema) {
objectSchema.accessorClass = RLMDynamicObject.class;
}
block(self, _oldRealm->_realm->schema_version());
_oldRealm = nil;
_realm = nil;
}
}
- (RLMObject *)createObject:(NSString *)className withValue:(id)value {
return [_realm createObject:className withValue:value];
}
- (RLMObject *)createObject:(NSString *)className withObject:(id)object {
return [self createObject:className withValue:object];
}
- (void)deleteObject:(RLMObject *)object {
[_realm deleteObject:object];
}
- (BOOL)deleteDataForClassName:(NSString *)name {
if (!name) {
return false;
}
TableRef table = ObjectStore::table_for_object_type(_realm.group, name.UTF8String);
if (!table) {
return false;
}
if ([_realm.schema schemaForClassName:name]) {
table->clear();
}
else {
realm::ObjectStore::delete_data_for_object(_realm.group, name.UTF8String);
}
return true;
}
- (void)renamePropertyForClass:(NSString *)className oldName:(NSString *)oldName newName:(NSString *)newName {
const char *objectType = className.UTF8String;
realm::ObjectStore::rename_property(_realm.group, *_schema, objectType, oldName.UTF8String, newName.UTF8String);
}
@end

View File

@ -1,223 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObject_Private.hpp"
#import "RLMAccessor.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMQueryUtil.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMSchema_Private.h"
// We declare things in RLMObject which are actually implemented in RLMObjectBase
// for documentation's sake, which leads to -Wunimplemented-method warnings.
// Other alternatives to this would be to disable -Wunimplemented-method for this
// file (but then we could miss legitimately missing things), or declaring the
// inherited things in a category (but they currently aren't nicely grouped for
// that).
@implementation RLMObject
// synthesized in RLMObjectBase
@dynamic invalidated, realm, objectSchema;
#pragma mark - Designated Initializers
- (instancetype)init {
return [super init];
}
- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema {
return [super initWithValue:value schema:schema];
}
- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm schema:(RLMObjectSchema *)schema {
return [super initWithRealm:realm schema:schema];
}
#pragma mark - Convenience Initializers
- (instancetype)initWithValue:(id)value {
[self.class sharedSchema]; // ensure this class' objectSchema is loaded in the partialSharedSchema
RLMSchema *schema = RLMSchema.partialSharedSchema;
return [super initWithValue:value schema:schema];
}
#pragma mark - Class-based Object Creation
+ (instancetype)createInDefaultRealmWithValue:(id)value {
return (RLMObject *)RLMCreateObjectInRealmWithValue([RLMRealm defaultRealm], [self className], value, false);
}
+ (instancetype)createInRealm:(RLMRealm *)realm withValue:(id)value {
return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, false);
}
+ (instancetype)createOrUpdateInDefaultRealmWithValue:(id)value {
return [self createOrUpdateInRealm:[RLMRealm defaultRealm] withValue:value];
}
+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value {
// verify primary key
RLMObjectSchema *schema = [self sharedSchema];
if (!schema.primaryKeyProperty) {
NSString *reason = [NSString stringWithFormat:@"'%@' does not have a primary key and can not be updated", schema.className];
@throw [NSException exceptionWithName:@"RLMExecption" reason:reason userInfo:nil];
}
return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, true);
}
#pragma mark - Subscripting
- (id)objectForKeyedSubscript:(NSString *)key {
return RLMObjectBaseObjectForKeyedSubscript(self, key);
}
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key {
RLMObjectBaseSetObjectForKeyedSubscript(self, key, obj);
}
#pragma mark - Getting & Querying
+ (RLMResults *)allObjects {
return RLMGetObjects(RLMRealm.defaultRealm, self.className, nil);
}
+ (RLMResults *)allObjectsInRealm:(RLMRealm *)realm {
return RLMGetObjects(realm, self.className, nil);
}
+ (RLMResults *)objectsWhere:(NSString *)predicateFormat, ... {
va_list args;
va_start(args, predicateFormat);
RLMResults *results = [self objectsWhere:predicateFormat args:args];
va_end(args);
return results;
}
+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args {
return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ... {
va_list args;
va_start(args, predicateFormat);
RLMResults *results = [self objectsInRealm:realm where:predicateFormat args:args];
va_end(args);
return results;
}
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args {
return [self objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}
+ (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate {
return RLMGetObjects(RLMRealm.defaultRealm, self.className, predicate);
}
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(NSPredicate *)predicate {
return RLMGetObjects(realm, self.className, predicate);
}
+ (instancetype)objectForPrimaryKey:(id)primaryKey {
return RLMGetObject(RLMRealm.defaultRealm, self.className, primaryKey);
}
+ (instancetype)objectInRealm:(RLMRealm *)realm forPrimaryKey:(id)primaryKey {
return RLMGetObject(realm, self.className, primaryKey);
}
#pragma mark - Other Instance Methods
- (BOOL)isEqualToObject:(RLMObject *)object {
return [object isKindOfClass:RLMObject.class] && RLMObjectBaseAreEqual(self, object);
}
+ (NSString *)className {
return [super className];
}
#pragma mark - Default values for schema definition
+ (NSArray *)indexedProperties {
return @[];
}
+ (NSDictionary *)linkingObjectsProperties {
return @{};
}
+ (NSDictionary *)defaultPropertyValues {
return nil;
}
+ (NSString *)primaryKey {
return nil;
}
+ (NSArray *)ignoredProperties {
return nil;
}
+ (NSArray *)requiredProperties {
return @[];
}
@end
@implementation RLMDynamicObject
+ (BOOL)shouldIncludeInDefaultSchema {
return NO;
}
- (id)valueForUndefinedKey:(NSString *)key {
return RLMDynamicGetByName(self, key, false);
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
RLMDynamicValidatedSet(self, key, value);
}
@end
@implementation RLMWeakObjectHandle {
realm::Row _row;
RLMClassInfo *_info;
Class _objectClass;
}
- (instancetype)initWithObject:(RLMObjectBase *)object {
if (!(self = [super init])) {
return nil;
}
_row = object->_row;
_info = object->_info;
_objectClass = object.class;
return self;
}
- (RLMObjectBase *)object {
RLMObjectBase *object = RLMCreateManagedAccessor(_objectClass, _info->realm, _info);
object->_row = std::move(_row);
return object;
}
@end

View File

@ -1,450 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObject_Private.hpp"
#import "RLMAccessor.h"
#import "RLMArray_Private.hpp"
#import "RLMListBase.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObservation.hpp"
#import "RLMOptionalBase.h"
#import "RLMProperty_Private.h"
#import "RLMRealm_Private.hpp"
#import "RLMSchema_Private.h"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
using namespace realm;
const NSUInteger RLMDescriptionMaxDepth = 5;
static bool maybeInitObjectSchemaForUnmanaged(RLMObjectBase *obj) {
obj->_objectSchema = [obj.class sharedSchema];
if (!obj->_objectSchema) {
return false;
}
// set default values
if (!obj->_objectSchema.isSwiftClass) {
NSDictionary *dict = RLMDefaultValuesForObjectSchema(obj->_objectSchema);
for (NSString *key in dict) {
[obj setValue:dict[key] forKey:key];
}
}
// set unmanaged accessor class
object_setClass(obj, obj->_objectSchema.unmanagedClass);
return true;
}
@implementation RLMObjectBase
// unmanaged init
- (instancetype)init {
if ((self = [super init])) {
maybeInitObjectSchemaForUnmanaged(self);
}
return self;
}
- (void)dealloc {
// This can't be a unique_ptr because associated objects are removed
// *after* c++ members are destroyed and dealloc is called, and we need it
// to be in a validish state when that happens
delete _observationInfo;
_observationInfo = nullptr;
}
static id validatedObjectForProperty(id obj, RLMProperty *prop, RLMSchema *schema) {
if (RLMIsObjectValidForProperty(obj, prop)) {
return obj;
}
// check for object or array of properties
if (prop.type == RLMPropertyTypeObject) {
// for object create and try to initialize with obj
RLMObjectSchema *objSchema = schema[prop.objectClassName];
return [[objSchema.objectClass alloc] initWithValue:obj schema:schema];
}
else if (prop.type == RLMPropertyTypeArray && [obj conformsToProtocol:@protocol(NSFastEnumeration)]) {
// for arrays, create objects for each element and return new array
RLMObjectSchema *objSchema = schema[prop.objectClassName];
RLMArray *objects = [[RLMArray alloc] initWithObjectClassName:objSchema.className];
for (id el in obj) {
[objects addObject:[[objSchema.objectClass alloc] initWithValue:el schema:schema]];
}
return objects;
}
// if not convertible to prop throw
@throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name);
}
- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema {
if (!(self = [super init])) {
return self;
}
if (!maybeInitObjectSchemaForUnmanaged(self)) {
// Don't populate fields from the passed-in object if we're called
// during schema init
return self;
}
NSArray *properties = _objectSchema.properties;
if (NSArray *array = RLMDynamicCast<NSArray>(value)) {
if (array.count != properties.count) {
@throw RLMException(@"Invalid array input. Number of array elements does not match number of properties.");
}
for (NSUInteger i = 0; i < array.count; i++) {
id propertyValue = validatedObjectForProperty(array[i], properties[i], schema);
[self setValue:RLMCoerceToNil(propertyValue) forKeyPath:[properties[i] name]];
}
}
else if (value) {
// assume our object is an NSDictionary or an object with kvc properties
NSDictionary *defaultValues = nil;
for (RLMProperty *prop in properties) {
id obj = RLMValidatedValueForProperty(value, prop.name, _objectSchema.className);
// get default for nil object
if (!obj) {
if (!defaultValues) {
defaultValues = RLMDefaultValuesForObjectSchema(_objectSchema);
}
obj = defaultValues[prop.name];
}
// don't set unspecified properties
if (!obj) {
continue;
}
obj = validatedObjectForProperty(obj, prop, schema);
[self setValue:RLMCoerceToNil(obj) forKeyPath:prop.name];
}
} else {
@throw RLMException(@"Must provide a non-nil value.");
}
return self;
}
id RLMCreateManagedAccessor(Class cls, __unsafe_unretained RLMRealm *realm, RLMClassInfo *info) {
RLMObjectBase *obj = [[cls alloc] initWithRealm:realm schema:info->rlmObjectSchema];
obj->_info = info;
return obj;
}
- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm
schema:(RLMObjectSchema *)schema {
self = [super init];
if (self) {
_realm = realm;
_objectSchema = schema;
}
return self;
}
- (id)valueForKey:(NSString *)key {
if (_observationInfo) {
return _observationInfo->valueForKey(key);
}
return [super valueForKey:key];
}
// Generic Swift properties can't be dynamic, so KVO doesn't work for them by default
- (id)valueForUndefinedKey:(NSString *)key {
if (Ivar ivar = _objectSchema[key].swiftIvar) {
return RLMCoerceToNil(object_getIvar(self, ivar));
}
return [super valueForUndefinedKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
RLMProperty *property = _objectSchema[key];
if (Ivar ivar = property.swiftIvar) {
if (property.type == RLMPropertyTypeArray && [value conformsToProtocol:@protocol(NSFastEnumeration)]) {
RLMArray *array = [object_getIvar(self, ivar) _rlmArray];
[array removeAllObjects];
[array addObjects:value];
}
else if (property.optional) {
RLMOptionalBase *optional = object_getIvar(self, ivar);
optional.underlyingValue = value;
}
return;
}
[super setValue:value forUndefinedKey:key];
}
// overridden at runtime per-class for performance
+ (NSString *)className {
NSString *className = NSStringFromClass(self);
if ([RLMSwiftSupport isSwiftClassName:className]) {
className = [RLMSwiftSupport demangleClassName:className];
}
return className;
}
// overridden at runtime per-class for performance
+ (RLMObjectSchema *)sharedSchema {
return [RLMSchema sharedSchemaForClass:self.class];
}
+ (Class)objectUtilClass:(BOOL)isSwift {
return RLMObjectUtilClass(isSwift);
}
- (NSString *)description
{
if (self.isInvalidated) {
return @"[invalid object]";
}
return [self descriptionWithMaxDepth:RLMDescriptionMaxDepth];
}
- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth {
if (depth == 0) {
return @"<Maximum depth exceeded>";
}
NSString *baseClassName = _objectSchema.className;
NSMutableString *mString = [NSMutableString stringWithFormat:@"%@ {\n", baseClassName];
for (RLMProperty *property in _objectSchema.properties) {
id object = RLMObjectBaseObjectForKeyedSubscript(self, property.name);
NSString *sub;
if ([object respondsToSelector:@selector(descriptionWithMaxDepth:)]) {
sub = [object descriptionWithMaxDepth:depth - 1];
}
else if (property.type == RLMPropertyTypeData) {
static NSUInteger maxPrintedDataLength = 24;
NSData *data = object;
NSUInteger length = data.length;
if (length > maxPrintedDataLength) {
data = [NSData dataWithBytes:data.bytes length:maxPrintedDataLength];
}
NSString *dataDescription = [data description];
sub = [NSString stringWithFormat:@"<%@ — %lu total bytes>", [dataDescription substringWithRange:NSMakeRange(1, dataDescription.length - 2)], (unsigned long)length];
}
else {
sub = [object description];
}
[mString appendFormat:@"\t%@ = %@;\n", property.name, [sub stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]];
}
[mString appendString:@"}"];
return [NSString stringWithString:mString];
}
- (RLMRealm *)realm {
return _realm;
}
- (RLMObjectSchema *)objectSchema {
return _objectSchema;
}
- (BOOL)isInvalidated {
// if not unmanaged and our accessor has been detached, we have been deleted
return self.class == _objectSchema.accessorClass && !_row.is_attached();
}
- (BOOL)isEqual:(id)object {
if (RLMObjectBase *other = RLMDynamicCast<RLMObjectBase>(object)) {
if (_objectSchema.primaryKeyProperty) {
return RLMObjectBaseAreEqual(self, other);
}
}
return [super isEqual:object];
}
- (NSUInteger)hash {
if (_objectSchema.primaryKeyProperty) {
id primaryProperty = [self valueForKey:_objectSchema.primaryKeyProperty.name];
// modify the hash of our primary key value to avoid potential (although unlikely) collisions
return [primaryProperty hash] ^ 1;
}
else {
return [super hash];
}
}
+ (BOOL)shouldIncludeInDefaultSchema {
return RLMIsObjectSubclass(self);
}
- (id)mutableArrayValueForKey:(NSString *)key {
id obj = [self valueForKey:key];
if ([obj isKindOfClass:[RLMArray class]]) {
return obj;
}
return [super mutableArrayValueForKey:key];
}
- (void)addObserver:(id)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context {
if (!_observationInfo) {
_observationInfo = new RLMObservationInfo(self);
}
_observationInfo->recordObserver(_row, _info, _objectSchema, keyPath);
[super addObserver:observer forKeyPath:keyPath options:options context:context];
}
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath {
[super removeObserver:observer forKeyPath:keyPath];
if (_observationInfo)
_observationInfo->removeObserver();
}
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
const char *className = class_getName(self);
const char accessorClassPrefix[] = "RLMAccessor_";
if (!strncmp(className, accessorClassPrefix, sizeof(accessorClassPrefix) - 1)) {
if (self.sharedSchema[key]) {
return NO;
}
}
return [super automaticallyNotifiesObserversForKey:key];
}
@end
RLMRealm *RLMObjectBaseRealm(__unsafe_unretained RLMObjectBase *object) {
return object ? object->_realm : nil;
}
RLMObjectSchema *RLMObjectBaseObjectSchema(__unsafe_unretained RLMObjectBase *object) {
return object ? object->_objectSchema : nil;
}
id RLMObjectBaseObjectForKeyedSubscript(RLMObjectBase *object, NSString *key) {
if (!object) {
return nil;
}
if (object->_realm) {
return RLMDynamicGetByName(object, key, false);
}
else {
return [object valueForKey:key];
}
}
void RLMObjectBaseSetObjectForKeyedSubscript(RLMObjectBase *object, NSString *key, id obj) {
if (!object) {
return;
}
if (object->_realm) {
RLMDynamicValidatedSet(object, key, obj);
}
else {
[object setValue:obj forKey:key];
}
}
BOOL RLMObjectBaseAreEqual(RLMObjectBase *o1, RLMObjectBase *o2) {
// if not the correct types throw
if ((o1 && ![o1 isKindOfClass:RLMObjectBase.class]) || (o2 && ![o2 isKindOfClass:RLMObjectBase.class])) {
@throw RLMException(@"Can only compare objects of class RLMObjectBase");
}
// if identical object (or both are nil)
if (o1 == o2) {
return YES;
}
// if one is nil
if (o1 == nil || o2 == nil) {
return NO;
}
// if not in realm or differing realms
if (o1->_realm == nil || o1->_realm != o2->_realm) {
return NO;
}
// if either are detached
if (!o1->_row.is_attached() || !o2->_row.is_attached()) {
return NO;
}
// if table and index are the same
return o1->_row.get_table() == o2->_row.get_table()
&& o1->_row.get_index() == o2->_row.get_index();
}
id RLMValidatedValueForProperty(id object, NSString *key, NSString *className) {
@try {
return [object valueForKey:key];
}
@catch (NSException *e) {
if ([e.name isEqualToString:NSUndefinedKeyException]) {
@throw RLMException(@"Invalid value '%@' to initialize object of type '%@': missing key '%@'",
object, className, key);
}
@throw;
}
}
Class RLMObjectUtilClass(BOOL isSwift) {
static Class objectUtilObjc = [RLMObjectUtil class];
static Class objectUtilSwift = NSClassFromString(@"RealmSwiftObjectUtil");
return isSwift && objectUtilSwift ? objectUtilSwift : objectUtilObjc;
}
@implementation RLMObjectUtil
+ (NSArray *)ignoredPropertiesForClass:(Class)cls {
return [cls ignoredProperties];
}
+ (NSArray *)indexedPropertiesForClass:(Class)cls {
return [cls indexedProperties];
}
+ (NSDictionary *)linkingObjectsPropertiesForClass:(Class)cls {
return [cls linkingObjectsProperties];
}
+ (NSDictionary *)linkingObjectProperties:(__unused id)object {
return nil;
}
+ (NSArray *)getGenericListPropertyNames:(__unused id)obj {
return nil;
}
+ (NSDictionary *)getLinkingObjectsProperties:(__unused id)obj {
return nil;
}
+ (NSDictionary *)getOptionalProperties:(__unused id)obj {
return nil;
}
+ (NSArray *)requiredPropertiesForClass:(Class)cls {
return [cls requiredProperties];
}
@end

View File

@ -1,440 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObjectSchema_Private.hpp"
#import "RLMArray.h"
#import "RLMListBase.h"
#import "RLMObject_Private.h"
#import "RLMProperty_Private.hpp"
#import "RLMRealm_Dynamic.h"
#import "RLMRealm_Private.hpp"
#import "RLMSchema_Private.h"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
#import "object_store.hpp"
using namespace realm;
// private properties
@interface RLMObjectSchema ()
@property (nonatomic, readwrite) NSDictionary<id, RLMProperty *> *allPropertiesByName;
@property (nonatomic, readwrite) NSString *className;
@end
@implementation RLMObjectSchema {
NSArray *_swiftGenericProperties;
}
- (instancetype)initWithClassName:(NSString *)objectClassName objectClass:(Class)objectClass properties:(NSArray *)properties {
self = [super init];
self.className = objectClassName;
self.properties = properties;
self.objectClass = objectClass;
self.accessorClass = objectClass;
self.unmanagedClass = objectClass;
return self;
}
// return properties by name
-(RLMProperty *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)key {
return _allPropertiesByName[key];
}
// create property map when setting property array
-(void)setProperties:(NSArray *)properties {
_properties = properties;
[self _propertiesDidChange];
}
- (void)setComputedProperties:(NSArray *)computedProperties {
_computedProperties = computedProperties;
[self _propertiesDidChange];
}
- (void)_propertiesDidChange {
NSMutableDictionary *map = [NSMutableDictionary dictionaryWithCapacity:_properties.count + _computedProperties.count];
NSUInteger index = 0;
for (RLMProperty *prop in _properties) {
prop.index = index++;
map[prop.name] = prop;
if (prop.isPrimary) {
self.primaryKeyProperty = prop;
}
}
for (RLMProperty *prop in _computedProperties) {
map[prop.name] = prop;
}
_allPropertiesByName = map;
}
- (void)setPrimaryKeyProperty:(RLMProperty *)primaryKeyProperty {
_primaryKeyProperty.isPrimary = NO;
primaryKeyProperty.isPrimary = YES;
_primaryKeyProperty = primaryKeyProperty;
}
+ (instancetype)schemaForObjectClass:(Class)objectClass {
RLMObjectSchema *schema = [RLMObjectSchema new];
// determine classname from objectclass as className method has not yet been updated
NSString *className = NSStringFromClass(objectClass);
bool isSwift = [RLMSwiftSupport isSwiftClassName:className];
if (isSwift) {
className = [RLMSwiftSupport demangleClassName:className];
}
schema.className = className;
schema.objectClass = objectClass;
schema.accessorClass = objectClass;
schema.isSwiftClass = isSwift;
// create array of RLMProperties, inserting properties of superclasses first
Class cls = objectClass;
Class superClass = class_getSuperclass(cls);
NSArray *allProperties = @[];
while (superClass && superClass != RLMObjectBase.class) {
allProperties = [[RLMObjectSchema propertiesForClass:cls isSwift:isSwift] arrayByAddingObjectsFromArray:allProperties];
cls = superClass;
superClass = class_getSuperclass(superClass);
}
NSArray *persistedProperties = [allProperties filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(RLMProperty *property, NSDictionary *) {
return !RLMPropertyTypeIsComputed(property.type);
}]];
schema.properties = persistedProperties;
NSArray *computedProperties = [allProperties filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(RLMProperty *property, NSDictionary *) {
return RLMPropertyTypeIsComputed(property.type);
}]];
schema.computedProperties = computedProperties;
// verify that we didn't add any properties twice due to inheritance
if (allProperties.count != [NSSet setWithArray:[allProperties valueForKey:@"name"]].count) {
NSCountedSet *countedPropertyNames = [NSCountedSet setWithArray:[allProperties valueForKey:@"name"]];
NSSet *duplicatePropertyNames = [countedPropertyNames filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *) {
return [countedPropertyNames countForObject:object] > 1;
}]];
if (duplicatePropertyNames.count == 1) {
@throw RLMException(@"Property '%@' is declared multiple times in the class hierarchy of '%@'", duplicatePropertyNames.allObjects.firstObject, className);
} else {
@throw RLMException(@"Object '%@' has properties that are declared multiple times in its class hierarchy: '%@'", className, [duplicatePropertyNames.allObjects componentsJoinedByString:@"', '"]);
}
}
if (NSString *primaryKey = [objectClass primaryKey]) {
for (RLMProperty *prop in schema.properties) {
if ([primaryKey isEqualToString:prop.name]) {
prop.indexed = YES;
schema.primaryKeyProperty = prop;
break;
}
}
if (!schema.primaryKeyProperty) {
@throw RLMException(@"Primary key property '%@' does not exist on object '%@'", primaryKey, className);
}
if (schema.primaryKeyProperty.type != RLMPropertyTypeInt && schema.primaryKeyProperty.type != RLMPropertyTypeString) {
@throw RLMException(@"Only 'string' and 'int' properties can be designated the primary key");
}
}
for (RLMProperty *prop in schema.properties) {
if (prop.optional && !RLMPropertyTypeIsNullable(prop.type)) {
@throw RLMException(@"Only 'string', 'binary', and 'object' properties can be made optional, and property '%@' is of type '%@'.",
prop.name, RLMTypeToString(prop.type));
}
}
return schema;
}
+ (nullable NSString *)baseNameForLazySwiftProperty:(NSString *)propertyName {
// A Swift lazy var shows up as two separate children on the reflection tree: one named 'x', and another that is
// optional and is named 'x.storage'. Note that '.' is illegal in either a Swift or Objective-C property name.
NSString *const storageSuffix = @".storage";
if ([propertyName hasSuffix:storageSuffix]) {
return [propertyName substringToIndex:propertyName.length - storageSuffix.length];
}
return nil;
}
+ (NSArray *)propertiesForClass:(Class)objectClass isSwift:(bool)isSwiftClass {
Class objectUtil = [objectClass objectUtilClass:isSwiftClass];
NSArray *ignoredProperties = [objectUtil ignoredPropertiesForClass:objectClass];
NSDictionary *linkingObjectsProperties = [objectUtil linkingObjectsPropertiesForClass:objectClass];
// For Swift classes we need an instance of the object when parsing properties
id swiftObjectInstance = isSwiftClass ? [[objectClass alloc] init] : nil;
unsigned int count;
objc_property_t *props = class_copyPropertyList(objectClass, &count);
NSMutableArray *propArray = [NSMutableArray arrayWithCapacity:count];
NSSet *indexed = [[NSSet alloc] initWithArray:[objectUtil indexedPropertiesForClass:objectClass]];
for (unsigned int i = 0; i < count; i++) {
NSString *propertyName = @(property_getName(props[i]));
if ([ignoredProperties containsObject:propertyName]) {
continue;
}
RLMProperty *prop = nil;
if (isSwiftClass) {
prop = [[RLMProperty alloc] initSwiftPropertyWithName:propertyName
indexed:[indexed containsObject:propertyName]
linkPropertyDescriptor:linkingObjectsProperties[propertyName]
property:props[i]
instance:swiftObjectInstance];
}
else {
prop = [[RLMProperty alloc] initWithName:propertyName
indexed:[indexed containsObject:propertyName]
linkPropertyDescriptor:linkingObjectsProperties[propertyName]
property:props[i]];
}
if (prop) {
[propArray addObject:prop];
}
}
free(props);
if (isSwiftClass) {
// List<> properties don't show up as objective-C properties due to
// being generic, so use Swift reflection to get a list of them, and
// then access their ivars directly
for (NSString *propName in [objectUtil getGenericListPropertyNames:swiftObjectInstance]) {
Ivar ivar = class_getInstanceVariable(objectClass, propName.UTF8String);
id value = object_getIvar(swiftObjectInstance, ivar);
NSString *className = [value _rlmArray].objectClassName;
NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) {
return [obj.name isEqualToString:propName];
}];
if (existing != NSNotFound) {
[propArray removeObjectAtIndex:existing];
}
[propArray addObject:[[RLMProperty alloc] initSwiftListPropertyWithName:propName
ivar:ivar
objectClassName:className]];
}
// Ditto for LinkingObjects<> properties.
NSDictionary *linkingObjectsProperties = [objectUtil getLinkingObjectsProperties:swiftObjectInstance];
for (NSString *propName in linkingObjectsProperties) {
NSDictionary *info = linkingObjectsProperties[propName];
Ivar ivar = class_getInstanceVariable(objectClass, propName.UTF8String);
NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) {
return [obj.name isEqualToString:propName];
}];
if (existing != NSNotFound) {
[propArray removeObjectAtIndex:existing];
}
[propArray addObject:[[RLMProperty alloc] initSwiftLinkingObjectsPropertyWithName:propName
ivar:ivar
objectClassName:info[@"class"]
linkOriginPropertyName:info[@"property"]]];
}
}
if (auto optionalProperties = [objectUtil getOptionalProperties:swiftObjectInstance]) {
for (RLMProperty *property in propArray) {
property.optional = false;
}
[optionalProperties enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSNumber *propertyType, __unused BOOL *stop) {
if ([ignoredProperties containsObject:propertyName]) {
return;
}
NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) {
return [obj.name isEqualToString:propertyName];
}];
RLMProperty *property;
if (existing != NSNotFound) {
property = propArray[existing];
property.optional = true;
}
if (auto type = RLMCoerceToNil(propertyType)) {
if (existing == NSNotFound) {
// Check to see if this optional property is an underlying storage property for a Swift lazy var.
// Managed lazy vars are't allowed.
// NOTE: Revisit this once property behaviors are implemented in Swift.
if (NSString *lazyPropertyBaseName = [self baseNameForLazySwiftProperty:propertyName]) {
if ([ignoredProperties containsObject:lazyPropertyBaseName]) {
// This property is the storage property for a ignored lazy Swift property. Just continue.
return;
} else {
@throw RLMException(@"Lazy managed property '%@' is not allowed on a Realm Swift object class. Either add the property to the ignored properties list or make it non-lazy.", lazyPropertyBaseName);
}
}
// The current property isn't a storage property for a lazy Swift property.
property = [[RLMProperty alloc] initSwiftOptionalPropertyWithName:propertyName
indexed:[indexed containsObject:propertyName]
ivar:class_getInstanceVariable(objectClass, propertyName.UTF8String)
propertyType:RLMPropertyType(type.intValue)];
[propArray addObject:property];
}
else {
property.type = RLMPropertyType(type.intValue);
}
}
}];
}
if (auto requiredProperties = [objectUtil requiredPropertiesForClass:objectClass]) {
for (RLMProperty *property in propArray) {
bool required = [requiredProperties containsObject:property.name];
if (required && property.type == RLMPropertyTypeObject) {
@throw RLMException(@"Object properties cannot be made required, "
"but '+[%@ requiredProperties]' included '%@'", objectClass, property.name);
}
property.optional &= !required;
}
}
for (RLMProperty *property in propArray) {
if (!property.optional && property.type == RLMPropertyTypeObject) { // remove if/when core supports required link columns
@throw RLMException(@"The `%@.%@` property must be marked as being optional.", [objectClass className], property.name);
}
}
return propArray;
}
- (id)copyWithZone:(NSZone *)zone {
RLMObjectSchema *schema = [[RLMObjectSchema allocWithZone:zone] init];
schema->_objectClass = _objectClass;
schema->_className = _className;
schema->_objectClass = _objectClass;
schema->_accessorClass = _objectClass;
schema->_unmanagedClass = _unmanagedClass;
schema->_isSwiftClass = _isSwiftClass;
// call property setter to reset map and primary key
schema.properties = [[NSArray allocWithZone:zone] initWithArray:_properties copyItems:YES];
schema.computedProperties = [[NSArray allocWithZone:zone] initWithArray:_computedProperties copyItems:YES];
return schema;
}
- (BOOL)isEqualToObjectSchema:(RLMObjectSchema *)objectSchema {
if (objectSchema.properties.count != _properties.count) {
return NO;
}
if (![_properties isEqualToArray:objectSchema.properties]) {
return NO;
}
if (![_computedProperties isEqualToArray:objectSchema.computedProperties]) {
return NO;
}
return YES;
}
- (NSString *)description {
NSMutableString *propertiesString = [NSMutableString string];
for (RLMProperty *property in self.properties) {
[propertiesString appendFormat:@"\t%@\n", [property.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]];
}
for (RLMProperty *property in self.computedProperties) {
[propertiesString appendFormat:@"\t%@\n", [property.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]];
}
return [NSString stringWithFormat:@"%@ {\n%@}", self.className, propertiesString];
}
- (realm::ObjectSchema)objectStoreCopy {
ObjectSchema objectSchema;
objectSchema.name = _className.UTF8String;
objectSchema.primary_key = _primaryKeyProperty ? _primaryKeyProperty.name.UTF8String : "";
for (RLMProperty *prop in _properties) {
Property p = [prop objectStoreCopy];
p.is_primary = (prop == _primaryKeyProperty);
objectSchema.persisted_properties.push_back(std::move(p));
}
for (RLMProperty *prop in _computedProperties) {
objectSchema.computed_properties.push_back([prop objectStoreCopy]);
}
return objectSchema;
}
+ (instancetype)objectSchemaForObjectStoreSchema:(realm::ObjectSchema const&)objectSchema {
RLMObjectSchema *schema = [RLMObjectSchema new];
schema.className = @(objectSchema.name.c_str());
// create array of RLMProperties
NSMutableArray *properties = [NSMutableArray arrayWithCapacity:objectSchema.persisted_properties.size()];
for (const Property &prop : objectSchema.persisted_properties) {
RLMProperty *property = [RLMProperty propertyForObjectStoreProperty:prop];
property.isPrimary = (prop.name == objectSchema.primary_key);
[properties addObject:property];
}
schema.properties = properties;
NSMutableArray *computedProperties = [NSMutableArray arrayWithCapacity:objectSchema.computed_properties.size()];
for (const Property &prop : objectSchema.computed_properties) {
[computedProperties addObject:[RLMProperty propertyForObjectStoreProperty:prop]];
}
schema.computedProperties = computedProperties;
// get primary key from realm metadata
if (objectSchema.primary_key.length()) {
NSString *primaryKeyString = [NSString stringWithUTF8String:objectSchema.primary_key.c_str()];
schema.primaryKeyProperty = schema[primaryKeyString];
if (!schema.primaryKeyProperty) {
@throw RLMException(@"No property matching primary key '%@'", primaryKeyString);
}
}
// for dynamic schema use vanilla RLMDynamicObject accessor classes
schema.objectClass = RLMObject.class;
schema.accessorClass = RLMDynamicObject.class;
schema.unmanagedClass = RLMObject.class;
return schema;
}
- (NSArray *)swiftGenericProperties {
if (_swiftGenericProperties) {
return _swiftGenericProperties;
}
// This check isn't semantically required, but avoiding accessing the local
// static helps perf in the obj-c case
if (!_isSwiftClass) {
return _swiftGenericProperties = @[];
}
// Check if it's a swift class using the obj-c API
static Class s_swiftObjectClass = NSClassFromString(@"RealmSwiftObject");
if (![_accessorClass isSubclassOfClass:s_swiftObjectClass]) {
return _swiftGenericProperties = @[];
}
NSMutableArray *genericProperties = [NSMutableArray new];
for (RLMProperty *prop in _properties) {
if (prop->_swiftIvar) {
[genericProperties addObject:prop];
}
}
// Currently all computed properties are Swift generics
[genericProperties addObjectsFromArray:_computedProperties];
return _swiftGenericProperties = genericProperties;
}
@end

View File

@ -1,543 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObjectStore.h"
#import "RLMAccessor.h"
#import "RLMArray_Private.hpp"
#import "RLMListBase.h"
#import "RLMObservation.hpp"
#import "RLMObject_Private.hpp"
#import "RLMObjectSchema_Private.hpp"
#import "RLMOptionalBase.h"
#import "RLMProperty_Private.h"
#import "RLMQueryUtil.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMSchema_Private.h"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
#import "object_store.hpp"
#import "results.hpp"
#import "shared_realm.hpp"
#import <objc/message.h>
using namespace realm;
void RLMRealmCreateAccessors(RLMSchema *schema) {
for (RLMObjectSchema *objectSchema in schema.objectSchema) {
if (objectSchema.accessorClass != objectSchema.objectClass) {
continue;
}
static unsigned long long count = 0;
NSString *prefix = [NSString stringWithFormat:@"RLMAccessor_%llu_", count++];
objectSchema.accessorClass = RLMAccessorClassForObjectClass(objectSchema.objectClass, objectSchema, prefix);
}
}
static inline void RLMVerifyRealmRead(__unsafe_unretained RLMRealm *const realm) {
if (!realm) {
@throw RLMException(@"Realm must not be nil");
}
[realm verifyThread];
}
static inline void RLMVerifyInWriteTransaction(__unsafe_unretained RLMRealm *const realm) {
RLMVerifyRealmRead(realm);
// if realm is not writable throw
if (!realm.inWriteTransaction) {
@throw RLMException(@"Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first.");
}
}
void RLMInitializeSwiftAccessorGenerics(__unsafe_unretained RLMObjectBase *const object) {
if (!object || !object->_row || !object->_objectSchema->_isSwiftClass) {
return;
}
if (![object isKindOfClass:object->_objectSchema.objectClass]) {
// It can be a different class if it's a dynamic object, and those don't
// require any init here (and would crash since they don't have the ivars)
return;
}
for (RLMProperty *prop in object->_objectSchema.swiftGenericProperties) {
if (prop->_type == RLMPropertyTypeArray) {
RLMArray *array = [[RLMArrayLinkView alloc] initWithParent:object property:prop];
[object_getIvar(object, prop.swiftIvar) set_rlmArray:array];
}
else if (prop.type == RLMPropertyTypeLinkingObjects) {
id linkingObjects = object_getIvar(object, prop.swiftIvar);
[linkingObjects setObject:(id)[[RLMWeakObjectHandle alloc] initWithObject:object]];
[linkingObjects setProperty:prop];
}
else {
RLMOptionalBase *optional = object_getIvar(object, prop.swiftIvar);
optional.property = prop;
optional.object = object;
}
}
}
static void validateValueForProperty(__unsafe_unretained id const obj,
__unsafe_unretained RLMProperty *const prop) {
switch (prop.type) {
case RLMPropertyTypeString:
case RLMPropertyTypeBool:
case RLMPropertyTypeDate:
case RLMPropertyTypeInt:
case RLMPropertyTypeFloat:
case RLMPropertyTypeDouble:
case RLMPropertyTypeData:
if (!RLMIsObjectValidForProperty(obj, prop)) {
@throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name);
}
break;
case RLMPropertyTypeObject:
break;
case RLMPropertyTypeArray: {
if (obj != nil && obj != NSNull.null) {
if (![obj conformsToProtocol:@protocol(NSFastEnumeration)]) {
@throw RLMException(@"Array property value (%@) is not enumerable.", obj);
}
}
break;
}
case RLMPropertyTypeAny:
case RLMPropertyTypeLinkingObjects:
@throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name);
}
}
static NSUInteger createRowForObject(RLMClassInfo const& info) {
try {
return info.table()->add_empty_row();
}
catch (std::exception const& e) {
@throw RLMException(e);
}
}
/* If a row exists with the specified primary key value, return its index. Otherwise, return `realm::not_found`.
*
* Precondition: `info` must refer to a class which has a primary key property
* Precondition: `primaryValue` is a validated property value that has been coerced to `nil`
*/
static NSUInteger getRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue) {
REALM_ASSERT_DEBUG(info.propertyForPrimaryKey());
RLMProperty *const primaryProperty = info.propertyForPrimaryKey();
const NSUInteger primaryPropertyColumn = info.tableColumn(primaryProperty);
switch (primaryProperty.type) {
case RLMPropertyTypeString:
return info.table()->find_first_string(primaryPropertyColumn, RLMStringDataWithNSString(primaryValue));
case RLMPropertyTypeInt:
if (primaryValue) {
return info.table()->find_first_int(primaryPropertyColumn, [primaryValue longLongValue]);
} else {
return info.table()->find_first_null(primaryPropertyColumn);
}
default:
REALM_UNREACHABLE();
}
}
/* Create a row with the specified primary key value and return its index.
*
* Precondition: `info` must refer to a class which has a valid primary key property
* Precondition: a write transaction is in progress
* Precondition: no row already exists with the specified `primaryValue` for this model
*/
static NSUInteger createRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue) {
REALM_ASSERT_DEBUG(info.propertyForPrimaryKey());
REALM_ASSERT_DEBUG(info.realm.inWriteTransaction);
REALM_ASSERT_DEBUG(getRowForObjectWithPrimaryKey(info, primaryValue) == realm::not_found);
RLMProperty *const primaryProperty = info.propertyForPrimaryKey();
const NSUInteger primaryColumnIndex = info.tableColumn(primaryProperty);
// create row
const NSUInteger rowIndex = createRowForObject(info);
Row row = info.table()->get(rowIndex);
// set value for primary key
validateValueForProperty(primaryValue, primaryProperty);
primaryValue = RLMCoerceToNil(primaryValue);
try {
switch (primaryProperty.type) {
case RLMPropertyTypeString:
REALM_ASSERT_DEBUG(!primaryValue || [primaryValue isKindOfClass:NSString.class]);
row.set_string_unique(primaryColumnIndex, RLMStringDataWithNSString(primaryValue));
break;
case RLMPropertyTypeInt:
if (primaryValue) {
REALM_ASSERT_DEBUG([primaryValue isKindOfClass:NSNumber.class]);
row.set_int_unique(primaryColumnIndex, [primaryValue longLongValue]);
} else {
row.set_null(primaryColumnIndex); // FIXME: Use `set_null_unique` once Core supports it
}
break;
default:
REALM_UNREACHABLE();
}
}
catch (std::exception const& e) {
@throw RLMException(e);
}
return rowIndex;
}
/* If a row exists with the specified primary key value, returns its index. Otherwise, creates a new row with the
* specified primary key value and returns its index. The out parameter `foundExisting` will be set to indicate
* whether or not a new row was created.
*
* Precondition: `info` must refer to a class which has a valid primary key property
* Precondition: a write transaction is in progress
*/
static NSUInteger createOrGetRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue,
bool* foundExisting = nullptr) {
REALM_ASSERT_DEBUG(info.propertyForPrimaryKey());
REALM_ASSERT_DEBUG(info.realm.inWriteTransaction);
const NSUInteger existingRow = getRowForObjectWithPrimaryKey(info, primaryValue);
if (existingRow == realm::not_found) {
*foundExisting = false;
return createRowForObjectWithPrimaryKey(info, primaryValue);
} else {
*foundExisting = true;
return existingRow;
}
}
/* If the class has a primary key, calls `valueForProperty` with that key and creates or gets the row with
* this primary key value. Otherwise if the class has no primary key, creates a new row. The out parameter
* `foundExisting` will be set to indicate whether or not a new row was created.
*
* Precondition: a write transaction is in progress
*/
template<typename F>
static NSUInteger createOrGetRowForObject(RLMClassInfo const& info, F valueForProperty,
bool createOrUpdate, bool* foundExisting) {
// try to get existing row if this class has a primary key
if (RLMProperty *primaryProperty = info.propertyForPrimaryKey()) {
// get primary value
const id primaryValue = valueForProperty(primaryProperty);
// search for existing object based on primary key type, creating a new row if one does not exist
NSUInteger rowIndex = createOrGetRowForObjectWithPrimaryKey(info, RLMCoerceToNil(primaryValue), foundExisting);
// ensure that `createOrUpdate` is set if we found an existing row
if (*foundExisting && !createOrUpdate) {
@throw RLMException(@"Can't create object with existing primary key value '%@'.", primaryValue);
}
return rowIndex;
}
// if no existing, create row
else {
*foundExisting = false;
return createRowForObject(info);
}
}
void RLMAddObjectToRealm(__unsafe_unretained RLMObjectBase *const object,
__unsafe_unretained RLMRealm *const realm,
bool createOrUpdate) {
RLMVerifyInWriteTransaction(realm);
// verify that object is unmanaged
if (object.invalidated) {
@throw RLMException(@"Adding a deleted or invalidated object to a Realm is not permitted");
}
if (object->_realm) {
if (object->_realm == realm) {
// no-op
return;
}
// for differing realms users must explicitly create the object in the second realm
@throw RLMException(@"Object is already managed by another Realm");
}
if (object->_observationInfo && object->_observationInfo->hasObservers()) {
@throw RLMException(@"Cannot add an object with observers to a Realm");
}
// set the realm and schema
NSString *objectClassName = object->_objectSchema.className;
auto& info = realm->_info[objectClassName];
object->_info = &info;
object->_objectSchema = info.rlmObjectSchema;
object->_realm = realm;
// get or create row
bool foundExisting;
auto primaryGetter = [=](__unsafe_unretained RLMProperty *const p) { return [object valueForKey:p.name]; };
object->_row = (*info.table())[createOrGetRowForObject(info, primaryGetter, createOrUpdate, &foundExisting)];
RLMCreationOptions creationOptions = RLMCreationOptionsPromoteUnmanaged;
if (createOrUpdate) {
creationOptions |= RLMCreationOptionsCreateOrUpdate;
}
// populate all properties
for (RLMProperty *prop in info.rlmObjectSchema.properties) {
// get object from ivar using key value coding
id value = nil;
if (prop.swiftIvar) {
if (prop.type == RLMPropertyTypeArray) {
value = static_cast<RLMListBase *>(object_getIvar(object, prop.swiftIvar))._rlmArray;
}
else { // optional
value = static_cast<RLMOptionalBase *>(object_getIvar(object, prop.swiftIvar)).underlyingValue;
}
}
else if ([object respondsToSelector:prop.getterSel]) {
value = [object valueForKey:prop.getterName];
}
if (!value && !prop.optional) {
@throw RLMException(@"No value or default value specified for property '%@' in '%@'",
prop.name, info.rlmObjectSchema.className);
}
// set the ivars for object and array properties to nil as otherwise the
// accessors retain objects that are no longer accessible via the properties
// this is mainly an issue when the object graph being added has cycles,
// as it's not obvious that the user has to set the *ivars* to nil to
// avoid leaking memory
if (prop.type == RLMPropertyTypeObject || prop.type == RLMPropertyTypeArray) {
if (!prop.swiftIvar) {
((void(*)(id, SEL, id))objc_msgSend)(object, prop.setterSel, nil);
}
}
// skip primary key when updating since it doesn't change
if (prop.isPrimary)
continue;
// set in table with out validation
RLMDynamicSet(object, prop, RLMCoerceToNil(value), creationOptions);
}
// set to proper accessor class
object_setClass(object, info.rlmObjectSchema.accessorClass);
RLMInitializeSwiftAccessorGenerics(object);
}
RLMObjectBase *RLMCreateObjectInRealmWithValue(RLMRealm *realm, NSString *className, id value, bool createOrUpdate = false) {
if (createOrUpdate && RLMIsObjectSubclass([value class])) {
RLMObjectBase *obj = value;
if ([obj->_objectSchema.className isEqualToString:className] && obj->_realm == realm) {
// This is a no-op if value is an RLMObject of the same type already backed by the target realm.
return value;
}
}
// verify writable
RLMVerifyInWriteTransaction(realm);
// create the object
auto& info = realm->_info[className];
RLMObjectBase *object = RLMCreateManagedAccessor(info.rlmObjectSchema.accessorClass, realm, &info);
RLMCreationOptions creationOptions = createOrUpdate ? RLMCreationOptionsCreateOrUpdate : RLMCreationOptionsNone;
// create row, and populate
if (NSArray *array = RLMDynamicCast<NSArray>(value)) {
// get or create our accessor
bool foundExisting;
NSArray *props = info.rlmObjectSchema.properties;
auto primaryGetter = [=](__unsafe_unretained RLMProperty *const p) {
return array[[props indexOfObject:p]];
};
object->_row = (*info.table())[createOrGetRowForObject(info, primaryGetter, createOrUpdate, &foundExisting)];
// populate
for (NSUInteger i = 0; i < array.count; i++) {
RLMProperty *prop = props[i];
// skip primary key when updating since it doesn't change
if (prop.isPrimary)
continue;
id val = array[i];
validateValueForProperty(val, prop);
RLMDynamicSet(object, prop, RLMCoerceToNil(val), creationOptions);
}
}
else {
__block bool foundExisting = false;
__block NSDictionary *defaultValues = nil;
auto getValue = ^(RLMProperty *prop) {
id propValue = RLMValidatedValueForProperty(value, prop.name, info.rlmObjectSchema.className);
if (!propValue && !foundExisting) {
if (!defaultValues) {
defaultValues = RLMDefaultValuesForObjectSchema(info.rlmObjectSchema);
}
propValue = defaultValues[prop.name];
if (!propValue && (prop.type == RLMPropertyTypeObject || prop.type == RLMPropertyTypeArray)) {
propValue = NSNull.null;
}
}
return propValue;
};
// get or create our accessor
object->_row = (*info.table())[createOrGetRowForObject(info, getValue, createOrUpdate, &foundExisting)];
// populate
for (RLMProperty *prop in info.rlmObjectSchema.properties) {
// skip primary key when updating since it doesn't change
if (prop.isPrimary)
continue;
if (id propValue = getValue(prop)) {
validateValueForProperty(propValue, prop);
RLMDynamicSet(object, prop, RLMCoerceToNil(propValue), creationOptions);
}
else if (!foundExisting && !prop.optional) {
@throw RLMException(@"Property '%@' of object of type '%@' cannot be nil.", prop.name, info.rlmObjectSchema.className);
}
}
}
RLMInitializeSwiftAccessorGenerics(object);
return object;
}
void RLMDeleteObjectFromRealm(__unsafe_unretained RLMObjectBase *const object,
__unsafe_unretained RLMRealm *const realm) {
if (realm != object->_realm) {
@throw RLMException(@"Can only delete an object from the Realm it belongs to.");
}
RLMVerifyInWriteTransaction(object->_realm);
// move last row to row we are deleting
if (object->_row.is_attached()) {
RLMTrackDeletions(realm, ^{
object->_row.get_table()->move_last_over(object->_row.get_index());
});
}
// set realm to nil
object->_realm = nil;
}
void RLMDeleteAllObjectsFromRealm(RLMRealm *realm) {
RLMVerifyInWriteTransaction(realm);
// clear table for each object schema
for (auto& info : realm->_info) {
RLMClearTable(info.second);
}
}
RLMResults *RLMGetObjects(RLMRealm *realm, NSString *objectClassName, NSPredicate *predicate) {
RLMVerifyRealmRead(realm);
// create view from table and predicate
RLMClassInfo& info = realm->_info[objectClassName];
if (!info.table()) {
// read-only realms may be missing tables since we can't add any
// missing ones on init
return [RLMResults resultsWithObjectInfo:info results:{}];
}
if (predicate) {
realm::Query query = RLMPredicateToQuery(predicate, info.rlmObjectSchema, realm.schema, realm.group);
return [RLMResults resultsWithObjectInfo:info
results:realm::Results(realm->_realm, std::move(query))];
}
return [RLMResults resultsWithObjectInfo:info
results:realm::Results(realm->_realm, *info.table())];
}
id RLMGetObject(RLMRealm *realm, NSString *objectClassName, id key) {
RLMVerifyRealmRead(realm);
RLMClassInfo& info = realm->_info[objectClassName];
auto primaryProperty = info.objectSchema->primary_key_property();
if (!primaryProperty) {
@throw RLMException(@"%@ does not have a primary key", objectClassName);
}
auto table = info.table();
if (!table) {
// read-only realms may be missing tables since we can't add any
// missing ones on init
return nil;
}
key = RLMCoerceToNil(key);
if (!key && !primaryProperty->is_nullable) {
@throw RLMException(@"Invalid null value for non-nullable primary key.");
}
size_t row = realm::not_found;
switch (primaryProperty->type) {
case PropertyType::String: {
NSString *string = RLMDynamicCast<NSString>(key);
if (!key || string) {
row = table->find_first_string(primaryProperty->table_column, RLMStringDataWithNSString(string));
} else {
@throw RLMException(@"Invalid value '%@' of type '%@' for string primary key.", key, [key class]);
}
break;
}
case PropertyType::Int:
if (NSNumber *number = RLMDynamicCast<NSNumber>(key)) {
row = table->find_first_int(primaryProperty->table_column, number.longLongValue);
} else if (!key) {
row = table->find_first_null(primaryProperty->table_column);
} else {
@throw RLMException(@"Invalid value '%@' of type '%@' for int primary key.", key, [key class]);
}
break;
default:
REALM_UNREACHABLE();
}
if (row == realm::not_found) {
return nil;
}
return RLMCreateObjectAccessor(realm, info, row);
}
RLMObjectBase *RLMCreateObjectAccessor(__unsafe_unretained RLMRealm *const realm,
RLMClassInfo& info,
NSUInteger index) {
return RLMCreateObjectAccessor(realm, info, (*info.table())[index]);
}
// Create accessor and register with realm
RLMObjectBase *RLMCreateObjectAccessor(__unsafe_unretained RLMRealm *const realm,
RLMClassInfo& info,
realm::RowExpr row) {
RLMObjectBase *accessor = RLMCreateManagedAccessor(info.rlmObjectSchema.accessorClass, realm, &info);
accessor->_row = row;
RLMInitializeSwiftAccessorGenerics(accessor);
return accessor;
}

View File

@ -1,500 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObservation.hpp"
#import "RLMAccessor.h"
#import "RLMArray_Private.hpp"
#import "RLMListBase.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObject_Private.hpp"
#import "RLMProperty_Private.h"
#import "RLMRealm_Private.hpp"
#import <realm/group.hpp>
using namespace realm;
namespace {
template<typename Iterator>
struct IteratorPair {
Iterator first;
Iterator second;
};
template<typename Iterator>
Iterator begin(IteratorPair<Iterator> const& p) {
return p.first;
}
template<typename Iterator>
Iterator end(IteratorPair<Iterator> const& p) {
return p.second;
}
template<typename Container>
auto reverse(Container const& c) {
return IteratorPair<typename Container::const_reverse_iterator>{c.rbegin(), c.rend()};
}
}
RLMObservationInfo::RLMObservationInfo(RLMClassInfo &objectSchema, std::size_t row, id object)
: object(object)
, objectSchema(&objectSchema)
{
setRow(*objectSchema.table(), row);
}
RLMObservationInfo::RLMObservationInfo(id object)
: object(object)
{
}
RLMObservationInfo::~RLMObservationInfo() {
if (prev) {
// Not the head of the linked list, so just detach from the list
REALM_ASSERT_DEBUG(prev->next == this);
prev->next = next;
if (next) {
REALM_ASSERT_DEBUG(next->prev == this);
next->prev = prev;
}
}
else if (objectSchema) {
// The head of the list, so remove self from the object schema's array
// of observation info, either replacing self with the next info or
// removing entirely if there is no next
auto end = objectSchema->observedObjects.end();
auto it = find(objectSchema->observedObjects.begin(), end, this);
if (it != end) {
if (next) {
*it = next;
next->prev = nullptr;
}
else {
iter_swap(it, std::prev(end));
objectSchema->observedObjects.pop_back();
}
}
}
// Otherwise the observed object was unmanaged, so nothing to do
#ifdef DEBUG
// ensure that incorrect cleanup fails noisily
object = (__bridge id)(void *)-1;
prev = (RLMObservationInfo *)-1;
next = (RLMObservationInfo *)-1;
#endif
}
NSString *RLMObservationInfo::columnName(size_t col) const noexcept {
return objectSchema->propertyForTableColumn(col).name;
}
void RLMObservationInfo::willChange(NSString *key, NSKeyValueChange kind, NSIndexSet *indexes) const {
if (indexes) {
forEach([=](__unsafe_unretained auto o) {
[o willChange:kind valuesAtIndexes:indexes forKey:key];
});
}
else {
forEach([=](__unsafe_unretained auto o) {
[o willChangeValueForKey:key];
});
}
}
void RLMObservationInfo::didChange(NSString *key, NSKeyValueChange kind, NSIndexSet *indexes) const {
if (indexes) {
forEach([=](__unsafe_unretained auto o) {
[o didChange:kind valuesAtIndexes:indexes forKey:key];
});
}
else {
forEach([=](__unsafe_unretained auto o) {
[o didChangeValueForKey:key];
});
}
}
void RLMObservationInfo::prepareForInvalidation() {
REALM_ASSERT_DEBUG(objectSchema);
REALM_ASSERT_DEBUG(!prev);
for (auto info = this; info; info = info->next)
info->invalidated = true;
}
void RLMObservationInfo::setRow(realm::Table &table, size_t newRow) {
REALM_ASSERT_DEBUG(!row);
REALM_ASSERT_DEBUG(objectSchema);
row = table[newRow];
for (auto info : objectSchema->observedObjects) {
if (info->row && info->row.get_index() == row.get_index()) {
prev = info;
next = info->next;
if (next)
next->prev = this;
info->next = this;
return;
}
}
objectSchema->observedObjects.push_back(this);
}
void RLMObservationInfo::recordObserver(realm::Row& objectRow, RLMClassInfo *objectInfo,
__unsafe_unretained RLMObjectSchema *const objectSchema,
__unsafe_unretained NSString *const keyPath) {
++observerCount;
if (row) {
return;
}
// add ourselves to the list of observed objects if this is the first time
// an observer is being added to a managed object
if (objectRow) {
this->objectSchema = objectInfo;
setRow(*objectRow.get_table(), objectRow.get_index());
return;
}
// Arrays need a reference to their containing object to avoid having to
// go through the awful proxy object from mutableArrayValueForKey.
// For managed objects we do this when the object is added or created
// (and have to to support notifications from modifying an object which
// was never observed), but for Swift classes (both RealmSwift and
// RLMObject) we can't do it then because we don't know what the parent
// object is.
NSUInteger sep = [keyPath rangeOfString:@"."].location;
NSString *key = sep == NSNotFound ? keyPath : [keyPath substringToIndex:sep];
RLMProperty *prop = objectSchema[key];
if (prop && prop.type == RLMPropertyTypeArray) {
id value = valueForKey(key);
RLMArray *array = [value isKindOfClass:[RLMListBase class]] ? [value _rlmArray] : value;
array->_key = key;
array->_parentObject = object;
}
else if (auto swiftIvar = prop.swiftIvar) {
if (auto optional = RLMDynamicCast<RLMOptionalBase>(object_getIvar(object, swiftIvar))) {
optional.property = prop;
optional.object = object;
}
}
}
void RLMObservationInfo::removeObserver() {
--observerCount;
}
id RLMObservationInfo::valueForKey(NSString *key) {
if (invalidated) {
if ([key isEqualToString:RLMInvalidatedKey]) {
return @YES;
}
return cachedObjects[key];
}
if (key != lastKey) {
lastKey = key;
lastProp = objectSchema ? objectSchema->rlmObjectSchema[key] : nil;
}
static auto superValueForKey = reinterpret_cast<id(*)(id, SEL, NSString *)>([NSObject methodForSelector:@selector(valueForKey:)]);
if (!lastProp) {
// Not a managed property, so use NSObject's implementation of valueForKey:
return RLMCoerceToNil(superValueForKey(object, @selector(valueForKey:), key));
}
auto getSuper = [&] {
return row ? RLMDynamicGet(object, lastProp) : RLMCoerceToNil(superValueForKey(object, @selector(valueForKey:), key));
};
// We need to return the same object each time for observing over keypaths
// to work, so we store a cache of them here. We can't just cache them on
// the object as that leads to retain cycles.
if (lastProp.type == RLMPropertyTypeArray) {
RLMArray *value = cachedObjects[key];
if (!value) {
value = getSuper();
if (!cachedObjects) {
cachedObjects = [NSMutableDictionary new];
}
cachedObjects[key] = value;
}
return value;
}
if (lastProp.type == RLMPropertyTypeObject) {
size_t col = row.get_column_index(lastProp.name.UTF8String);
if (row.is_null_link(col)) {
[cachedObjects removeObjectForKey:key];
return nil;
}
RLMObjectBase *value = cachedObjects[key];
if (value && value->_row.get_index() == row.get_link(col)) {
return value;
}
value = getSuper();
if (!cachedObjects) {
cachedObjects = [NSMutableDictionary new];
}
cachedObjects[key] = value;
return value;
}
return getSuper();
}
RLMObservationInfo *RLMGetObservationInfo(RLMObservationInfo *info, size_t row,
RLMClassInfo& objectSchema) {
if (info) {
return info;
}
for (RLMObservationInfo *info : objectSchema.observedObjects) {
if (info->isForRow(row)) {
return info;
}
}
return nullptr;
}
void RLMClearTable(RLMClassInfo &objectSchema) {
for (auto info : objectSchema.observedObjects) {
info->willChange(RLMInvalidatedKey);
}
RLMTrackDeletions(objectSchema.realm, ^{
objectSchema.table()->clear();
for (auto info : objectSchema.observedObjects) {
info->prepareForInvalidation();
}
});
for (auto info : reverse(objectSchema.observedObjects)) {
info->didChange(RLMInvalidatedKey);
}
objectSchema.observedObjects.clear();
}
void RLMTrackDeletions(__unsafe_unretained RLMRealm *const realm, dispatch_block_t block) {
std::vector<std::vector<RLMObservationInfo *> *> observers;
// Build up an array of observation info arrays which is indexed by table
// index (the object schemata may be in an entirely different order)
for (auto& info : realm->_info) {
if (info.second.observedObjects.empty()) {
continue;
}
size_t ndx = info.second.table()->get_index_in_group();
if (ndx >= observers.size()) {
observers.resize(std::max(observers.size() * 2, ndx + 1));
}
observers[ndx] = &info.second.observedObjects;
}
// No need for change tracking if no objects are observed
if (observers.empty()) {
block();
return;
}
struct change {
RLMObservationInfo *info;
__unsafe_unretained NSString *property;
NSMutableIndexSet *indexes;
};
std::vector<change> changes;
std::vector<RLMObservationInfo *> invalidated;
// This callback is called by core with a list of row deletions and
// resulting link nullifications immediately before things are deleted and nullified
realm.group.set_cascade_notification_handler([&](realm::Group::CascadeNotification const& cs) {
for (auto const& link : cs.links) {
size_t table_ndx = link.origin_table->get_index_in_group();
if (table_ndx >= observers.size() || !observers[table_ndx]) {
// The modified table has no observers
continue;
}
for (auto observer : *observers[table_ndx]) {
if (!observer->isForRow(link.origin_row_ndx)) {
continue;
}
NSString *name = observer->columnName(link.origin_col_ndx);
if (observer->getRow().get_table()->get_column_type(link.origin_col_ndx) != type_LinkList) {
changes.push_back({observer, name});
continue;
}
auto c = find_if(begin(changes), end(changes), [&](auto const& c) {
return c.info == observer && c.property == name;
});
if (c == end(changes)) {
changes.push_back({observer, name, [NSMutableIndexSet new]});
c = prev(end(changes));
}
// We know what row index is being removed from the LinkView,
// but what we actually want is the indexes in the LinkView that
// are going away
auto linkview = observer->getRow().get_linklist(link.origin_col_ndx);
size_t start = 0, index;
while ((index = linkview->find(link.old_target_row_ndx, start)) != realm::not_found) {
[c->indexes addIndex:index];
start = index + 1;
}
}
}
for (auto const& row : cs.rows) {
if (row.table_ndx >= observers.size() || !observers[row.table_ndx]) {
// The modified table has no observers
continue;
}
for (auto observer : *observers[row.table_ndx]) {
if (observer->isForRow(row.row_ndx)) {
invalidated.push_back(observer);
break;
}
}
}
// The relative order of these loops is very important
for (auto info : invalidated) {
info->willChange(RLMInvalidatedKey);
}
for (auto const& change : changes) {
change.info->willChange(change.property, NSKeyValueChangeRemoval, change.indexes);
}
for (auto info : invalidated) {
info->prepareForInvalidation();
}
});
try {
block();
}
catch (...) {
realm.group.set_cascade_notification_handler(nullptr);
throw;
}
for (auto const& change : reverse(changes)) {
change.info->didChange(change.property, NSKeyValueChangeRemoval, change.indexes);
}
for (auto info : reverse(invalidated)) {
info->didChange(RLMInvalidatedKey);
}
realm.group.set_cascade_notification_handler(nullptr);
}
namespace {
template<typename Func>
void forEach(realm::BindingContext::ObserverState const& state, Func&& func) {
for (size_t i = 0, size = state.changes.size(); i < size; ++i) {
if (state.changes[i].kind != realm::BindingContext::ColumnInfo::Kind::None) {
func(i, state.changes[i], static_cast<RLMObservationInfo *>(state.info));
}
}
}
}
std::vector<realm::BindingContext::ObserverState> RLMGetObservedRows(RLMSchemaInfo const& schema) {
std::vector<realm::BindingContext::ObserverState> observers;
for (auto& table : schema) {
for (auto info : table.second.observedObjects) {
auto const& row = info->getRow();
if (!row.is_attached())
continue;
observers.push_back({
row.get_table()->get_index_in_group(),
row.get_index(),
info});
}
}
sort(begin(observers), end(observers));
return observers;
}
static NSKeyValueChange convert(realm::BindingContext::ColumnInfo::Kind kind) {
switch (kind) {
case realm::BindingContext::ColumnInfo::Kind::None:
case realm::BindingContext::ColumnInfo::Kind::SetAll:
return NSKeyValueChangeSetting;
case realm::BindingContext::ColumnInfo::Kind::Set:
return NSKeyValueChangeReplacement;
case realm::BindingContext::ColumnInfo::Kind::Insert:
return NSKeyValueChangeInsertion;
case realm::BindingContext::ColumnInfo::Kind::Remove:
return NSKeyValueChangeRemoval;
}
}
static NSIndexSet *convert(realm::IndexSet const& in, NSMutableIndexSet *out) {
if (in.empty()) {
return nil;
}
[out removeAllIndexes];
for (auto range : in) {
[out addIndexesInRange:{range.first, range.second - range.first}];
}
return out;
}
void RLMWillChange(std::vector<realm::BindingContext::ObserverState> const& observed,
std::vector<void *> const& invalidated) {
for (auto info : invalidated) {
static_cast<RLMObservationInfo *>(info)->willChange(RLMInvalidatedKey);
}
if (!observed.empty()) {
NSMutableIndexSet *indexes = [NSMutableIndexSet new];
for (auto const& o : observed) {
forEach(o, [&](size_t, auto const& change, RLMObservationInfo *info) {
info->willChange(info->columnName(change.initial_column_index),
convert(change.kind), convert(change.indices, indexes));
});
}
}
for (auto info : invalidated) {
static_cast<RLMObservationInfo *>(info)->prepareForInvalidation();
}
}
void RLMDidChange(std::vector<realm::BindingContext::ObserverState> const& observed,
std::vector<void *> const& invalidated) {
if (!observed.empty()) {
// Loop in reverse order to avoid O(N^2) behavior in Foundation
NSMutableIndexSet *indexes = [NSMutableIndexSet new];
for (auto const& o : reverse(observed)) {
forEach(o, [&](size_t i, auto const& change, RLMObservationInfo *info) {
info->didChange(info->columnName(i), convert(change.kind), convert(change.indices, indexes));
});
}
}
for (auto const& info : reverse(invalidated)) {
static_cast<RLMObservationInfo *>(info)->didChange(RLMInvalidatedKey);
}
}

View File

@ -1,89 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMAccessor.h"
#import "RLMOptionalBase.h"
#import "RLMObject_Private.h"
#import "RLMObjectStore.h"
#import "RLMProperty_Private.h"
#import "RLMUtil.hpp"
#import <objc/runtime.h>
@interface RLMOptionalBase ()
@property (nonatomic) id unmanagedValue;
@end
@implementation RLMOptionalBase
- (instancetype)init {
return self;
}
- (id)underlyingValue {
if ((_object && _object->_realm) || _object.isInvalidated) {
return RLMDynamicGet(_object, _property);
}
else {
return _unmanagedValue;
}
}
- (void)setUnderlyingValue:(id)underlyingValue {
if ((_object && _object->_realm) || _object.isInvalidated) {
if (_property.isPrimary) {
@throw RLMException(@"Primary key can't be changed after an object is inserted.");
}
RLMDynamicSet(_object, _property, underlyingValue, RLMCreationOptionsNone);
}
else {
NSString *propertyName = _property.name;
[_object willChangeValueForKey:propertyName];
_unmanagedValue = underlyingValue;
[_object didChangeValueForKey:propertyName];
}
}
- (BOOL)isKindOfClass:(Class)aClass {
return [self.underlyingValue isKindOfClass:aClass] || RLMIsKindOfClass(object_getClass(self), aClass);
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.underlyingValue methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.underlyingValue];
}
- (id)forwardingTargetForSelector:(__unused SEL)sel {
return self.underlyingValue;
}
- (BOOL)respondsToSelector:(SEL)aSelector {
if (id val = self.underlyingValue) {
return [val respondsToSelector:aSelector];
}
return NO;
}
- (void)doesNotRecognizeSelector:(SEL)aSelector {
[self.underlyingValue doesNotRecognizeSelector:aSelector];
}
@end

View File

@ -1,118 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "RLMPredicateUtil.hpp"
// NSConditionalExpressionType is new in OS X 10.11 and iOS 9.0
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#define CONDITIONAL_EXPRESSION_DECLARED (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#define CONDITIONAL_EXPRESSION_DECLARED (__IPHONE_OS_VERSION_MIN_REQUIRED >= 90000)
#else
#define CONDITIONAL_EXPRESSION_DECLARED 0
#endif
#if !CONDITIONAL_EXPRESSION_DECLARED
#define NSConditionalExpressionType 20
@interface NSExpression (NewIn1011And90)
+ (NSExpression *)expressionForConditional:(NSPredicate *)predicate trueExpression:(NSExpression *)trueExpression falseExpression:(NSExpression *)falseExpression;
- (NSExpression *)trueExpression;
- (NSExpression *)falseExpression;
@end
#endif
namespace {
struct PredicateExpressionTransformer {
PredicateExpressionTransformer(ExpressionVisitor visitor) : m_visitor(visitor) { }
NSExpression *visit(NSExpression *expression) const;
NSPredicate *visit(NSPredicate *predicate) const;
ExpressionVisitor m_visitor;
};
NSExpression *PredicateExpressionTransformer::visit(NSExpression *expression) const {
expression = m_visitor(expression);
switch (expression.expressionType) {
case NSFunctionExpressionType: {
NSMutableArray *arguments = [NSMutableArray array];
for (NSExpression *argument in expression.arguments) {
[arguments addObject:visit(argument)];
}
if (expression.operand) {
return [NSExpression expressionForFunction:visit(expression.operand) selectorName:expression.function arguments:arguments];
} else {
return [NSExpression expressionForFunction:expression.function arguments:arguments];
}
}
case NSUnionSetExpressionType:
return [NSExpression expressionForUnionSet:visit(expression.leftExpression) with:visit(expression.rightExpression)];
case NSIntersectSetExpressionType:
return [NSExpression expressionForIntersectSet:visit(expression.leftExpression) with:visit(expression.rightExpression)];
case NSMinusSetExpressionType:
return [NSExpression expressionForMinusSet:visit(expression.leftExpression) with:visit(expression.rightExpression)];
case NSSubqueryExpressionType:
return [NSExpression expressionForSubquery:visit(expression.operand) usingIteratorVariable:expression.variable predicate:visit(expression.predicate)];
case NSAggregateExpressionType: {
NSMutableArray *subexpressions = [NSMutableArray array];
for (NSExpression *subexpression in expression.collection) {
[subexpressions addObject:visit(subexpression)];
}
return [NSExpression expressionForAggregate:subexpressions];
}
case NSConditionalExpressionType:
return [NSExpression expressionForConditional:visit(expression.predicate) trueExpression:visit(expression.trueExpression) falseExpression:visit(expression.falseExpression)];
default:
// The remaining expression types do not contain nested expressions or predicates.
return expression;
}
}
NSPredicate *PredicateExpressionTransformer::visit(NSPredicate *predicate) const {
if ([predicate isKindOfClass:[NSCompoundPredicate class]]) {
NSCompoundPredicate *compoundPredicate = (NSCompoundPredicate *)predicate;
NSMutableArray *subpredicates = [NSMutableArray array];
for (NSPredicate *subpredicate in compoundPredicate.subpredicates) {
[subpredicates addObject:visit(subpredicate)];
}
return [[NSCompoundPredicate alloc] initWithType:compoundPredicate.compoundPredicateType subpredicates:subpredicates];
}
if ([predicate isKindOfClass:[NSComparisonPredicate class]]) {
NSComparisonPredicate *comparisonPredicate = (NSComparisonPredicate *)predicate;
NSExpression *leftExpression = visit(comparisonPredicate.leftExpression);
NSExpression *rightExpression = visit(comparisonPredicate.rightExpression);
return [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression:rightExpression modifier:comparisonPredicate.comparisonPredicateModifier type:comparisonPredicate.predicateOperatorType options:comparisonPredicate.options];
}
return predicate;
}
} // anonymous namespace
NSPredicate *transformPredicate(NSPredicate *predicate, ExpressionVisitor visitor) {
PredicateExpressionTransformer transformer(visitor);
return transformer.visit(predicate);
}

View File

@ -1,569 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMProperty_Private.hpp"
#import "RLMArray.h"
#import "RLMListBase.h"
#import "RLMObject.h"
#import "RLMObject_Private.h"
#import "RLMOptionalBase.h"
#import "RLMSchema_Private.h"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
BOOL RLMPropertyTypeIsNullable(RLMPropertyType propertyType) {
return propertyType != RLMPropertyTypeArray && propertyType != RLMPropertyTypeLinkingObjects;
}
BOOL RLMPropertyTypeIsComputed(RLMPropertyType propertyType) {
return propertyType == RLMPropertyTypeLinkingObjects;
}
static bool rawTypeIsComputedProperty(NSString *rawType) {
if ([rawType isEqualToString:@"@\"RLMLinkingObjects\""] || [rawType hasPrefix:@"@\"RLMLinkingObjects<"]) {
return true;
}
return false;
}
@implementation RLMProperty
+ (instancetype)propertyForObjectStoreProperty:(const realm::Property &)prop {
return [[RLMProperty alloc] initWithName:@(prop.name.c_str())
type:(RLMPropertyType)prop.type
objectClassName:prop.object_type.length() ? @(prop.object_type.c_str()) : nil
linkOriginPropertyName:prop.link_origin_property_name.length() ? @(prop.link_origin_property_name.c_str()) : nil
indexed:prop.is_indexed
optional:prop.is_nullable];
}
- (instancetype)initWithName:(NSString *)name
type:(RLMPropertyType)type
objectClassName:(NSString *)objectClassName
linkOriginPropertyName:(NSString *)linkOriginPropertyName
indexed:(BOOL)indexed
optional:(BOOL)optional {
self = [super init];
if (self) {
_name = name;
_type = type;
_objectClassName = objectClassName;
_linkOriginPropertyName = linkOriginPropertyName;
_indexed = indexed;
_optional = optional;
[self setObjcCodeFromType];
[self updateAccessors];
}
return self;
}
- (void)setName:(NSString *)name {
_name = name;
[self updateAccessors];
}
- (void)updateAccessors {
// populate getter/setter names if generic
if (!_getterName) {
_getterName = _name;
}
if (!_setterName) {
// Objective-C setters only capitalize the first letter of the property name if it falls between 'a' and 'z'
int asciiCode = [_name characterAtIndex:0];
BOOL shouldUppercase = asciiCode >= 'a' && asciiCode <= 'z';
NSString *firstChar = [_name substringToIndex:1];
firstChar = shouldUppercase ? firstChar.uppercaseString : firstChar;
_setterName = [NSString stringWithFormat:@"set%@%@:", firstChar, [_name substringFromIndex:1]];
}
_getterSel = NSSelectorFromString(_getterName);
_setterSel = NSSelectorFromString(_setterName);
}
-(void)setObjcCodeFromType {
if (_optional) {
_objcType = '@';
return;
}
switch (_type) {
case RLMPropertyTypeInt:
_objcType = 'q';
break;
case RLMPropertyTypeBool:
_objcType = 'c';
break;
case RLMPropertyTypeDouble:
_objcType = 'd';
break;
case RLMPropertyTypeFloat:
_objcType = 'f';
break;
case RLMPropertyTypeAny:
case RLMPropertyTypeArray:
case RLMPropertyTypeData:
case RLMPropertyTypeDate:
case RLMPropertyTypeObject:
case RLMPropertyTypeString:
case RLMPropertyTypeLinkingObjects:
_objcType = '@';
break;
}
}
// determine RLMPropertyType from objc code - returns true if valid type was found/set
- (BOOL)setTypeFromRawType {
const char *code = _objcRawType.UTF8String;
_objcType = *code; // first char of type attr
// map to RLMPropertyType
switch (self.objcType) {
case 's': // short
case 'i': // int
case 'l': // long
case 'q': // long long
_type = RLMPropertyTypeInt;
return YES;
case 'f':
_type = RLMPropertyTypeFloat;
return YES;
case 'd':
_type = RLMPropertyTypeDouble;
return YES;
case 'c': // BOOL is stored as char - since rlm has no char type this is ok
case 'B':
_type = RLMPropertyTypeBool;
return YES;
case '@': {
_optional = true;
static const char arrayPrefix[] = "@\"RLMArray<";
static const int arrayPrefixLen = sizeof(arrayPrefix) - 1;
static const char numberPrefix[] = "@\"NSNumber<";
static const int numberPrefixLen = sizeof(numberPrefix) - 1;
static const char linkingObjectsPrefix[] = "@\"RLMLinkingObjects";
static const int linkingObjectsPrefixLen = sizeof(linkingObjectsPrefix) - 1;
if (strcmp(code, "@\"NSString\"") == 0) {
_type = RLMPropertyTypeString;
}
else if (strcmp(code, "@\"NSDate\"") == 0) {
_type = RLMPropertyTypeDate;
}
else if (strcmp(code, "@\"NSData\"") == 0) {
_type = RLMPropertyTypeData;
}
else if (strncmp(code, arrayPrefix, arrayPrefixLen) == 0) {
_optional = false;
// get object class from type string - @"RLMArray<objectClassName>"
_type = RLMPropertyTypeArray;
_objectClassName = [[NSString alloc] initWithBytes:code + arrayPrefixLen
length:strlen(code + arrayPrefixLen) - 2 // drop trailing >"
encoding:NSUTF8StringEncoding];
Class cls = [RLMSchema classForString:_objectClassName];
if (!cls) {
@throw RLMException(@"Property '%@' is of type 'RLMArray<%@>' which is not a supported RLMArray object type. "
@"RLMArrays can only contain instances of RLMObject subclasses. "
@"See https://realm.io/docs/objc/latest/#to-many for more information.", _name, _objectClassName);
}
}
else if (strncmp(code, numberPrefix, numberPrefixLen) == 0) {
// get number type from type string - @"NSNumber<objectClassName>"
NSString *numberType = [[NSString alloc] initWithBytes:code + numberPrefixLen
length:strlen(code + numberPrefixLen) - 2 // drop trailing >"
encoding:NSUTF8StringEncoding];
if ([numberType isEqualToString:@"RLMInt"]) {
_type = RLMPropertyTypeInt;
}
else if ([numberType isEqualToString:@"RLMFloat"]) {
_type = RLMPropertyTypeFloat;
}
else if ([numberType isEqualToString:@"RLMDouble"]) {
_type = RLMPropertyTypeDouble;
}
else if ([numberType isEqualToString:@"RLMBool"]) {
_type = RLMPropertyTypeBool;
}
else {
@throw RLMException(@"Property '%@' is of type 'NSNumber<%@>' which is not a supported NSNumber object type. "
@"NSNumbers can only be RLMInt, RLMFloat, RLMDouble, and RLMBool at the moment. "
@"See https://realm.io/docs/objc/latest for more information.", _name, numberType);
}
}
else if (strncmp(code, linkingObjectsPrefix, linkingObjectsPrefixLen) == 0 &&
(code[linkingObjectsPrefixLen] == '"' || code[linkingObjectsPrefixLen] == '<')) {
_type = RLMPropertyTypeLinkingObjects;
_optional = false;
if (!_objectClassName || !_linkOriginPropertyName) {
@throw RLMException(@"Property '%@' is of type RLMLinkingObjects but +linkingObjectsProperties did not specify the class "
"or property that is the origin of the link.", _name);
}
// If the property was declared with a protocol indicating the contained type, validate that it matches
// the class from the dictionary returned by +linkingObjectsProperties.
if (code[linkingObjectsPrefixLen] == '<') {
NSString *classNameFromProtocol = [[NSString alloc] initWithBytes:code + linkingObjectsPrefixLen + 1
length:strlen(code + linkingObjectsPrefixLen) - 3 // drop trailing >"
encoding:NSUTF8StringEncoding];
if (![_objectClassName isEqualToString:classNameFromProtocol]) {
@throw RLMException(@"Property '%@' was declared with type RLMLinkingObjects<%@>, but a conflicting "
"class name of '%@' was returned by +linkingObjectsProperties.", _name,
classNameFromProtocol, _objectClassName);
}
}
}
else if (strcmp(code, "@\"NSNumber\"") == 0) {
@throw RLMException(@"Property '%@' requires a protocol defining the contained type - example: NSNumber<RLMInt>.", _name);
}
else if (strcmp(code, "@\"RLMArray\"") == 0) {
@throw RLMException(@"Property '%@' requires a protocol defining the contained type - example: RLMArray<Person>.", _name);
}
else {
NSString *className;
Class cls = nil;
if (code[1] == '\0') {
className = @"id";
}
else {
// for objects strip the quotes and @
className = [_objcRawType substringWithRange:NSMakeRange(2, _objcRawType.length-3)];
cls = [RLMSchema classForString:className];
}
if (!cls) {
@throw RLMException(@"Property '%@' is declared as '%@', which is not a supported RLMObject property type. "
@"All properties must be primitives, NSString, NSDate, NSData, NSNumber, RLMArray, RLMLinkingObjects, or subclasses of RLMObject. "
@"See https://realm.io/docs/objc/latest/api/Classes/RLMObject.html for more information.", _name, className);
}
_type = RLMPropertyTypeObject;
_optional = true;
_objectClassName = [cls className] ?: className;
}
return YES;
}
default:
return NO;
}
}
- (bool)parseObjcProperty:(objc_property_t)property {
unsigned int count;
objc_property_attribute_t *attrs = property_copyAttributeList(property, &count);
bool isReadOnly = false;
for (size_t i = 0; i < count; ++i) {
switch (*attrs[i].name) {
case 'T':
_objcRawType = @(attrs[i].value);
break;
case 'R':
isReadOnly = true;
break;
case 'N':
// nonatomic
break;
case 'D':
// dynamic
break;
case 'G':
_getterName = @(attrs[i].value);
break;
case 'S':
_setterName = @(attrs[i].value);
break;
default:
break;
}
}
free(attrs);
return isReadOnly;
}
- (instancetype)initSwiftPropertyWithName:(NSString *)name
indexed:(BOOL)indexed
linkPropertyDescriptor:(RLMPropertyDescriptor *)linkPropertyDescriptor
property:(objc_property_t)property
instance:(RLMObject *)obj {
self = [super init];
if (!self) {
return nil;
}
_name = name;
_indexed = indexed;
if (linkPropertyDescriptor) {
_objectClassName = [linkPropertyDescriptor.objectClass className];
_linkOriginPropertyName = linkPropertyDescriptor.propertyName;
}
if ([self parseObjcProperty:property]) {
return nil;
}
id propertyValue = [obj valueForKey:_name];
// FIXME: temporarily workaround added since Objective-C generics used in Swift show up as `@`
// * broken starting in Swift 3.0 Xcode 8 b1
// * tested to still be broken in Swift 3.0 Xcode 8 b6
// * if the Realm Objective-C Swift tests pass with this removed, it's been fixed
// * once it has been fixed, remove this entire conditional block (contents included) entirely
// * Bug Report: SR-2031 https://bugs.swift.org/browse/SR-2031
if ([_objcRawType isEqualToString:@"@"]) {
if (propertyValue) {
_objcRawType = [NSString stringWithFormat:@"@\"%@\"", [propertyValue class]];
} else if (linkPropertyDescriptor) {
// we're going to naively assume that the user used the correct type since we can't check it
_objcRawType = @"@\"RLMLinkingObjects\"";
}
}
// convert array types to objc variant
if ([_objcRawType isEqualToString:@"@\"RLMArray\""]) {
_objcRawType = [NSString stringWithFormat:@"@\"RLMArray<%@>\"", [propertyValue objectClassName]];
}
else if ([_objcRawType isEqualToString:@"@\"NSNumber\""]) {
const char *numberType = [propertyValue objCType];
if (!numberType) {
@throw RLMException(@"Can't persist NSNumber without default value: use a Swift-native number type or provide a default value.");
}
switch (*numberType) {
case 'i':
case 'l':
case 'q':
_objcRawType = @"@\"NSNumber<RLMInt>\"";
break;
case 'f':
_objcRawType = @"@\"NSNumber<RLMFloat>\"";
break;
case 'd':
_objcRawType = @"@\"NSNumber<RLMDouble>\"";
break;
case 'B':
case 'c':
_objcRawType = @"@\"NSNumber<RLMBool>\"";
break;
default:
@throw RLMException(@"Can't persist NSNumber of type '%s': only integers, floats, doubles, and bools are currently supported.", numberType);
}
}
auto throwForPropertyName = ^(NSString *propertyName){
@throw RLMException(@"Can't persist property '%@' with incompatible type. "
"Add to Object.ignoredProperties() class method to ignore.",
propertyName);
};
if (![self setTypeFromRawType]) {
throwForPropertyName(self.name);
}
if (_objcType == 'c') {
// Check if it's a BOOL or Int8 by trying to set it to 2 and seeing if
// it actually sets it to 1.
[obj setValue:@2 forKey:name];
NSNumber *value = [obj valueForKey:name];
_type = value.intValue == 2 ? RLMPropertyTypeInt : RLMPropertyTypeBool;
}
// update getter/setter names
[self updateAccessors];
return self;
}
- (instancetype)initWithName:(NSString *)name
indexed:(BOOL)indexed
linkPropertyDescriptor:(RLMPropertyDescriptor *)linkPropertyDescriptor
property:(objc_property_t)property
{
self = [super init];
if (!self) {
return nil;
}
_name = name;
_indexed = indexed;
if (linkPropertyDescriptor) {
_objectClassName = [linkPropertyDescriptor.objectClass className];
_linkOriginPropertyName = linkPropertyDescriptor.propertyName;
}
bool isReadOnly = [self parseObjcProperty:property];
bool isComputedProperty = rawTypeIsComputedProperty(_objcRawType);
if (isReadOnly && !isComputedProperty) {
return nil;
}
if (![self setTypeFromRawType]) {
@throw RLMException(@"Can't persist property '%@' with incompatible type. "
"Add to ignoredPropertyNames: method to ignore.", self.name);
}
if (!isReadOnly && isComputedProperty) {
@throw RLMException(@"Property '%@' must be declared as readonly as %@ properties cannot be written to.",
self.name, RLMTypeToString(_type));
}
// update getter/setter names
[self updateAccessors];
return self;
}
- (instancetype)initSwiftListPropertyWithName:(NSString *)name
ivar:(Ivar)ivar
objectClassName:(NSString *)objectClassName {
self = [super init];
if (!self) {
return nil;
}
_name = name;
_type = RLMPropertyTypeArray;
_objectClassName = objectClassName;
_objcType = 't';
_swiftIvar = ivar;
// no obj-c property for generic lists, and thus no getter/setter names
return self;
}
- (instancetype)initSwiftOptionalPropertyWithName:(NSString *)name
indexed:(BOOL)indexed
ivar:(Ivar)ivar
propertyType:(RLMPropertyType)propertyType {
self = [super init];
if (!self) {
return nil;
}
_name = name;
_type = propertyType;
_indexed = indexed;
_objcType = '@';
_swiftIvar = ivar;
_optional = true;
// no obj-c property for generic optionals, and thus no getter/setter names
return self;
}
- (instancetype)initSwiftLinkingObjectsPropertyWithName:(NSString *)name
ivar:(Ivar)ivar
objectClassName:(NSString *)objectClassName
linkOriginPropertyName:(NSString *)linkOriginPropertyName {
self = [super init];
if (!self) {
return nil;
}
_name = name;
_type = RLMPropertyTypeLinkingObjects;
_objectClassName = objectClassName;
_linkOriginPropertyName = linkOriginPropertyName;
_objcType = '@';
_swiftIvar = ivar;
// no obj-c property for generic linking objects properties, and thus no getter/setter names
return self;
}
- (id)copyWithZone:(NSZone *)zone {
RLMProperty *prop = [[RLMProperty allocWithZone:zone] init];
prop->_name = _name;
prop->_type = _type;
prop->_objcType = _objcType;
prop->_objectClassName = _objectClassName;
prop->_indexed = _indexed;
prop->_getterName = _getterName;
prop->_setterName = _setterName;
prop->_getterSel = _getterSel;
prop->_setterSel = _setterSel;
prop->_isPrimary = _isPrimary;
prop->_swiftIvar = _swiftIvar;
prop->_optional = _optional;
prop->_linkOriginPropertyName = _linkOriginPropertyName;
return prop;
}
- (RLMProperty *)copyWithNewName:(NSString *)name {
RLMProperty *prop = [self copy];
prop.name = name;
return prop;
}
- (BOOL)isEqual:(id)object {
if (![object isKindOfClass:[RLMProperty class]]) {
return NO;
}
return [self isEqualToProperty:object];
}
- (BOOL)isEqualToProperty:(RLMProperty *)property {
return _type == property->_type
&& _indexed == property->_indexed
&& _isPrimary == property->_isPrimary
&& _optional == property->_optional
&& [_name isEqualToString:property->_name]
&& (_objectClassName == property->_objectClassName || [_objectClassName isEqualToString:property->_objectClassName])
&& (_linkOriginPropertyName == property->_linkOriginPropertyName || [_linkOriginPropertyName isEqualToString:property->_linkOriginPropertyName]);
}
- (NSString *)description {
return [NSString stringWithFormat:@"%@ {\n\ttype = %@;\n\tobjectClassName = %@;\n\tlinkOriginPropertyName = %@;\n\tindexed = %@;\n\tisPrimary = %@;\n\toptional = %@;\n}", self.name, RLMTypeToString(self.type), self.objectClassName, self.linkOriginPropertyName, self.indexed ? @"YES" : @"NO", self.isPrimary ? @"YES" : @"NO", self.optional ? @"YES" : @"NO"];
}
- (realm::Property)objectStoreCopy {
realm::Property p;
p.name = _name.UTF8String;
p.type = (realm::PropertyType)_type;
p.object_type = _objectClassName ? _objectClassName.UTF8String : "";
p.is_indexed = _indexed;
p.is_nullable = _optional;
p.link_origin_property_name = _linkOriginPropertyName ? _linkOriginPropertyName.UTF8String : "";
return p;
}
@end
@implementation RLMPropertyDescriptor
+ (instancetype)descriptorWithClass:(Class)objectClass propertyName:(NSString *)propertyName
{
RLMPropertyDescriptor *descriptor = [[RLMPropertyDescriptor alloc] init];
descriptor->_objectClass = objectClass;
descriptor->_propertyName = propertyName;
return descriptor;
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -1,689 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMRealm_Private.hpp"
#import "RLMAnalytics.hpp"
#import "RLMArray_Private.hpp"
#import "RLMRealmConfiguration_Private.hpp"
#import "RLMMigration_Private.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMProperty_Private.h"
#import "RLMObjectStore.h"
#import "RLMObject_Private.h"
#import "RLMObject_Private.hpp"
#import "RLMObservation.hpp"
#import "RLMProperty.h"
#import "RLMQueryUtil.hpp"
#import "RLMRealmUtil.hpp"
#import "RLMSchema_Private.hpp"
#import "RLMUpdateChecker.hpp"
#import "RLMUtil.hpp"
#include "impl/realm_coordinator.hpp"
#include "object_store.hpp"
#include "schema.hpp"
#include "shared_realm.hpp"
#include <realm/commit_log.hpp>
#include <realm/disable_sync_to_disk.hpp>
#include <realm/version.hpp>
using namespace realm;
using util::File;
@interface RLMRealm ()
@property (nonatomic, strong) NSHashTable *notificationHandlers;
- (void)sendNotifications:(RLMNotification)notification;
@end
void RLMDisableSyncToDisk() {
realm::disable_sync_to_disk();
}
// Notification Token
@interface RLMRealmNotificationToken : RLMNotificationToken
@property (nonatomic, strong) RLMRealm *realm;
@property (nonatomic, copy) RLMNotificationBlock block;
@end
@implementation RLMRealmNotificationToken
- (void)stop {
[_realm verifyThread];
[_realm.notificationHandlers removeObject:self];
_realm = nil;
_block = nil;
}
- (void)dealloc {
if (_realm || _block) {
NSLog(@"RLMNotificationToken released without unregistering a notification. You must hold "
@"on to the RLMNotificationToken returned from addNotificationBlock and call "
@"-[RLMNotificationToken stop] when you no longer wish to receive RLMRealm notifications.");
}
}
@end
static bool shouldForciblyDisableEncryption() {
static bool disableEncryption = getenv("REALM_DISABLE_ENCRYPTION");
return disableEncryption;
}
NSData *RLMRealmValidatedEncryptionKey(NSData *key) {
if (shouldForciblyDisableEncryption()) {
return nil;
}
if (key) {
if (key.length != 64) {
@throw RLMException(@"Encryption key must be exactly 64 bytes long");
}
#if TARGET_OS_WATCH
@throw RLMException(@"Cannot open an encrypted Realm on watchOS.");
#endif
}
return key;
}
@implementation RLMRealm {
NSHashTable *_collectionEnumerators;
}
+ (BOOL)isCoreDebug {
return realm::Version::has_feature(realm::feature_Debug);
}
+ (void)initialize {
static bool initialized;
if (initialized) {
return;
}
initialized = true;
RLMCheckForUpdates();
RLMSendAnalytics();
}
- (BOOL)isEmpty {
return realm::ObjectStore::is_empty(self.group);
}
- (void)verifyThread {
_realm->verify_thread();
}
- (BOOL)inWriteTransaction {
return _realm->is_in_transaction();
}
- (realm::Group &)group {
return _realm->read_group();
}
- (BOOL)autorefresh {
return _realm->auto_refresh();
}
- (void)setAutorefresh:(BOOL)autorefresh {
_realm->set_auto_refresh(autorefresh);
}
+ (NSString *)writeableTemporaryPathForFile:(NSString *)fileName {
return [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
}
+ (instancetype)defaultRealm {
return [RLMRealm realmWithConfiguration:[RLMRealmConfiguration rawDefaultConfiguration] error:nil];
}
+ (instancetype)realmWithURL:(NSURL *)fileURL {
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
configuration.fileURL = fileURL;
return [RLMRealm realmWithConfiguration:configuration error:nil];
}
// ARC tries to eliminate calls to autorelease when the value is then immediately
// returned, but this results in significantly different semantics between debug
// and release builds for RLMRealm, so force it to always autorelease.
static id RLMAutorelease(id value) {
// +1 __bridge_retained, -1 CFAutorelease
return value ? (__bridge id)CFAutorelease((__bridge_retained CFTypeRef)value) : nil;
}
static void RLMRealmSetSchemaAndAlign(RLMRealm *realm, RLMSchema *targetSchema) {
realm.schema = targetSchema;
realm->_info = RLMSchemaInfo(realm, targetSchema, realm->_realm->schema());
}
+ (instancetype)realmWithSharedRealm:(SharedRealm)sharedRealm schema:(RLMSchema *)schema {
RLMRealm *realm = [RLMRealm new];
realm->_realm = sharedRealm;
realm->_dynamic = YES;
RLMRealmSetSchemaAndAlign(realm, schema);
return RLMAutorelease(realm);
}
REALM_NOINLINE void RLMRealmTranslateException(NSError **error) {
try {
throw;
}
catch (RealmFileException const& ex) {
switch (ex.kind()) {
case RealmFileException::Kind::PermissionDenied:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFilePermissionDenied, ex), error);
break;
case RealmFileException::Kind::IncompatibleLockFile: {
NSString *err = @"Realm file is currently open in another process "
"which cannot share access with this process. All "
"processes sharing a single file must be the same "
"architecture. For sharing files between the Realm "
"Browser and an iOS simulator, this means that you "
"must use a 64-bit simulator.";
RLMSetErrorOrThrow(RLMMakeError(RLMErrorIncompatibleLockFile,
File::PermissionDenied(err.UTF8String, ex.path())), error);
break;
}
case RealmFileException::Kind::NotFound:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileNotFound, ex), error);
break;
case RealmFileException::Kind::Exists:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileExists, ex), error);
break;
case RealmFileException::Kind::AccessError:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileAccess, ex), error);
break;
case RealmFileException::Kind::FormatUpgradeRequired:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileFormatUpgradeRequired, ex), error);
break;
default:
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, ex), error);
break;
}
}
catch (AddressSpaceExhausted const &ex) {
RLMSetErrorOrThrow(RLMMakeError(RLMErrorAddressSpaceExhausted, ex), error);
}
catch (SchemaMismatchException const& ex) {
RLMSetErrorOrThrow(RLMMakeError(RLMErrorSchemaMismatch, ex), error);
}
catch (std::system_error const& ex) {
RLMSetErrorOrThrow(RLMMakeError(ex), error);
}
catch (const std::exception &exp) {
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), error);
}
}
+ (instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error {
bool dynamic = configuration.dynamic;
bool readOnly = configuration.readOnly;
{
Realm::Config& config = configuration.config;
// try to reuse existing realm first
if (config.cache || dynamic) {
if (RLMRealm *realm = RLMGetThreadLocalCachedRealmForPath(config.path)) {
auto const& old_config = realm->_realm->config();
if (old_config.read_only() != config.read_only()) {
@throw RLMException(@"Realm at path '%s' already opened with different read permissions", config.path.c_str());
}
if (old_config.in_memory != config.in_memory) {
@throw RLMException(@"Realm at path '%s' already opened with different inMemory settings", config.path.c_str());
}
if (realm->_dynamic != dynamic) {
@throw RLMException(@"Realm at path '%s' already opened with different dynamic settings", config.path.c_str());
}
if (old_config.encryption_key != config.encryption_key) {
@throw RLMException(@"Realm at path '%s' already opened with different encryption key", config.path.c_str());
}
return RLMAutorelease(realm);
}
}
}
configuration = [configuration copy];
Realm::Config& config = configuration.config;
RLMRealm *realm = [RLMRealm new];
realm->_dynamic = dynamic;
// protects the realm cache and accessors cache
static std::mutex initLock;
std::lock_guard<std::mutex> lock(initLock);
try {
realm->_realm = Realm::get_shared_realm(config);
}
catch (...) {
RLMRealmTranslateException(error);
return nil;
}
// if we have a cached realm on another thread, copy without a transaction
if (RLMRealm *cachedRealm = RLMGetAnyCachedRealmForPath(config.path)) {
RLMRealmSetSchemaAndAlign(realm, cachedRealm.schema);
}
else if (dynamic) {
RLMRealmSetSchemaAndAlign(realm, [RLMSchema dynamicSchemaFromObjectStoreSchema:realm->_realm->schema()]);
}
else {
// set/align schema or perform migration if needed
RLMSchema *schema = configuration.customSchema ?: RLMSchema.sharedSchema;
Realm::MigrationFunction migrationFunction;
auto migrationBlock = configuration.migrationBlock;
if (migrationBlock && configuration.schemaVersion > 0) {
migrationFunction = [=](SharedRealm old_realm, SharedRealm realm, Schema& mutableSchema) {
RLMSchema *oldSchema = [RLMSchema dynamicSchemaFromObjectStoreSchema:old_realm->schema()];
RLMRealm *oldRealm = [RLMRealm realmWithSharedRealm:old_realm schema:oldSchema];
// The destination RLMRealm can't just use the schema from the
// SharedRealm because it doesn't have information about whether or
// not a class was defined in Swift, which effects how new objects
// are created
RLMRealm *newRealm = [RLMRealm realmWithSharedRealm:realm schema:schema.copy];
[[[RLMMigration alloc] initWithRealm:newRealm oldRealm:oldRealm schema:mutableSchema] execute:migrationBlock];
oldRealm->_realm = nullptr;
newRealm->_realm = nullptr;
};
}
try {
realm->_realm->update_schema(schema.objectStoreCopy, config.schema_version,
std::move(migrationFunction));
}
catch (...) {
RLMRealmTranslateException(error);
return nil;
}
RLMRealmSetSchemaAndAlign(realm, schema);
RLMRealmCreateAccessors(realm.schema);
if (!readOnly) {
// initializing the schema started a read transaction, so end it
[realm invalidate];
}
}
if (config.cache) {
RLMCacheRealm(config.path, realm);
}
if (!readOnly) {
realm->_realm->m_binding_context = RLMCreateBindingContext(realm);
}
return RLMAutorelease(realm);
}
+ (void)resetRealmState {
RLMClearRealmCache();
realm::_impl::RealmCoordinator::clear_cache();
[RLMRealmConfiguration resetRealmConfigurationState];
}
- (void)verifyNotificationsAreSupported {
[self verifyThread];
if (_realm->config().read_only()) {
@throw RLMException(@"Read-only Realms do not change and do not have change notifications");
}
if (!_realm->can_deliver_notifications()) {
@throw RLMException(@"Can only add notification blocks from within runloops.");
}
}
- (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block {
if (!block) {
@throw RLMException(@"The notification block should not be nil");
}
[self verifyNotificationsAreSupported];
_realm->read_group();
if (!_notificationHandlers) {
_notificationHandlers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
}
RLMRealmNotificationToken *token = [[RLMRealmNotificationToken alloc] init];
token.realm = self;
token.block = block;
[_notificationHandlers addObject:token];
return token;
}
- (void)sendNotifications:(RLMNotification)notification {
NSAssert(!_realm->config().read_only(), @"Read-only realms do not have notifications");
NSUInteger count = _notificationHandlers.count;
if (count == 0) {
return;
}
// call this realms notification blocks
if (count == 1) {
if (auto block = [_notificationHandlers.anyObject block]) {
block(notification, self);
}
}
else {
for (RLMRealmNotificationToken *token in _notificationHandlers.allObjects) {
if (auto block = token.block) {
block(notification, self);
}
}
}
}
- (RLMRealmConfiguration *)configuration {
RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init];
configuration.config = _realm->config();
configuration.dynamic = _dynamic;
configuration.customSchema = _schema;
return configuration;
}
- (void)beginWriteTransaction {
try {
_realm->begin_transaction();
}
catch (std::exception &ex) {
@throw RLMException(ex);
}
}
- (void)commitWriteTransaction {
[self commitWriteTransaction:nil];
}
- (BOOL)commitWriteTransaction:(NSError **)outError {
try {
_realm->commit_transaction();
return YES;
}
catch (...) {
RLMRealmTranslateException(outError);
return NO;
}
}
- (void)transactionWithBlock:(void(^)(void))block {
[self transactionWithBlock:block error:nil];
}
- (BOOL)transactionWithBlock:(void(^)(void))block error:(NSError **)outError {
[self beginWriteTransaction];
block();
if (_realm->is_in_transaction()) {
return [self commitWriteTransaction:outError];
}
return YES;
}
- (void)cancelWriteTransaction {
try {
_realm->cancel_transaction();
}
catch (std::exception &ex) {
@throw RLMException(ex);
}
}
- (void)invalidate {
if (_realm->is_in_transaction()) {
NSLog(@"WARNING: An RLMRealm instance was invalidated during a write "
"transaction and all pending changes have been rolled back.");
}
[self detachAllEnumerators];
for (auto& objectInfo : _info) {
for (RLMObservationInfo *info : objectInfo.second.observedObjects) {
info->willChange(RLMInvalidatedKey);
}
}
_realm->invalidate();
for (auto& objectInfo : _info) {
for (RLMObservationInfo *info : objectInfo.second.observedObjects) {
info->didChange(RLMInvalidatedKey);
}
objectInfo.second.releaseTable();
}
}
/**
Replaces all string columns in this Realm with a string enumeration column and compacts the
database file.
Cannot be called from a write transaction.
Compaction will not occur if other `RLMRealm` instances exist.
While compaction is in progress, attempts by other threads or processes to open the database will
wait.
Be warned that resource requirements for compaction is proportional to the amount of live data in
the database.
Compaction works by writing the database contents to a temporary database file and then replacing
the database with the temporary one. The name of the temporary file is formed by appending
`.tmp_compaction_space` to the name of the database.
@return YES if the compaction succeeded.
*/
- (BOOL)compact {
// compact() automatically ends the read transaction, but we need to clean
// up cached state and send invalidated notifications when that happens, so
// explicitly end it first unless we're in a write transaction (in which
// case compact() will throw an exception)
if (!_realm->is_in_transaction()) {
[self invalidate];
}
try {
return _realm->compact();
}
catch (std::exception const& ex) {
@throw RLMException(ex);
}
}
- (void)dealloc {
if (_realm) {
if (_realm->is_in_transaction()) {
[self cancelWriteTransaction];
NSLog(@"WARNING: An RLMRealm instance was deallocated during a write transaction and all "
"pending changes have been rolled back. Make sure to retain a reference to the "
"RLMRealm for the duration of the write transaction.");
}
}
}
- (BOOL)refresh {
return _realm->refresh();
}
- (void)addObject:(__unsafe_unretained RLMObject *const)object {
RLMAddObjectToRealm(object, self, false);
}
- (void)addObjects:(id<NSFastEnumeration>)array {
for (RLMObject *obj in array) {
if (![obj isKindOfClass:[RLMObject class]]) {
@throw RLMException(@"Cannot insert objects of type %@ with addObjects:. Only RLMObjects are supported.",
NSStringFromClass(obj.class));
}
[self addObject:obj];
}
}
- (void)addOrUpdateObject:(RLMObject *)object {
// verify primary key
if (!object.objectSchema.primaryKeyProperty) {
@throw RLMException(@"'%@' does not have a primary key and can not be updated", object.objectSchema.className);
}
RLMAddObjectToRealm(object, self, true);
}
- (void)addOrUpdateObjectsFromArray:(id)array {
for (RLMObject *obj in array) {
[self addOrUpdateObject:obj];
}
}
- (void)deleteObject:(RLMObject *)object {
RLMDeleteObjectFromRealm(object, self);
}
- (void)deleteObjects:(id)array {
if ([array respondsToSelector:@selector(realm)] && [array respondsToSelector:@selector(deleteObjectsFromRealm)]) {
if (self != (RLMRealm *)[array realm]) {
@throw RLMException(@"Can only delete objects from the Realm they belong to.");
}
[array deleteObjectsFromRealm];
}
else if ([array conformsToProtocol:@protocol(NSFastEnumeration)]) {
for (id obj in array) {
if ([obj isKindOfClass:RLMObjectBase.class]) {
RLMDeleteObjectFromRealm(obj, self);
}
}
}
else {
@throw RLMException(@"Invalid array type - container must be an RLMArray, RLMArray, or NSArray of RLMObjects");
}
}
- (void)deleteAllObjects {
RLMDeleteAllObjectsFromRealm(self);
}
- (RLMResults *)allObjects:(NSString *)objectClassName {
return RLMGetObjects(self, objectClassName, nil);
}
- (RLMResults *)objects:(NSString *)objectClassName where:(NSString *)predicateFormat, ... {
va_list args;
va_start(args, predicateFormat);
RLMResults *results = [self objects:objectClassName where:predicateFormat args:args];
va_end(args);
return results;
}
- (RLMResults *)objects:(NSString *)objectClassName where:(NSString *)predicateFormat args:(va_list)args {
return [self objects:objectClassName withPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}
- (RLMResults *)objects:(NSString *)objectClassName withPredicate:(NSPredicate *)predicate {
return RLMGetObjects(self, objectClassName, predicate);
}
- (RLMObject *)objectWithClassName:(NSString *)className forPrimaryKey:(id)primaryKey {
return RLMGetObject(self, className, primaryKey);
}
+ (uint64_t)schemaVersionAtURL:(NSURL *)fileURL encryptionKey:(NSData *)key error:(NSError **)error {
try {
RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
config.fileURL = fileURL;
config.encryptionKey = RLMRealmValidatedEncryptionKey(key);
uint64_t version = Realm::get_schema_version(config.config);
if (version == realm::ObjectStore::NotVersioned) {
RLMSetErrorOrThrow([NSError errorWithDomain:RLMErrorDomain code:RLMErrorFail userInfo:@{NSLocalizedDescriptionKey:@"Cannot open an uninitialized realm in read-only mode"}], error);
}
return version;
}
catch (std::exception &exp) {
RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), error);
return RLMNotVersioned;
}
}
+ (nullable NSError *)migrateRealm:(RLMRealmConfiguration *)configuration {
// Preserves backwards compatibility
NSError *error;
[self performMigrationForConfiguration:configuration error:&error];
return error;
}
+ (BOOL)performMigrationForConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error {
if (RLMGetAnyCachedRealmForPath(configuration.config.path)) {
@throw RLMException(@"Cannot migrate Realms that are already open.");
}
NSError *localError; // Prevents autorelease
BOOL success;
@autoreleasepool {
success = [RLMRealm realmWithConfiguration:configuration error:&localError] != nil;
}
if (!success && error) {
*error = localError; // Must set outside pool otherwise will free anyway
}
return success;
}
- (RLMObject *)createObject:(NSString *)className withValue:(id)value {
return (RLMObject *)RLMCreateObjectInRealmWithValue(self, className, value, false);
}
- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(NSData *)key error:(NSError **)error {
key = RLMRealmValidatedEncryptionKey(key);
NSString *path = fileURL.path;
try {
_realm->write_copy(path.UTF8String, {static_cast<const char *>(key.bytes), key.length});
return YES;
}
catch (...) {
__autoreleasing NSError *dummyError;
if (!error) {
error = &dummyError;
}
RLMRealmTranslateException(error);
return NO;
}
return NO;
}
- (void)registerEnumerator:(RLMFastEnumerator *)enumerator {
if (!_collectionEnumerators) {
_collectionEnumerators = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
}
[_collectionEnumerators addObject:enumerator];
}
- (void)unregisterEnumerator:(RLMFastEnumerator *)enumerator {
[_collectionEnumerators removeObject:enumerator];
}
- (void)detachAllEnumerators {
for (RLMFastEnumerator *enumerator in _collectionEnumerators) {
[enumerator detach];
}
_collectionEnumerators = nil;
}
@end

View File

@ -1,295 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMRealmConfiguration_Private.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMRealm_Private.h"
#import "RLMSchema_Private.hpp"
#import "RLMUtil.hpp"
#import "schema.hpp"
#import "shared_realm.hpp"
static NSString *const c_RLMRealmConfigurationProperties[] = {
@"fileURL",
@"inMemoryIdentifier",
@"encryptionKey",
@"readOnly",
@"schemaVersion",
@"migrationBlock",
@"deleteRealmIfMigrationNeeded",
@"dynamic",
@"customSchema",
};
static NSString *const c_defaultRealmFileName = @"default.realm";
RLMRealmConfiguration *s_defaultConfiguration;
static NSString *defaultDirectoryForBundleIdentifier(NSString *bundleIdentifier) {
#if TARGET_OS_TV
(void)bundleIdentifier;
// tvOS prohibits writing to the Documents directory, so we use the Library/Caches directory instead.
return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
#elif TARGET_OS_IPHONE
(void)bundleIdentifier;
// On iOS the Documents directory isn't user-visible, so put files there
return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
#else
// On OS X it is, so put files in Application Support. If we aren't running
// in a sandbox, put it in a subdirectory based on the bundle identifier
// to avoid accidentally sharing files between applications
NSString *path = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0];
if (![[NSProcessInfo processInfo] environment][@"APP_SANDBOX_CONTAINER_ID"]) {
if (!bundleIdentifier) {
bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
}
if (!bundleIdentifier) {
bundleIdentifier = [NSBundle mainBundle].executablePath.lastPathComponent;
}
path = [path stringByAppendingPathComponent:bundleIdentifier];
// create directory
[[NSFileManager defaultManager] createDirectoryAtPath:path
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
return path;
#endif
}
NSString *RLMRealmPathForFileAndBundleIdentifier(NSString *fileName, NSString *bundleIdentifier) {
return [defaultDirectoryForBundleIdentifier(bundleIdentifier)
stringByAppendingPathComponent:fileName];
}
NSString *RLMRealmPathForFile(NSString *fileName) {
static NSString *directory = defaultDirectoryForBundleIdentifier(nil);
return [directory stringByAppendingPathComponent:fileName];
}
@implementation RLMRealmConfiguration {
realm::Realm::Config _config;
}
- (realm::Realm::Config&)config {
return _config;
}
+ (instancetype)defaultConfiguration {
return [[self rawDefaultConfiguration] copy];
}
+ (void)setDefaultConfiguration:(RLMRealmConfiguration *)configuration {
if (!configuration) {
@throw RLMException(@"Cannot set the default configuration to nil.");
}
@synchronized(c_defaultRealmFileName) {
s_defaultConfiguration = [configuration copy];
}
}
+ (RLMRealmConfiguration *)rawDefaultConfiguration {
@synchronized(c_defaultRealmFileName) {
if (!s_defaultConfiguration) {
s_defaultConfiguration = [[RLMRealmConfiguration alloc] init];
}
}
return s_defaultConfiguration;
}
+ (void)resetRealmConfigurationState {
@synchronized(c_defaultRealmFileName) {
s_defaultConfiguration = nil;
}
}
- (instancetype)init {
self = [super init];
if (self) {
static NSURL *defaultRealmURL = [NSURL fileURLWithPath:RLMRealmPathForFile(c_defaultRealmFileName)];
self.fileURL = defaultRealmURL;
self.schemaVersion = 0;
}
return self;
}
- (instancetype)copyWithZone:(NSZone *)zone {
RLMRealmConfiguration *configuration = [[[self class] allocWithZone:zone] init];
configuration->_config = _config;
configuration->_dynamic = _dynamic;
configuration->_migrationBlock = _migrationBlock;
configuration->_customSchema = _customSchema;
return configuration;
}
- (NSString *)description {
NSMutableString *string = [NSMutableString stringWithFormat:@"%@ {\n", self.class];
for (NSString *key : c_RLMRealmConfigurationProperties) {
NSString *description = [[self valueForKey:key] description];
description = [description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"];
[string appendFormat:@"\t%@ = %@;\n", key, description];
}
return [string stringByAppendingString:@"}"];
}
static void RLMNSStringToStdString(std::string &out, NSString *in) {
out.resize([in maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
if (out.empty()) {
return;
}
NSUInteger size = out.size();
[in getBytes:&out[0]
maxLength:size
usedLength:&size
encoding:NSUTF8StringEncoding
options:0 range:{0, in.length} remainingRange:nullptr];
out.resize(size);
}
- (NSURL *)fileURL {
return _config.in_memory ? nil : [NSURL fileURLWithPath:@(_config.path.c_str())];
}
- (void)setFileURL:(NSURL *)fileURL {
NSString *path = fileURL.path;
if (path.length == 0) {
@throw RLMException(@"Realm path must not be empty");
}
RLMNSStringToStdString(_config.path, path);
_config.in_memory = false;
}
- (NSString *)inMemoryIdentifier {
if (!_config.in_memory) {
return nil;
}
return [@(_config.path.c_str()) lastPathComponent];
}
- (void)setInMemoryIdentifier:(NSString *)inMemoryIdentifier {
if (inMemoryIdentifier.length == 0) {
@throw RLMException(@"In-memory identifier must not be empty");
}
RLMNSStringToStdString(_config.path, [NSTemporaryDirectory() stringByAppendingPathComponent:inMemoryIdentifier]);
_config.in_memory = true;
}
- (NSData *)encryptionKey {
return _config.encryption_key.empty() ? nil : [NSData dataWithBytes:_config.encryption_key.data() length:_config.encryption_key.size()];
}
- (void)setEncryptionKey:(NSData * __nullable)encryptionKey {
if (NSData *key = RLMRealmValidatedEncryptionKey(encryptionKey)) {
auto bytes = static_cast<const char *>(key.bytes);
_config.encryption_key.assign(bytes, bytes + key.length);
}
else {
_config.encryption_key.clear();
}
}
- (BOOL)readOnly {
return _config.read_only();
}
- (void)setReadOnly:(BOOL)readOnly {
if (readOnly) {
if (self.deleteRealmIfMigrationNeeded) {
@throw RLMException(@"Cannot set `readOnly` when `deleteRealmIfMigrationNeeded` is set.");
}
_config.schema_mode = realm::SchemaMode::ReadOnly;
}
else if (self.readOnly) {
_config.schema_mode = realm::SchemaMode::Automatic;
}
}
- (uint64_t)schemaVersion {
return _config.schema_version;
}
- (void)setSchemaVersion:(uint64_t)schemaVersion {
if (schemaVersion == RLMNotVersioned) {
@throw RLMException(@"Cannot set schema version to %llu (RLMNotVersioned)", RLMNotVersioned);
}
_config.schema_version = schemaVersion;
}
- (BOOL)deleteRealmIfMigrationNeeded {
return _config.schema_mode == realm::SchemaMode::ResetFile;
}
- (void)setDeleteRealmIfMigrationNeeded:(BOOL)deleteRealmIfMigrationNeeded {
if (deleteRealmIfMigrationNeeded) {
if (self.readOnly) {
@throw RLMException(@"Cannot set `deleteRealmIfMigrationNeeded` when `readOnly` is set.");
}
_config.schema_mode = realm::SchemaMode::ResetFile;
}
else if (self.deleteRealmIfMigrationNeeded) {
_config.schema_mode = realm::SchemaMode::Automatic;
}
}
- (NSArray *)objectClasses {
return [_customSchema.objectSchema valueForKeyPath:@"objectClass"];
}
- (void)setObjectClasses:(NSArray *)objectClasses {
self.customSchema = [RLMSchema schemaWithObjectClasses:objectClasses];
}
- (void)setDynamic:(bool)dynamic {
_dynamic = dynamic;
_config.cache = !dynamic;
}
- (bool)cache {
return _config.cache;
}
- (void)setCache:(bool)cache {
_config.cache = cache;
}
- (bool)disableFormatUpgrade {
return _config.disable_format_upgrade;
}
- (void)setDisableFormatUpgrade:(bool)disableFormatUpgrade {
_config.disable_format_upgrade = disableFormatUpgrade;
}
- (realm::SchemaMode)schemaMode {
return _config.schema_mode;
}
- (void)setSchemaMode:(realm::SchemaMode)mode {
_config.schema_mode = mode;
}
@end

View File

@ -1,142 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMRealmUtil.hpp"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObservation.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMUtil.hpp"
#import <Realm/RLMConstants.h>
#import <Realm/RLMSchema.h>
#import "binding_context.hpp"
#import <map>
#import <mutex>
#import <sys/event.h>
#import <sys/stat.h>
#import <sys/time.h>
#import <unistd.h>
// Global realm state
static std::mutex s_realmCacheMutex;
static std::map<std::string, NSMapTable *> s_realmsPerPath;
void RLMCacheRealm(std::string const& path, RLMRealm *realm) {
std::lock_guard<std::mutex> lock(s_realmCacheMutex);
NSMapTable *realms = s_realmsPerPath[path];
if (!realms) {
s_realmsPerPath[path] = realms = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsObjectPersonality
valueOptions:NSPointerFunctionsWeakMemory];
}
[realms setObject:realm forKey:@(pthread_mach_thread_np(pthread_self()))];
}
RLMRealm *RLMGetAnyCachedRealmForPath(std::string const& path) {
std::lock_guard<std::mutex> lock(s_realmCacheMutex);
return [s_realmsPerPath[path] objectEnumerator].nextObject;
}
RLMRealm *RLMGetThreadLocalCachedRealmForPath(std::string const& path) {
mach_port_t threadID = pthread_mach_thread_np(pthread_self());
std::lock_guard<std::mutex> lock(s_realmCacheMutex);
return [s_realmsPerPath[path] objectForKey:@(threadID)];
}
void RLMClearRealmCache() {
std::lock_guard<std::mutex> lock(s_realmCacheMutex);
s_realmsPerPath.clear();
}
namespace {
class RLMNotificationHelper : public realm::BindingContext {
public:
RLMNotificationHelper(RLMRealm *realm) : _realm(realm) { }
bool can_deliver_notifications() const noexcept override {
// The main thread may not be in a run loop yet if we're called from
// something like `applicationDidFinishLaunching:`, but it presumably will
// be in the future
if ([NSThread isMainThread]) {
return true;
}
// Current mode indicates why the current callout from the runloop was made,
// and is null if a runloop callout isn't currently being processed
if (auto mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent())) {
CFRelease(mode);
return true;
}
return false;
}
void changes_available() override {
@autoreleasepool {
auto realm = _realm;
if (realm && !realm.autorefresh) {
[realm sendNotifications:RLMRealmRefreshRequiredNotification];
}
}
}
std::vector<ObserverState> get_observed_rows() override {
@autoreleasepool {
if (auto realm = _realm) {
[realm detachAllEnumerators];
return RLMGetObservedRows(realm->_info);
}
return {};
}
}
void will_change(std::vector<ObserverState> const& observed, std::vector<void*> const& invalidated) override {
@autoreleasepool {
RLMWillChange(observed, invalidated);
}
}
void did_change(std::vector<ObserverState> const& observed, std::vector<void*> const& invalidated) override {
try {
@autoreleasepool {
RLMDidChange(observed, invalidated);
[_realm sendNotifications:RLMRealmDidChangeNotification];
}
}
catch (...) {
// This can only be called during a write transaction if it was
// called due to the transaction beginning, so cancel it to ensure
// exceptions thrown here behave the same as exceptions thrown when
// actually beginning the write
if (_realm.inWriteTransaction) {
[_realm cancelWriteTransaction];
}
throw;
}
}
private:
// This is owned by the realm, so it needs to not retain the realm
__weak RLMRealm *const _realm;
};
} // anonymous namespace
std::unique_ptr<realm::BindingContext> RLMCreateBindingContext(RLMRealm *realm) {
return std::unique_ptr<realm::BindingContext>(new RLMNotificationHelper(realm));
}

View File

@ -1,444 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMResults_Private.h"
#import "RLMArray_Private.hpp"
#import "RLMCollection_Private.hpp"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObject_Private.hpp"
#import "RLMObservation.hpp"
#import "RLMProperty_Private.h"
#import "RLMQueryUtil.hpp"
#import "RLMRealm_Private.hpp"
#import "RLMSchema_Private.h"
#import "RLMUtil.hpp"
#import "results.hpp"
#import <objc/runtime.h>
#import <objc/message.h>
#import <realm/table_view.hpp>
using namespace realm;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"
@implementation RLMNotificationToken
@end
#pragma clang diagnostic pop
//
// RLMResults implementation
//
@implementation RLMResults {
realm::Results _results;
RLMRealm *_realm;
RLMClassInfo *_info;
}
- (instancetype)initPrivate {
self = [super init];
return self;
}
static void assertKeyPathIsNotNested(NSString *keyPath) {
if ([keyPath rangeOfString:@"."].location != NSNotFound) {
@throw RLMException(@"Nested key paths are not supported yet for KVC collection operators.");
}
}
[[gnu::noinline]]
[[noreturn]]
static void throwError(NSString *aggregateMethod) {
try {
throw;
}
catch (realm::InvalidTransactionException const&) {
@throw RLMException(@"Cannot modify Results outside of a write transaction");
}
catch (realm::IncorrectThreadException const&) {
@throw RLMException(@"Realm accessed from incorrect thread");
}
catch (realm::Results::InvalidatedException const&) {
@throw RLMException(@"RLMResults has been invalidated");
}
catch (realm::Results::DetatchedAccessorException const&) {
@throw RLMException(@"Object has been invalidated");
}
catch (realm::Results::IncorrectTableException const& e) {
@throw RLMException(@"Object type '%s' does not match RLMResults type '%s'.",
e.actual.data(), e.expected.data());
}
catch (realm::Results::OutOfBoundsIndexException const& e) {
@throw RLMException(@"Index %zu is out of bounds (must be less than %zu)",
e.requested, e.valid_count);
}
catch (realm::Results::UnsupportedColumnTypeException const& e) {
@throw RLMException(@"%@ is not supported for %@ property '%s'",
aggregateMethod,
RLMTypeToString((RLMPropertyType)e.column_type),
e.column_name.data());
}
}
template<typename Function>
static auto translateErrors(Function&& f, NSString *aggregateMethod=nil) {
try {
return f();
}
catch (...) {
throwError(aggregateMethod);
}
}
+ (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;
}
+ (instancetype)emptyDetachedResults {
return [[self alloc] initPrivate];
}
static inline void RLMResultsValidateInWriteTransaction(__unsafe_unretained RLMResults *const ar) {
ar->_realm->_realm->verify_thread();
ar->_realm->_realm->verify_in_write();
}
- (BOOL)isInvalidated {
return translateErrors([&] { return !_results.is_valid(); });
}
- (NSUInteger)count {
return translateErrors([&] { return _results.size(); });
}
- (NSString *)objectClassName {
return RLMStringDataToNSString(_results.get_object_type());
}
- (RLMObjectSchema *)objectSchema {
return _info->rlmObjectSchema;
}
- (RLMClassInfo *)objectInfo {
return _info;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(__unused __unsafe_unretained id [])buffer
count:(NSUInteger)len {
__autoreleasing RLMFastEnumerator *enumerator;
if (state->state == 0) {
enumerator = [[RLMFastEnumerator alloc] initWithCollection:self objectSchema:*_info];
state->extra[0] = (long)enumerator;
state->extra[1] = self.count;
}
else {
enumerator = (__bridge id)(void *)state->extra[0];
}
return [enumerator countByEnumeratingWithState:state count:len];
}
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ... {
va_list args;
va_start(args, predicateFormat);
NSUInteger index = [self indexOfObjectWhere:predicateFormat args:args];
va_end(args);
return index;
}
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args {
return [self indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:predicateFormat
arguments:args]];
}
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate {
if (_results.get_mode() == Results::Mode::Empty) {
return NSNotFound;
}
Query query = translateErrors([&] { return _results.get_query(); });
query.and_query(RLMPredicateToQuery(predicate, _info->rlmObjectSchema, _realm.schema, _realm.group));
query.sync_view_if_needed();
#if REALM_VER_MAJOR >= 2
size_t indexInTable;
if (const auto& sort = _results.get_sort()) {
// A sort order is specified so we need to return the first match given that ordering.
TableView table_view = query.find_all();
table_view.sort(sort);
if (!table_view.size()) {
return NSNotFound;
}
indexInTable = table_view.get_source_ndx(0);
} else {
indexInTable = query.find();
}
if (indexInTable == realm::not_found) {
return NSNotFound;
}
return RLMConvertNotFound(_results.index_of(indexInTable));
#else
TableView table_view;
if (const auto& sort = _results.get_sort()) {
// A sort order is specified so we need to return the first match given that ordering.
table_view = query.find_all();
table_view.sort(sort);
} else {
table_view = query.find_all(0, -1, 1);
}
if (!table_view.size()) {
return NSNotFound;
}
return _results.index_of(table_view.get_source_ndx(0));
#endif
}
- (id)objectAtIndex:(NSUInteger)index {
return translateErrors([&] {
return RLMCreateObjectAccessor(_realm, *_info, _results.get(index));
});
}
- (id)firstObject {
auto row = translateErrors([&] { return _results.first(); });
return row ? RLMCreateObjectAccessor(_realm, *_info, *row) : nil;
}
- (id)lastObject {
auto row = translateErrors([&] { return _results.last(); });
return row ? RLMCreateObjectAccessor(_realm, *_info, *row) : nil;
}
- (NSUInteger)indexOfObject:(RLMObject *)object {
if (!object || (!object->_realm && !object.invalidated)) {
return NSNotFound;
}
return translateErrors([&] {
return RLMConvertNotFound(_results.index_of(object->_row));
});
}
- (id)valueForKeyPath:(NSString *)keyPath {
if ([keyPath characterAtIndex:0] == '@') {
if ([keyPath isEqualToString:@"@count"]) {
return @(self.count);
}
NSRange operatorRange = [keyPath rangeOfString:@"." options:NSLiteralSearch];
NSUInteger keyPathLength = keyPath.length;
NSUInteger separatorIndex = operatorRange.location != NSNotFound ? operatorRange.location : keyPathLength;
NSString *operatorName = [keyPath substringWithRange:NSMakeRange(1, separatorIndex - 1)];
SEL opSelector = NSSelectorFromString([NSString stringWithFormat:@"_%@ForKeyPath:", operatorName]);
BOOL isValidOperator = [self respondsToSelector:opSelector];
if (!isValidOperator) {
@throw RLMException(@"Unsupported KVC collection operator found in key path '%@'", keyPath);
}
else if (separatorIndex >= keyPathLength - 1) {
@throw RLMException(@"Missing key path for KVC collection operator %@ in key path '%@'", operatorName, keyPath);
}
NSString *operatorKeyPath = [keyPath substringFromIndex:separatorIndex + 1];
if (isValidOperator) {
return ((id(*)(id, SEL, id))objc_msgSend)(self, opSelector, operatorKeyPath);
}
}
return [super valueForKeyPath:keyPath];
}
- (id)valueForKey:(NSString *)key {
return translateErrors([&] {
return RLMCollectionValueForKey(self, key);
});
}
- (void)setValue:(id)value forKey:(NSString *)key {
translateErrors([&] { RLMResultsValidateInWriteTransaction(self); });
RLMCollectionSetValueForKey(self, key, value);
}
- (NSNumber *)_aggregateForKeyPath:(NSString *)keyPath method:(util::Optional<Mixed> (Results::*)(size_t))method methodName:(NSString *)methodName {
assertKeyPathIsNotNested(keyPath);
return [self aggregate:keyPath method:method methodName:methodName];
}
- (NSNumber *)_minForKeyPath:(NSString *)keyPath {
return [self _aggregateForKeyPath:keyPath method:&Results::min methodName:@"@min"];
}
- (NSNumber *)_maxForKeyPath:(NSString *)keyPath {
return [self _aggregateForKeyPath:keyPath method:&Results::max methodName:@"@max"];
}
- (NSNumber *)_sumForKeyPath:(NSString *)keyPath {
return [self _aggregateForKeyPath:keyPath method:&Results::sum methodName:@"@sum"];
}
- (NSNumber *)_avgForKeyPath:(NSString *)keyPath {
return [self _aggregateForKeyPath:keyPath method:&Results::average methodName:@"@avg"];
}
- (NSArray *)_unionOfObjectsForKeyPath:(NSString *)keyPath {
assertKeyPathIsNotNested(keyPath);
return translateErrors([&] {
return RLMCollectionValueForKey(self, keyPath);
});
}
- (NSArray *)_distinctUnionOfObjectsForKeyPath:(NSString *)keyPath {
return [NSSet setWithArray:[self _unionOfObjectsForKeyPath:keyPath]].allObjects;
}
- (NSArray *)_unionOfArraysForKeyPath:(NSString *)keyPath {
assertKeyPathIsNotNested(keyPath);
if ([keyPath isEqualToString:@"self"]) {
@throw RLMException(@"self is not a valid key-path for a KVC array collection operator as 'unionOfArrays'.");
}
return translateErrors([&] {
NSArray *nestedResults = RLMCollectionValueForKey(self, keyPath);
NSMutableArray *flatArray = [NSMutableArray arrayWithCapacity:nestedResults.count];
for (id<RLMFastEnumerable> array in nestedResults) {
NSArray *nsArray = RLMCollectionValueForKey(array, @"self");
[flatArray addObjectsFromArray:nsArray];
}
return flatArray;
});
}
- (NSArray *)_distinctUnionOfArraysForKeyPath:(__unused NSString *)keyPath {
return [NSSet setWithArray:[self _unionOfArraysForKeyPath:keyPath]].allObjects;
}
- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ... {
va_list args;
va_start(args, predicateFormat);
RLMResults *results = [self objectsWhere:predicateFormat args:args];
va_end(args);
return results;
}
- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args {
return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]];
}
- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate {
return translateErrors([&] {
if (_results.get_mode() == Results::Mode::Empty) {
return self;
}
auto query = RLMPredicateToQuery(predicate, _info->rlmObjectSchema, _realm.schema, _realm.group);
return [RLMResults resultsWithObjectInfo:*_info results:_results.filter(std::move(query))];
});
}
- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending {
return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]];
}
- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties {
return translateErrors([&] {
if (_results.get_mode() == Results::Mode::Empty) {
return self;
}
return [RLMResults resultsWithObjectInfo:*_info results:_results.sort(RLMSortDescriptorFromDescriptors(*_info->table(), properties))];
});
}
- (id)objectAtIndexedSubscript:(NSUInteger)index {
return [self objectAtIndex:index];
}
- (id)aggregate:(NSString *)property method:(util::Optional<Mixed> (Results::*)(size_t))method methodName:(NSString *)methodName {
size_t column = _info->tableColumn(property);
auto value = translateErrors([&] { return (_results.*method)(column); }, methodName);
if (!value) {
return nil;
}
return RLMMixedToObjc(*value);
}
- (id)minOfProperty:(NSString *)property {
return [self aggregate:property method:&Results::min methodName:@"minOfProperty"];
}
- (id)maxOfProperty:(NSString *)property {
return [self aggregate:property method:&Results::max methodName:@"maxOfProperty"];
}
- (id)sumOfProperty:(NSString *)property {
return [self aggregate:property method:&Results::sum methodName:@"sumOfProperty"];
}
- (id)averageOfProperty:(NSString *)property {
return [self aggregate:property method:&Results::average methodName:@"averageOfProperty"];
}
- (void)deleteObjectsFromRealm {
return translateErrors([&] {
if (_results.get_mode() == Results::Mode::Table) {
RLMResultsValidateInWriteTransaction(self);
RLMClearTable(*self.objectInfo);
}
else {
RLMTrackDeletions(_realm, ^{ _results.clear(); });
}
});
}
- (NSString *)description {
return RLMDescriptionWithMaxDepth(@"RLMResults", self, RLMDescriptionMaxDepth);
}
- (NSUInteger)indexInSource:(NSUInteger)index {
return translateErrors([&] { return _results.get(index).get_index(); });
}
- (realm::TableView)tableView {
return translateErrors([&] { return _results.get_tableview(); });
}
// The compiler complains about the method's argument type not matching due to
// it not having the generic type attached, but it doesn't seem to be possible
// to actually include the generic type
// http://www.openradar.me/radar?id=6135653276319744
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-parameter-types"
- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMResults *, RLMCollectionChange *, NSError *))block {
[_realm verifyNotificationsAreSupported];
return RLMAddNotificationBlock(self, _results, block, true);
}
#pragma clang diagnostic pop
- (BOOL)isAttached
{
return !!_realm;
}
@end
@implementation RLMLinkingObjects
@end

View File

@ -1,338 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMSchema_Private.h"
#import "RLMAccessor.h"
#import "RLMObject_Private.hpp"
#import "RLMObjectSchema_Private.hpp"
#import "RLMProperty_Private.h"
#import "RLMRealm_Private.hpp"
#import "RLMSwiftSupport.h"
#import "RLMUtil.hpp"
#import "object_store.hpp"
#import "schema.hpp"
#import <realm/group.hpp>
#import <objc/runtime.h>
#include <mutex>
using namespace realm;
const uint64_t RLMNotVersioned = realm::ObjectStore::NotVersioned;
// RLMSchema private properties
@interface RLMSchema ()
@property (nonatomic, readwrite) NSMutableDictionary *objectSchemaByName;
@end
static RLMSchema *s_sharedSchema = [[RLMSchema alloc] init];
static NSMutableDictionary *s_localNameToClass = [[NSMutableDictionary alloc] init];
static NSMutableDictionary *s_privateObjectSubclasses = [[NSMutableDictionary alloc] init];
static enum class SharedSchemaState {
Uninitialized,
Initializing,
Initialized
} s_sharedSchemaState = SharedSchemaState::Uninitialized;
@implementation RLMSchema {
NSArray *_objectSchema;
realm::Schema _objectStoreSchema;
}
// Caller must @synchronize on s_localNameToClass
static RLMObjectSchema *RLMRegisterClass(Class cls) {
if (RLMObjectSchema *schema = s_privateObjectSubclasses[[cls className]]) {
return schema;
}
auto prevState = s_sharedSchemaState;
s_sharedSchemaState = SharedSchemaState::Initializing;
RLMObjectSchema *schema = [RLMObjectSchema schemaForObjectClass:cls];
s_sharedSchemaState = prevState;
// set unmanaged class on shared shema for unmanaged object creation
schema.unmanagedClass = RLMUnmanagedAccessorClassForObjectClass(schema.objectClass, schema);
// override sharedSchema class methods for performance
RLMReplaceSharedSchemaMethod(cls, schema);
s_privateObjectSubclasses[schema.className] = schema;
if ([cls shouldIncludeInDefaultSchema] && prevState != SharedSchemaState::Initialized) {
s_sharedSchema.objectSchemaByName[schema.className] = schema;
}
return schema;
}
// Caller must @synchronize on s_localNameToClass
static void RLMRegisterClassLocalNames(Class *classes, NSUInteger count) {
for (NSUInteger i = 0; i < count; i++) {
Class cls = classes[i];
if (!RLMIsObjectSubclass(cls) || RLMIsGeneratedClass(cls)) {
continue;
}
NSString *className = NSStringFromClass(cls);
if ([RLMSwiftSupport isSwiftClassName:className]) {
className = [RLMSwiftSupport demangleClassName:className];
}
// NSStringFromClass demangles the names for top-level Swift classes
// but not for nested classes. _T indicates it's a Swift symbol, t
// indicates it's a type, and C indicates it's a class.
else if ([className hasPrefix:@"_TtC"]) {
@throw RLMException(@"RLMObject subclasses cannot be nested within other declarations. Please move %@ to global scope.", className);
}
if (Class existingClass = s_localNameToClass[className]) {
if (existingClass != cls) {
@throw RLMException(@"RLMObject subclasses with the same name cannot be included twice in the same target. "
@"Please make sure '%@' is only linked once to your current target.", className);
}
continue;
}
s_localNameToClass[className] = cls;
RLMReplaceClassNameMethod(cls, className);
}
}
- (instancetype)init {
self = [super init];
if (self) {
_objectSchemaByName = [[NSMutableDictionary alloc] init];
}
return self;
}
- (NSArray *)objectSchema {
if (!_objectSchema) {
_objectSchema = [_objectSchemaByName allValues];
}
return _objectSchema;
}
- (void)setObjectSchema:(NSArray *)objectSchema {
_objectSchema = objectSchema;
_objectSchemaByName = [NSMutableDictionary dictionaryWithCapacity:objectSchema.count];
for (RLMObjectSchema *object in objectSchema) {
[_objectSchemaByName setObject:object forKey:object.className];
}
}
- (RLMObjectSchema *)schemaForClassName:(NSString *)className {
if (RLMObjectSchema *schema = _objectSchemaByName[className]) {
return schema; // fast path for already-initialized schemas
} else if (Class cls = [RLMSchema classForString:className]) {
[cls sharedSchema]; // initialize the schema
return _objectSchemaByName[className]; // try again
} else {
return nil;
}
}
- (RLMObjectSchema *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)className {
RLMObjectSchema *schema = [self schemaForClassName:className];
if (!schema) {
@throw RLMException(@"Object type '%@' not managed by the Realm", className);
}
return schema;
}
+ (instancetype)schemaWithObjectClasses:(NSArray *)classes {
NSUInteger count = classes.count;
auto classArray = std::make_unique<__unsafe_unretained Class[]>(count);
[classes getObjects:classArray.get() range:NSMakeRange(0, count)];
RLMSchema *schema = [[self alloc] init];
@synchronized(s_localNameToClass) {
RLMRegisterClassLocalNames(classArray.get(), count);
schema->_objectSchemaByName = [NSMutableDictionary dictionaryWithCapacity:count];
for (Class cls in classes) {
if (!RLMIsObjectSubclass(cls)) {
@throw RLMException(@"Can't add non-Object type '%@' to a schema.", cls);
}
schema->_objectSchemaByName[[cls className]] = RLMRegisterClass(cls);
}
}
NSMutableArray *errors = [NSMutableArray new];
// Verify that all of the targets of links are included in the class list
[schema->_objectSchemaByName enumerateKeysAndObjectsUsingBlock:^(id, RLMObjectSchema *objectSchema, BOOL *) {
for (RLMProperty *prop in objectSchema.properties) {
if (prop.type != RLMPropertyTypeObject && prop.type != RLMPropertyTypeArray) {
continue;
}
if (!schema->_objectSchemaByName[prop.objectClassName]) {
[errors addObject:[NSString stringWithFormat:@"- '%@.%@' links to class '%@', which is missing from the list of classes managed by the Realm", objectSchema.className, prop.name, prop.objectClassName]];
}
}
}];
if (errors.count) {
@throw RLMException(@"Invalid class subset list:\n%@", [errors componentsJoinedByString:@"\n"]);
}
return schema;
}
+ (RLMObjectSchema *)sharedSchemaForClass:(Class)cls {
@synchronized(s_localNameToClass) {
// We create instances of Swift objects during schema init, and they
// obviously need to not also try to initialize the schema
if (s_sharedSchemaState == SharedSchemaState::Initializing) {
return nil;
}
RLMRegisterClassLocalNames(&cls, 1);
return RLMRegisterClass(cls);
}
}
+ (instancetype)partialSharedSchema {
return s_sharedSchema;
}
// schema based on runtime objects
+ (instancetype)sharedSchema {
@synchronized(s_localNameToClass) {
// We replace this method with one which just returns s_sharedSchema
// once initialization is complete, but we still need to check if it's
// already complete because it may have been done by another thread
// while we were waiting for the lock
if (s_sharedSchemaState == SharedSchemaState::Initialized) {
return s_sharedSchema;
}
if (s_sharedSchemaState == SharedSchemaState::Initializing) {
@throw RLMException(@"Illegal recursive call of +[%@ %@]. Note: Properties of Swift `Object` classes must not be prepopulated with queried results from a Realm.", self, NSStringFromSelector(_cmd));
}
s_sharedSchemaState = SharedSchemaState::Initializing;
try {
// Make sure we've discovered all classes
{
unsigned int numClasses;
using malloc_ptr = std::unique_ptr<__unsafe_unretained Class[], decltype(&free)>;
malloc_ptr classes(objc_copyClassList(&numClasses), &free);
RLMRegisterClassLocalNames(classes.get(), numClasses);
}
[s_localNameToClass enumerateKeysAndObjectsUsingBlock:^(NSString *, Class cls, BOOL *) {
RLMRegisterClass(cls);
}];
}
catch (...) {
s_sharedSchemaState = SharedSchemaState::Uninitialized;
throw;
}
// Replace this method with one that doesn't need to acquire a lock
Class metaClass = objc_getMetaClass(class_getName(self));
IMP imp = imp_implementationWithBlock(^{ return s_sharedSchema; });
class_replaceMethod(metaClass, @selector(sharedSchema), imp, "@@:");
s_sharedSchemaState = SharedSchemaState::Initialized;
}
return s_sharedSchema;
}
// schema based on tables in a realm
+ (instancetype)dynamicSchemaFromObjectStoreSchema:(Schema const&)objectStoreSchema {
// cache descriptors for all subclasses of RLMObject
NSMutableArray *schemaArray = [NSMutableArray arrayWithCapacity:objectStoreSchema.size()];
for (auto &objectSchema : objectStoreSchema) {
RLMObjectSchema *schema = [RLMObjectSchema objectSchemaForObjectStoreSchema:objectSchema];
[schemaArray addObject:schema];
}
// set class array and mapping
RLMSchema *schema = [RLMSchema new];
schema.objectSchema = schemaArray;
return schema;
}
+ (Class)classForString:(NSString *)className {
if (Class cls = s_localNameToClass[className]) {
return cls;
}
if (Class cls = NSClassFromString(className)) {
return RLMIsObjectSubclass(cls) ? cls : nil;
}
// className might be the local name of a Swift class we haven't registered
// yet, so scan them all then recheck
{
unsigned int numClasses;
std::unique_ptr<__unsafe_unretained Class[], decltype(&free)> classes(objc_copyClassList(&numClasses), &free);
RLMRegisterClassLocalNames(classes.get(), numClasses);
}
return s_localNameToClass[className];
}
- (id)copyWithZone:(NSZone *)zone {
RLMSchema *schema = [[RLMSchema allocWithZone:zone] init];
schema->_objectSchemaByName = [[NSMutableDictionary allocWithZone:zone]
initWithDictionary:_objectSchemaByName copyItems:YES];
return schema;
}
- (BOOL)isEqualToSchema:(RLMSchema *)schema {
if (_objectSchemaByName.count != schema->_objectSchemaByName.count) {
return NO;
}
__block BOOL matches = YES;
[_objectSchemaByName enumerateKeysAndObjectsUsingBlock:^(NSString *name, RLMObjectSchema *objectSchema, BOOL *stop) {
if (![schema->_objectSchemaByName[name] isEqualToObjectSchema:objectSchema]) {
*stop = YES;
matches = NO;
}
}];
return matches;
}
- (NSString *)description {
NSMutableString *objectSchemaString = [NSMutableString string];
NSArray *sort = @[[NSSortDescriptor sortDescriptorWithKey:@"className" ascending:YES]];
for (RLMObjectSchema *objectSchema in [self.objectSchema sortedArrayUsingDescriptors:sort]) {
[objectSchemaString appendFormat:@"\t%@\n",
[objectSchema.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]];
}
return [NSString stringWithFormat:@"Schema {\n%@}", objectSchemaString];
}
- (Schema)objectStoreCopy {
if (_objectStoreSchema.size() == 0) {
std::vector<realm::ObjectSchema> schema;
schema.reserve(_objectSchemaByName.count);
[_objectSchemaByName enumerateKeysAndObjectsUsingBlock:[&](NSString *, RLMObjectSchema *objectSchema, BOOL *) {
schema.push_back(objectSchema.objectStoreCopy);
}];
_objectStoreSchema = std::move(schema);
}
return _objectStoreSchema;
}
@end

View File

@ -1,31 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMSwiftSupport.h"
@implementation RLMSwiftSupport
+ (BOOL)isSwiftClassName:(NSString *)className {
return [className rangeOfString:@"."].location != NSNotFound;
}
+ (NSString *)demangleClassName:(NSString *)className {
return [className substringFromIndex:[className rangeOfString:@"."].location + 1];
}
@end

View File

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMUpdateChecker.hpp"
#import "RLMRealm.h"
#import "RLMUtil.hpp"
#if TARGET_IPHONE_SIMULATOR && !defined(REALM_COCOA_VERSION)
#import "RLMVersion.h"
#endif
void RLMCheckForUpdates() {
#if TARGET_IPHONE_SIMULATOR
if (getenv("REALM_DISABLE_UPDATE_CHECKER") || RLMIsRunningInPlayground()) {
return;
}
auto handler = ^(NSData *data, NSURLResponse *response, NSError *error) {
if (error || ((NSHTTPURLResponse *)response).statusCode != 200) {
return;
}
NSString *latestVersion = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (![REALM_COCOA_VERSION isEqualToString:latestVersion]) {
NSLog(@"Version %@ of Realm is now available: https://github.com/realm/realm-cocoa/blob/v%@/CHANGELOG.md", latestVersion, latestVersion);
}
};
NSString *url = [NSString stringWithFormat:@"https://static.realm.io/update/cocoa?%@", REALM_COCOA_VERSION];
[[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url] completionHandler:handler] resume];
#endif
}

View File

@ -1,353 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMUtil.hpp"
#import "RLMArray_Private.hpp"
#import "RLMListBase.h"
#import "RLMObjectSchema_Private.hpp"
#import "RLMObjectStore.h"
#import "RLMObject_Private.hpp"
#import "RLMProperty_Private.h"
#import "RLMSchema_Private.h"
#import "RLMSwiftSupport.h"
#import "shared_realm.hpp"
#import <realm/mixed.hpp>
#import <realm/table_view.hpp>
#include <sys/sysctl.h>
#include <sys/types.h>
#if !defined(REALM_COCOA_VERSION)
#import "RLMVersion.h"
#endif
static inline bool nsnumber_is_like_integer(__unsafe_unretained NSNumber *const obj)
{
char data_type = [obj objCType][0];
return data_type == *@encode(bool) ||
data_type == *@encode(char) ||
data_type == *@encode(short) ||
data_type == *@encode(int) ||
data_type == *@encode(long) ||
data_type == *@encode(long long) ||
data_type == *@encode(unsigned short) ||
data_type == *@encode(unsigned int) ||
data_type == *@encode(unsigned long) ||
data_type == *@encode(unsigned long long);
}
static inline bool nsnumber_is_like_bool(__unsafe_unretained NSNumber *const obj)
{
// @encode(BOOL) is 'B' on iOS 64 and 'c'
// objcType is always 'c'. Therefore compare to "c".
if ([obj objCType][0] == 'c') {
return true;
}
if (nsnumber_is_like_integer(obj)) {
int value = [obj intValue];
return value == 0 || value == 1;
}
return false;
}
static inline bool nsnumber_is_like_float(__unsafe_unretained NSNumber *const obj)
{
char data_type = [obj objCType][0];
return data_type == *@encode(float) ||
data_type == *@encode(short) ||
data_type == *@encode(int) ||
data_type == *@encode(long) ||
data_type == *@encode(long long) ||
data_type == *@encode(unsigned short) ||
data_type == *@encode(unsigned int) ||
data_type == *@encode(unsigned long) ||
data_type == *@encode(unsigned long long) ||
// A double is like float if it fits within float bounds
(data_type == *@encode(double) && ABS([obj doubleValue]) <= FLT_MAX);
}
static inline bool nsnumber_is_like_double(__unsafe_unretained NSNumber *const obj)
{
char data_type = [obj objCType][0];
return data_type == *@encode(double) ||
data_type == *@encode(float) ||
data_type == *@encode(short) ||
data_type == *@encode(int) ||
data_type == *@encode(long) ||
data_type == *@encode(long long) ||
data_type == *@encode(unsigned short) ||
data_type == *@encode(unsigned int) ||
data_type == *@encode(unsigned long) ||
data_type == *@encode(unsigned long long);
}
BOOL RLMIsObjectValidForProperty(__unsafe_unretained id const obj,
__unsafe_unretained RLMProperty *const property) {
if (property.optional && !RLMCoerceToNil(obj)) {
return YES;
}
switch (property.type) {
case RLMPropertyTypeString:
return [obj isKindOfClass:[NSString class]];
case RLMPropertyTypeBool:
if ([obj isKindOfClass:[NSNumber class]]) {
return nsnumber_is_like_bool(obj);
}
return NO;
case RLMPropertyTypeDate:
return [obj isKindOfClass:[NSDate class]];
case RLMPropertyTypeInt:
if (NSNumber *number = RLMDynamicCast<NSNumber>(obj)) {
return nsnumber_is_like_integer(number);
}
return NO;
case RLMPropertyTypeFloat:
if (NSNumber *number = RLMDynamicCast<NSNumber>(obj)) {
return nsnumber_is_like_float(number);
}
return NO;
case RLMPropertyTypeDouble:
if (NSNumber *number = RLMDynamicCast<NSNumber>(obj)) {
return nsnumber_is_like_double(number);
}
return NO;
case RLMPropertyTypeData:
return [obj isKindOfClass:[NSData class]];
case RLMPropertyTypeAny:
return NO;
case RLMPropertyTypeObject:
case RLMPropertyTypeLinkingObjects: {
// only NSNull, nil, or objects which derive from RLMObject and match the given
// object class are valid
RLMObjectBase *objBase = RLMDynamicCast<RLMObjectBase>(obj);
return objBase && [objBase->_objectSchema.className isEqualToString:property.objectClassName];
}
case RLMPropertyTypeArray: {
if (RLMArray *array = RLMDynamicCast<RLMArray>(obj)) {
return [array.objectClassName isEqualToString:property.objectClassName];
}
if (RLMListBase *list = RLMDynamicCast<RLMListBase>(obj)) {
return [list._rlmArray.objectClassName isEqualToString:property.objectClassName];
}
if ([obj conformsToProtocol:@protocol(NSFastEnumeration)]) {
// check each element for compliance
for (id el in (id<NSFastEnumeration>)obj) {
RLMObjectBase *obj = RLMDynamicCast<RLMObjectBase>(el);
if (!obj || ![obj->_objectSchema.className isEqualToString:property.objectClassName]) {
return NO;
}
}
return YES;
}
if (!obj || obj == NSNull.null) {
return YES;
}
return NO;
}
}
@throw RLMException(@"Invalid RLMPropertyType specified");
}
NSDictionary *RLMDefaultValuesForObjectSchema(__unsafe_unretained RLMObjectSchema *const objectSchema) {
if (!objectSchema.isSwiftClass) {
return [objectSchema.objectClass defaultPropertyValues];
}
NSMutableDictionary *defaults = nil;
if ([objectSchema.objectClass isSubclassOfClass:RLMObject.class]) {
defaults = [NSMutableDictionary dictionaryWithDictionary:[objectSchema.objectClass defaultPropertyValues]];
}
else {
defaults = [NSMutableDictionary dictionary];
}
RLMObject *defaultObject = [[objectSchema.objectClass alloc] init];
for (RLMProperty *prop in objectSchema.properties) {
if (!defaults[prop.name] && defaultObject[prop.name]) {
defaults[prop.name] = defaultObject[prop.name];
}
}
return defaults;
}
static NSException *RLMException(NSString *reason, NSDictionary *additionalUserInfo) {
NSMutableDictionary *userInfo = @{RLMRealmVersionKey: REALM_COCOA_VERSION,
RLMRealmCoreVersionKey: @REALM_VERSION}.mutableCopy;
if (additionalUserInfo != nil) {
[userInfo addEntriesFromDictionary:additionalUserInfo];
}
NSException *e = [NSException exceptionWithName:RLMExceptionName
reason:reason
userInfo:userInfo];
return e;
}
NSException *RLMException(NSString *fmt, ...) {
va_list args;
va_start(args, fmt);
NSException *e = RLMException([[NSString alloc] initWithFormat:fmt arguments:args], @{});
va_end(args);
return e;
}
NSException *RLMException(std::exception const& exception) {
return RLMException(@"%@", @(exception.what()));
}
NSError *RLMMakeError(RLMError code, std::exception const& exception) {
return [NSError errorWithDomain:RLMErrorDomain
code:code
userInfo:@{NSLocalizedDescriptionKey: @(exception.what()),
@"Error Code": @(code)}];
}
NSError *RLMMakeError(RLMError code, const realm::util::File::AccessError& exception) {
return [NSError errorWithDomain:RLMErrorDomain
code:code
userInfo:@{NSLocalizedDescriptionKey: @(exception.what()),
NSFilePathErrorKey: @(exception.get_path().c_str()),
@"Error Code": @(code)}];
}
NSError *RLMMakeError(RLMError code, const realm::RealmFileException& exception) {
NSString *underlying = @(exception.underlying().c_str());
return [NSError errorWithDomain:RLMErrorDomain
code:code
userInfo:@{NSLocalizedDescriptionKey: @(exception.what()),
NSFilePathErrorKey: @(exception.path().c_str()),
@"Error Code": @(code),
@"Underlying": underlying.length == 0 ? @"n/a" : underlying}];
}
NSError *RLMMakeError(std::system_error const& exception) {
BOOL isGenericCategoryError = (exception.code().category() == std::generic_category());
NSString *category = @(exception.code().category().name());
NSString *errorDomain = isGenericCategoryError ? NSPOSIXErrorDomain : RLMUnknownSystemErrorDomain;
return [NSError errorWithDomain:errorDomain
code:exception.code().value()
userInfo:@{NSLocalizedDescriptionKey: @(exception.what()),
@"Error Code": @(exception.code().value()),
@"Category": category}];
}
NSError *RLMMakeError(NSException *exception) {
return [NSError errorWithDomain:RLMErrorDomain
code:0
userInfo:@{NSLocalizedDescriptionKey: exception.reason}];
}
void RLMSetErrorOrThrow(NSError *error, NSError **outError) {
if (outError) {
*outError = error;
}
else {
NSString *msg = error.localizedDescription;
if (error.userInfo[NSFilePathErrorKey]) {
msg = [NSString stringWithFormat:@"%@: %@", error.userInfo[NSFilePathErrorKey], error.localizedDescription];
}
@throw RLMException(msg, @{NSUnderlyingErrorKey: error});
}
}
// Determines if class1 descends from class2
static inline BOOL RLMIsSubclass(Class class1, Class class2) {
class1 = class_getSuperclass(class1);
return RLMIsKindOfClass(class1, class2);
}
static bool treatFakeObjectAsRLMObject = false;
void RLMSetTreatFakeObjectAsRLMObject(BOOL flag) {
treatFakeObjectAsRLMObject = flag;
}
BOOL RLMIsObjectOrSubclass(Class klass) {
if (RLMIsKindOfClass(klass, RLMObjectBase.class)) {
return YES;
}
if (treatFakeObjectAsRLMObject) {
static Class FakeObjectClass = NSClassFromString(@"FakeObject");
return RLMIsKindOfClass(klass, FakeObjectClass);
}
return NO;
}
BOOL RLMIsObjectSubclass(Class klass) {
if (RLMIsSubclass(class_getSuperclass(klass), RLMObjectBase.class)) {
return YES;
}
if (treatFakeObjectAsRLMObject) {
static Class FakeObjectClass = NSClassFromString(@"FakeObject");
return RLMIsSubclass(klass, FakeObjectClass);
}
return NO;
}
BOOL RLMIsDebuggerAttached()
{
int name[] = {
CTL_KERN,
KERN_PROC,
KERN_PROC_PID,
getpid()
};
struct kinfo_proc info;
size_t info_size = sizeof(info);
if (sysctl(name, sizeof(name)/sizeof(name[0]), &info, &info_size, NULL, 0) == -1) {
NSLog(@"sysctl() failed: %s", strerror(errno));
return false;
}
return (info.kp_proc.p_flag & P_TRACED) != 0;
}
BOOL RLMIsRunningInPlayground() {
return [[NSBundle mainBundle].bundleIdentifier hasPrefix:@"com.apple.dt.playground."];
}
id RLMMixedToObjc(realm::Mixed const& mixed) {
switch (mixed.get_type()) {
case realm::type_String:
return RLMStringDataToNSString(mixed.get_string());
case realm::type_Int:
return @(mixed.get_int());
case realm::type_Float:
return @(mixed.get_float());
case realm::type_Double:
return @(mixed.get_double());
case realm::type_Bool:
return @(mixed.get_bool());
case realm::type_Timestamp:
return RLMTimestampToNSDate(mixed.get_timestamp());
case realm::type_Binary:
return RLMBinaryDataToNSData(mixed.get_binary());
case realm::type_Link:
case realm::type_LinkList:
default:
@throw RLMException(@"Invalid data type for RLMPropertyTypeAny property.");
}
}

View File

@ -1,27 +0,0 @@
framework module Realm {
umbrella header "Realm.h"
export *
module * { export * }
explicit module Private {
header "RLMAccessor.h"
header "RLMArray_Private.h"
header "RLMListBase.h"
header "RLMObjectBase_Dynamic.h"
header "RLMObjectSchema_Private.h"
header "RLMObjectStore.h"
header "RLMObject_Private.h"
header "RLMOptionalBase.h"
header "RLMProperty_Private.h"
header "RLMRealmConfiguration_Private.h"
header "RLMRealm_Private.h"
header "RLMResults_Private.h"
header "RLMSchema_Private.h"
}
explicit module Dynamic {
header "RLMRealm_Dynamic.h"
header "RLMObjectBase_Dynamic.h"
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,63 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
@class RLMObjectSchema, RLMProperty, RLMObjectBase, RLMProperty;
#ifdef __cplusplus
typedef NSUInteger RLMCreationOptions;
#else
typedef NS_OPTIONS(NSUInteger, RLMCreationOptions);
#endif
NS_ASSUME_NONNULL_BEGIN
//
// Accessors Class Creation/Caching
//
// get accessor classes for an object class - generates classes if not cached
Class RLMAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema, NSString *prefix);
Class RLMUnmanagedAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema);
// Check if a given class is a generated accessor class
bool RLMIsGeneratedClass(Class cls);
//
// Dynamic getters/setters
//
FOUNDATION_EXTERN void RLMDynamicValidatedSet(RLMObjectBase *obj, NSString *propName, id __nullable val);
FOUNDATION_EXTERN id __nullable RLMDynamicGet(RLMObjectBase *obj, RLMProperty *prop);
FOUNDATION_EXTERN id __nullable RLMDynamicGetByName(RLMObjectBase *obj, NSString *propName, bool asList);
// by property/column
void RLMDynamicSet(RLMObjectBase *obj, RLMProperty *prop, id val, RLMCreationOptions options);
//
// Class modification
//
// Replace className method for the given class
void RLMReplaceClassNameMethod(Class accessorClass, NSString *className);
// Replace sharedSchema method for the given class
void RLMReplaceSharedSchemaMethod(Class accessorClass, RLMObjectSchema * __nullable schema);
NS_ASSUME_NONNULL_END

View File

@ -1,55 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
// Asynchronously submits build information to Realm if running in an iOS
// simulator or on OS X if a debugger is attached. Does nothing if running on an
// iOS / watchOS device or if a debugger is *not* attached.
//
// To be clear: this does *not* run when your app is in production or on
// your end-users devices; it will only run in the simulator or when a debugger
// is attached.
//
// Why are we doing this? In short, because it helps us build a better product
// for you. None of the data personally identifies you, your employer or your
// app, but it *will* help us understand what language you use, what iOS
// versions you target, etc. Having this info will help prioritizing our time,
// adding new features and deprecating old features. Collecting an anonymized
// bundle & anonymized MAC is the only way for us to count actual usage of the
// other metrics accurately. If we dont have a way to deduplicate the info
// reported, it will be useless, as a single developer building their Swift app
// 10 times would report 10 times more than a single Objective-C developer that
// only builds once, making the data all but useless.
// No one likes sharing data unless its necessary, we get it, and weve
// debated adding this for a long long time. Since Realm is a free product
// without an email signup, we feel this is a necessary step so we can collect
// relevant data to build a better product for you. If you truly, absolutely
// feel compelled to not send this data back to Realm, then you can set an env
// variable named REALM_DISABLE_ANALYTICS. Since Realm is free we believe
// letting these analytics run is a small price to pay for the product & support
// we give you.
//
// Currently the following information is reported:
// - What version of Realm is being used, and from which language (obj-c or Swift).
// - What version of OS X it's running on (in case Xcode aggressively drops
// support for older versions again, we need to know what we need to support).
// - The minimum iOS/OS X version that the application is targeting (again, to
// help us decide what versions we need to support).
// - An anonymous MAC address and bundle ID to aggregate the other information on.
// - What version of Swift is being used (if applicable).
void RLMSendAnalytics();

View File

@ -1,369 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMCollection.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMObject, RLMRealm, RLMResults<RLMObjectType: RLMObject *>, RLMNotificationToken;
/**
`RLMArray` is the container type in Realm used to define to-many relationships.
Unlike an `NSArray`, `RLMArray`s hold a single type, specified by the `objectClassName` property.
This is referred to in these docs as the type of the array.
When declaring an `RLMArray` property, the type must be marked as conforming to a
protocol by the same name as the objects it should contain (see the
`RLM_ARRAY_TYPE` macro). In addition, the property can be declared using Objective-C
generics for better compile-time type safety.
RLM_ARRAY_TYPE(ObjectType)
...
@property RLMArray<ObjectType *><ObjectType> *arrayOfObjectTypes;
`RLMArray`s can be queried with the same predicates as `RLMObject` and `RLMResult`s.
`RLMArray`s cannot be created directly. `RLMArray` properties on `RLMObject`s are
lazily created when accessed, or can be obtained by querying a Realm.
### Key-Value Observing
`RLMArray` supports array key-value observing on `RLMArray` properties on `RLMObject`
subclasses, and the `invalidated` property on `RLMArray` instances themselves is
key-value observing compliant when the `RLMArray` is attached to a managed
`RLMObject` (`RLMArray`s on unmanaged `RLMObject`s will never become invalidated).
Because `RLMArray`s are attached to the object which they are a property of, they
do not require using the mutable collection proxy objects from
`-mutableArrayValueForKey:` or KVC-compatible mutation methods on the containing
object. Instead, you can call the mutation methods on the `RLMArray` directly.
*/
@interface RLMArray<RLMObjectType: RLMObject *> : NSObject<RLMCollection, NSFastEnumeration>
#pragma mark - Properties
/**
The number of objects in the array.
*/
@property (nonatomic, readonly, assign) NSUInteger count;
/**
The class name (i.e. type) of the `RLMObject`s contained in the array.
*/
@property (nonatomic, readonly, copy) NSString *objectClassName;
/**
The Realm which manages the array. Returns `nil` for unmanaged arrays.
*/
@property (nonatomic, readonly, nullable) RLMRealm *realm;
/**
Indicates if the array can no longer be accessed.
*/
@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
#pragma mark - Accessing Objects from an Array
/**
Returns the object at the index specified.
@param index The index to look up.
@return An `RLMObject` of the type contained in the array.
*/
- (RLMObjectType)objectAtIndex:(NSUInteger)index;
/**
Returns the first object in the array.
Returns `nil` if called on an empty array.
@return An `RLMObject` of the type contained in the array.
*/
- (nullable RLMObjectType)firstObject;
/**
Returns the last object in the array.
Returns `nil` if called on an empty array.
@return An `RLMObject` of the type contained in the array.
*/
- (nullable RLMObjectType)lastObject;
#pragma mark - Adding, Removing, and Replacing Objects in an Array
/**
Adds an object to the end of the array.
@warning This method may only be called during a write transaction.
@param object An `RLMObject` of the type contained in the array.
*/
- (void)addObject:(RLMObjectType)object;
/**
Adds an array of objects to the end of the array.
@warning This method may only be called during a write transaction.
@param objects An enumerable object such as `NSArray` or `RLMResults` which contains objects of the
same class as the array.
*/
- (void)addObjects:(id<NSFastEnumeration>)objects;
/**
Inserts an object at the given index.
Throws an exception if the index exceeds the bounds of the array.
@warning This method may only be called during a write transaction.
@param anObject An `RLMObject` of the type contained in the array.
@param index The index at which to insert the object.
*/
- (void)insertObject:(RLMObjectType)anObject atIndex:(NSUInteger)index;
/**
Removes an object at the given index.
Throws an exception if the index exceeds the bounds of the array.
@warning This method may only be called during a write transaction.
@param index The array index identifying the object to be removed.
*/
- (void)removeObjectAtIndex:(NSUInteger)index;
/**
Removes the last object in the array.
@warning This method may only be called during a write transaction.
*/
- (void)removeLastObject;
/**
Removes all objects from the array.
@warning This method may only be called during a write transaction.
*/
- (void)removeAllObjects;
/**
Replaces an object at the given index with a new object.
Throws an exception if the index exceeds the bounds of the array.
@warning This method may only be called during a write transaction.
@param index The index of the object to be replaced.
@param anObject An object (of the same type as returned from the `objectClassName` selector).
*/
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(RLMObjectType)anObject;
/**
Moves the object at the given source index to the given destination index.
Throws an exception if the index exceeds the bounds of the array.
@warning This method may only be called during a write transaction.
@param sourceIndex The index of the object to be moved.
@param destinationIndex The index to which the object at `sourceIndex` should be moved.
*/
- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex;
/**
Exchanges the objects in the array at given indices.
Throws an exception if either index exceeds the bounds of the array.
@warning This method may only be called during a write transaction.
@param index1 The index of the object which should replace the object at index `index2`.
@param index2 The index of the object which should replace the object at index `index1`.
*/
- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2;
#pragma mark - Querying an Array
/**
Returns the index of an object in the array.
Returns `NSNotFound` if the object is not found in the array.
@param object An object (of the same type as returned from the `objectClassName` selector).
*/
- (NSUInteger)indexOfObject:(RLMObjectType)object;
/**
Returns the index of the first object in the array matching the predicate.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return The index of the object, or `NSNotFound` if the object is not found in the array.
*/
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns the index of the first object in the array matching the predicate.
@param predicate The predicate with which to filter the objects.
@return The index of the object, or `NSNotFound` if the object is not found in the array.
*/
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate;
/**
Returns all the objects matching the given predicate in the array.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return An `RLMResults` of objects that match the given predicate.
*/
- (RLMResults<RLMObjectType> *)objectsWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (RLMResults<RLMObjectType> *)objectsWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns all the objects matching the given predicate in the array.
@param predicate The predicate with which to filter the objects.
@return An `RLMResults` of objects that match the given predicate
*/
- (RLMResults<RLMObjectType> *)objectsWithPredicate:(NSPredicate *)predicate;
/**
Returns a sorted `RLMResults` from the array.
@param property The property name to sort by.
@param ascending The direction to sort in.
@return An `RLMResults` sorted by the specified property.
*/
- (RLMResults<RLMObjectType> *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending;
/**
Returns a sorted `RLMResults` from the array.
@param properties An array of `RLMSortDescriptor`s to sort by.
@return An `RLMResults` sorted by the specified properties.
*/
- (RLMResults<RLMObjectType> *)sortedResultsUsingDescriptors:(NSArray *)properties;
/// :nodoc:
- (RLMObjectType)objectAtIndexedSubscript:(NSUInteger)index;
/// :nodoc:
- (void)setObject:(RLMObjectType)newValue atIndexedSubscript:(NSUInteger)index;
#pragma mark - Notifications
/**
Registers a block to be called each time the array changes.
The block will be asynchronously called with the initial array, and then
called again after each write transaction which changes any of the objects in
the array, which objects are in the results, or the order of the objects in the
array.
The `changes` parameter will be `nil` the first time the block is called.
For each call after that, it will contain information about
which rows in the array were added, removed or modified. If a write transaction
did not modify any objects in the array, the block is not called at all.
See the `RLMCollectionChange` documentation for information on how the changes
are reported and an example of updating a `UITableView`.
If an error occurs the block will be called with `nil` for the results
parameter and a non-`nil` error. Currently the only errors that can occur are
when opening the Realm on the background worker thread.
Notifications are delivered via the standard run loop, and so can't be
delivered while the run loop is blocked by other activity. When
notifications can't be delivered instantly, multiple notifications may be
coalesced into a single notification. This can include the notification
with the initial results. For example, the following code performs a write
transaction immediately after adding the notification block, so there is no
opportunity for the initial notification to be delivered first. As a
result, the initial notification will reflect the state of the Realm after
the write transaction.
Person *person = [[Person allObjectsInRealm:realm] firstObject];
NSLog(@"person.dogs.count: %zu", person.dogs.count); // => 0
self.token = [person.dogs addNotificationBlock(RLMArray<Dog *> *dogs,
RLMCollectionChange *changes,
NSError *error) {
// Only fired once for the example
NSLog(@"dogs.count: %zu", dogs.count) // => 1
}];
[realm transactionWithBlock:^{
Dog *dog = [[Dog alloc] init];
dog.name = @"Rex";
[person.dogs addObject:dog];
}];
// end of run loop execution context
You must retain the returned token for as long as you want updates to continue
to be sent to the block. To stop receiving updates, call `-stop` on the token.
@warning This method cannot be called during a write transaction, or when the
containing Realm is read-only.
@warning This method may only be called on a managed array.
@param block The block to be called each time the array changes.
@return A token which must be held for as long as you want updates to be delivered.
*/
- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray<RLMObjectType> *__nullable array,
RLMCollectionChange *__nullable changes,
NSError *__nullable error))block __attribute__((warn_unused_result));
#pragma mark - Unavailable Methods
/**
`-[RLMArray init]` is not available because `RLMArray`s cannot be created directly.
`RLMArray` properties on `RLMObject`s are lazily created when accessed, or can be obtained by querying a Realm.
*/
- (instancetype)init __attribute__((unavailable("RLMArrays cannot be created directly")));
/**
`+[RLMArray new]` is not available because `RLMArray`s cannot be created directly.
`RLMArray` properties on `RLMObject`s are lazily created when accessed, or can be obtained by querying a Realm.
*/
+ (instancetype)new __attribute__((unavailable("RLMArrays cannot be created directly")));
@end
/// :nodoc:
@interface RLMArray (Swift)
// for use only in Swift class definitions
- (instancetype)initWithObjectClassName:(NSString *)objectClassName;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,28 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMArray.h>
NS_ASSUME_NONNULL_BEGIN
@interface RLMArray ()
- (instancetype)initWithObjectClassName:(NSString *)objectClassName;
- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,70 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMArray_Private.h"
#import "RLMCollection_Private.hpp"
#import <Realm/RLMResults.h>
#import <realm/link_view_fwd.hpp>
namespace realm {
class Results;
}
@class RLMObjectBase, RLMObjectSchema, RLMProperty;
class RLMClassInfo;
class RLMObservationInfo;
@interface RLMArray () {
@protected
NSString *_objectClassName;
@public
// The name of the property which this RLMArray represents
NSString *_key;
__weak RLMObjectBase *_parentObject;
}
@end
//
// LinkView backed RLMArray subclass
//
@interface RLMArrayLinkView : RLMArray <RLMFastEnumerable>
- (instancetype)initWithParent:(RLMObjectBase *)parentObject property:(RLMProperty *)property;
// deletes all objects in the RLMArray from their containing realms
- (void)deleteObjectsFromRealm;
@end
void RLMValidateArrayObservationKey(NSString *keyPath, RLMArray *array);
// Initialize the observation info for an array if needed
void RLMEnsureArrayObservationInfo(std::unique_ptr<RLMObservationInfo>& info,
NSString *keyPath, RLMArray *array, id observed);
//
// RLMResults private methods
//
@interface RLMResults () <RLMFastEnumerable>
+ (instancetype)resultsWithObjectInfo:(RLMClassInfo&)info
results:(realm::Results)results;
- (void)deleteObjectsFromRealm;
@end

View File

@ -1,325 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMRealm, RLMResults, RLMObject, RLMSortDescriptor, RLMNotificationToken, RLMCollectionChange;
/**
A homogenous collection of `RLMObject` instances. Examples of conforming types include `RLMArray`,
`RLMResults`, and `RLMLinkingObjects`.
*/
@protocol RLMCollection <NSFastEnumeration>
@required
#pragma mark - Properties
/**
The number of objects in the collection.
*/
@property (nonatomic, readonly, assign) NSUInteger count;
/**
The class name (i.e. type) of the `RLMObject`s contained in the collection.
*/
@property (nonatomic, readonly, copy) NSString *objectClassName;
/**
The Realm which manages the collection, or `nil` for unmanaged collections.
*/
@property (nonatomic, readonly) RLMRealm *realm;
#pragma mark - Accessing Objects from a Collection
/**
Returns the object at the index specified.
@param index The index to look up.
@return An `RLMObject` of the type contained in the collection.
*/
- (id)objectAtIndex:(NSUInteger)index;
/**
Returns the first object in the collection.
Returns `nil` if called on an empty collection.
@return An `RLMObject` of the type contained in the collection.
*/
- (nullable id)firstObject;
/**
Returns the last object in the collection.
Returns `nil` if called on an empty collection.
@return An `RLMObject` of the type contained in the collection.
*/
- (nullable id)lastObject;
#pragma mark - Querying a Collection
/**
Returns the index of an object in the collection.
Returns `NSNotFound` if the object is not found in the collection.
@param object An object (of the same type as returned from the `objectClassName` selector).
*/
- (NSUInteger)indexOfObject:(RLMObject *)object;
/**
Returns the index of the first object in the collection matching the predicate.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return The index of the object, or `NSNotFound` if the object is not found in the collection.
*/
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns the index of the first object in the collection matching the predicate.
@param predicate The predicate with which to filter the objects.
@return The index of the object, or `NSNotFound` if the object is not found in the collection.
*/
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate;
/**
Returns all objects matching the given predicate in the collection.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return An `RLMResults` containing objects that match the given predicate.
*/
- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns all objects matching the given predicate in the collection.
@param predicate The predicate with which to filter the objects.
@return An `RLMResults` containing objects that match the given predicate.
*/
- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate;
/**
Returns a sorted `RLMResults` from the collection.
@param property The property name to sort by.
@param ascending The direction to sort in.
@return An `RLMResults` sorted by the specified property.
*/
- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending;
/**
Returns a sorted `RLMResults` from the collection.
@param properties An array of `RLMSortDescriptor`s to sort by.
@return An `RLMResults` sorted by the specified properties.
*/
- (RLMResults *)sortedResultsUsingDescriptors:(NSArray<RLMSortDescriptor *> *)properties;
/// :nodoc:
- (id)objectAtIndexedSubscript:(NSUInteger)index;
/**
Returns an `NSArray` containing the results of invoking `valueForKey:` using `key` on each of the collection's objects.
@param key The name of the property.
@return An `NSArray` containing results.
*/
- (nullable id)valueForKey:(NSString *)key;
/**
Invokes `setValue:forKey:` on each of the collection's objects using the specified `value` and `key`.
@warning This method may only be called during a write transaction.
@param value The object value.
@param key The name of the property.
*/
- (void)setValue:(nullable id)value forKey:(NSString *)key;
#pragma mark - Notifications
/**
Registers a block to be called each time the collection changes.
The block will be asynchronously called with the initial collection, and then
called again after each write transaction which changes either any of the
objects in the collection, or which objects are in the collection.
The `change` parameter will be `nil` the first time the block is called.
For each call after that, it will contain information about
which rows in the collection were added, removed or modified. If a write transaction
did not modify any objects in this collection, the block is not called at all.
See the `RLMCollectionChange` documentation for information on how the changes
are reported and an example of updating a `UITableView`.
If an error occurs the block will be called with `nil` for the collection
parameter and a non-`nil` error. Currently the only errors that can occur are
when opening the Realm on the background worker thread.
At the time when the block is called, the collection object will be fully
evaluated and up-to-date, and as long as you do not perform a write transaction
on the same thread or explicitly call `-[RLMRealm refresh]`, accessing it will
never perform blocking work.
Notifications are delivered via the standard run loop, and so can't be
delivered while the run loop is blocked by other activity. When
notifications can't be delivered instantly, multiple notifications may be
coalesced into a single notification. This can include the notification
with the initial collection. For example, the following code performs a write
transaction immediately after adding the notification block, so there is no
opportunity for the initial notification to be delivered first. As a
result, the initial notification will reflect the state of the Realm after
the write transaction.
id<RLMCollection> collection = [Dog allObjects];
NSLog(@"dogs.count: %zu", dogs.count); // => 0
self.token = [collection addNotificationBlock:^(id<RLMCollection> dogs,
RLMCollectionChange *changes,
NSError *error) {
// Only fired once for the example
NSLog(@"dogs.count: %zu", dogs.count); // => 1
}];
[realm transactionWithBlock:^{
Dog *dog = [[Dog alloc] init];
dog.name = @"Rex";
[realm addObject:dog];
}];
// end of run loop execution context
You must retain the returned token for as long as you want updates to continue
to be sent to the block. To stop receiving updates, call `-stop` on the token.
@warning This method cannot be called during a write transaction, or when the
containing Realm is read-only.
@param block The block to be called each time the collection changes.
@return A token which must be held for as long as you want collection notifications to be delivered.
*/
- (RLMNotificationToken *)addNotificationBlock:(void (^)(id<RLMCollection> __nullable collection,
RLMCollectionChange *__nullable change,
NSError *__nullable error))block __attribute__((warn_unused_result));
@end
/**
An `RLMSortDescriptor` stores a property name and a sort order for use with
`sortedResultsUsingDescriptors:`. It is similar to `NSSortDescriptor`, but supports
only the subset of functionality which can be efficiently run by Realm's query
engine.
`RLMSortDescriptor` instances are immutable.
*/
@interface RLMSortDescriptor : NSObject
#pragma mark - Properties
/**
The name of the property which the sort descriptor orders results by.
*/
@property (nonatomic, readonly) NSString *property;
/**
Whether the descriptor sorts in ascending or descending order.
*/
@property (nonatomic, readonly) BOOL ascending;
#pragma mark - Methods
/**
Returns a new sort descriptor for the given property name and sort direction.
*/
+ (instancetype)sortDescriptorWithProperty:(NSString *)propertyName ascending:(BOOL)ascending;
/**
Returns a copy of the receiver with the sort direction reversed.
*/
- (instancetype)reversedSortDescriptor;
@end
/**
A `RLMCollectionChange` object encapsulates information about changes to collections
that are reported by Realm notifications.
`RLMCollectionChange` is passed to the notification blocks registered with
`-addNotificationBlock` on `RLMArray` and `RLMResults`, and reports what rows in the
collection changed since the last time the notification block was called.
The change information is available in two formats: a simple array of row
indices in the collection for each type of change, and an array of index paths
in a requested section suitable for passing directly to `UITableView`'s batch
update methods. A complete example of updating a `UITableView` named `tv`:
[tv beginUpdates];
[tv deleteRowsAtIndexPaths:[changes deletionsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic];
[tv insertRowsAtIndexPaths:[changes insertionsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic];
[tv reloadRowsAtIndexPaths:[changes modificationsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic];
[tv endUpdates];
All of the arrays in an `RLMCollectionChange` are always sorted in ascending order.
*/
@interface RLMCollectionChange : NSObject
/// The indices of objects in the previous version of the collection which have
/// been removed from this one.
@property (nonatomic, readonly) NSArray<NSNumber *> *deletions;
/// The indices in the new version of the collection which were newly inserted.
@property (nonatomic, readonly) NSArray<NSNumber *> *insertions;
/**
The indices in the new version of the collection which were modified.
For `RLMResults`, this means that one or more of the properties of the object at
that index were modified (or an object linked to by that object was
modified).
For `RLMArray`, the array itself being modified to contain a
different object at that index will also be reported as a modification.
*/
@property (nonatomic, readonly) NSArray<NSNumber *> *modifications;
/// Returns the index paths of the deletion indices in the given section.
- (NSArray<NSIndexPath *> *)deletionsInSection:(NSUInteger)section;
/// Returns the index paths of the insertion indices in the given section.
- (NSArray<NSIndexPath *> *)insertionsInSection:(NSUInteger)section;
/// Returns the index paths of the modification indices in the given section.
- (NSArray<NSIndexPath *> *)modificationsInSection:(NSUInteger)section;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,72 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMCollection.h>
#import <Realm/RLMRealm.h>
namespace realm {
class List;
class Results;
class TableView;
struct CollectionChangeSet;
struct NotificationToken;
}
class RLMClassInfo;
@protocol RLMFastEnumerable
@property (nonatomic, readonly) RLMRealm *realm;
@property (nonatomic, readonly) RLMClassInfo *objectInfo;
@property (nonatomic, readonly) NSUInteger count;
- (NSUInteger)indexInSource:(NSUInteger)index;
- (realm::TableView)tableView;
@end
// An object which encapulates the shared logic for fast-enumerating RLMArray
// and RLMResults, and has a buffer to store strong references to the current
// set of enumerated items
@interface RLMFastEnumerator : NSObject
- (instancetype)initWithCollection:(id<RLMFastEnumerable>)collection
objectSchema:(RLMClassInfo&)objectSchema;
// Detach this enumerator from the source collection. Must be called before the
// source collection is changed.
- (void)detach;
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
count:(NSUInteger)len;
@end
@interface RLMCancellationToken : RLMNotificationToken
- (instancetype)initWithToken:(realm::NotificationToken)token;
@end
@interface RLMCollectionChange ()
- (instancetype)initWithChanges:(realm::CollectionChangeSet)indices;
@end
template<typename Collection>
RLMNotificationToken *RLMAddNotificationBlock(id objcCollection,
Collection& collection,
void (^block)(id, RLMCollectionChange *, NSError *),
bool suppressInitialChange=false);
NSArray *RLMCollectionValueForKey(id<RLMFastEnumerable> collection, NSString *key);
void RLMCollectionSetValueForKey(id<RLMFastEnumerable> collection, NSString *key, id value);
NSString *RLMDescriptionWithMaxDepth(NSString *name, id<RLMCollection> collection, NSUInteger depth);

View File

@ -1,204 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
// For compatibility with Xcode 7, before extensible string enums were introduced,
#ifdef NS_EXTENSIBLE_STRING_ENUM
#define RLM_EXTENSIBLE_STRING_ENUM NS_EXTENSIBLE_STRING_ENUM
#define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(_, extensible_string_enum) NS_SWIFT_NAME(extensible_string_enum)
#else
#define RLM_EXTENSIBLE_STRING_ENUM
#define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(fully_qualified, _) NS_SWIFT_NAME(fully_qualified)
#endif
#if __has_attribute(ns_error_domain)
#define RLM_ERROR_ENUM(type, name, domain) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wignored-attributes\"") \
NS_ENUM(type, __attribute__((ns_error_domain(domain))) name) \
_Pragma("clang diagnostic pop")
#else
#define RLM_ERROR_ENUM(type, name, domain) NS_ENUM(type, name)
#endif
#pragma mark - Enums
/**
`RLMPropertyType` is an enumeration describing all property types supported in Realm models.
For more information, see [Realm Models](https://realm.io/docs/objc/latest/#models).
*/
// Make sure numbers match those in <realm/data_type.hpp>
typedef NS_ENUM(int32_t, RLMPropertyType) {
#pragma mark - Primitive types
/** Integers: `NSInteger`, `int`, `long`, `Int` (Swift) */
RLMPropertyTypeInt = 0,
/** Booleans: `BOOL`, `bool`, `Bool` (Swift) */
RLMPropertyTypeBool = 1,
/** Floating-point numbers: `float`, `Float` (Swift) */
RLMPropertyTypeFloat = 9,
/** Double-precision floating-point numbers: `double`, `Double` (Swift) */
RLMPropertyTypeDouble = 10,
#pragma mark - Object types
/** Strings: `NSString`, `String` (Swift) */
RLMPropertyTypeString = 2,
/** Binary data: `NSData` */
RLMPropertyTypeData = 4,
/**
Any object: `id`.
This property type is no longer supported for new models. However, old models with any-typed properties are still
supported for migration purposes.
*/
RLMPropertyTypeAny = 6,
/** Dates: `NSDate` */
RLMPropertyTypeDate = 8,
#pragma mark - Array/Linked object types
/** Realm model objects. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */
RLMPropertyTypeObject = 12,
/** Realm arrays. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */
RLMPropertyTypeArray = 13,
/** Realm linking objects. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */
RLMPropertyTypeLinkingObjects = 14,
};
/** An error domain identifying Realm-specific errors. */
extern NSString * const RLMErrorDomain;
/** An error domain identifying non-specific system errors. */
extern NSString * const RLMUnknownSystemErrorDomain;
/**
`RLMError` is an enumeration representing all recoverable errors. It is associated with the
Realm error domain specified in `RLMErrorDomain`.
*/
typedef RLM_ERROR_ENUM(NSInteger, RLMError, RLMErrorDomain) {
/** Denotes a general error that occurred when trying to open a Realm. */
RLMErrorFail = 1,
/** Denotes a file I/O error that occurred when trying to open a Realm. */
RLMErrorFileAccess = 2,
/**
Denotes a file permission error that ocurred when trying to open a Realm.
This error can occur if the user does not have permission to open or create
the specified file in the specified access mode when opening a Realm.
*/
RLMErrorFilePermissionDenied = 3,
/** Denotes an error where a file was to be written to disk, but another file with the same name already exists. */
RLMErrorFileExists = 4,
/**
Denotes an error that occurs if a file could not be found.
This error may occur if a Realm file could not be found on disk when trying to open a
Realm as read-only, or if the directory part of the specified path was not found when
trying to write a copy.
*/
RLMErrorFileNotFound = 5,
/**
Denotes an error that occurs if a file format upgrade is required to open the file,
but upgrades were explicitly disabled.
*/
RLMErrorFileFormatUpgradeRequired = 6,
/**
Denotes an error that occurs if the database file is currently open in another
process which cannot share with the current process due to an
architecture mismatch.
This error may occur if trying to share a Realm file between an i386 (32-bit) iOS
Simulator and the Realm Browser application. In this case, please use the 64-bit
version of the iOS Simulator.
*/
RLMErrorIncompatibleLockFile = 8,
/** Denotes an error that occurs when there is insufficient available address space. */
RLMErrorAddressSpaceExhausted = 9,
/** Denotes an error that occurs if there is a schema version mismatch, so that a migration is required. */
RLMErrorSchemaMismatch = 10,
};
#pragma mark - Constants
#pragma mark - Notification Constants
/**
A notification indicating that changes were made to a Realm.
*/
typedef NSString * RLMNotification RLM_EXTENSIBLE_STRING_ENUM;
/**
This notification is posted by a Realm when the data in that Realm has changed.
More specifically, this notification is posted after a Realm has been refreshed to
reflect a write transaction. This can happen when an autorefresh occurs, when
`-[RLMRealm refresh]` is called, after an implicit refresh from `-[RLMRealm beginWriteTransaction]`,
or after a local write transaction is completed.
*/
extern RLMNotification const RLMRealmRefreshRequiredNotification
RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(RLMRealmRefreshRequiredNotification, RefreshRequired);
/**
This notification is posted by a Realm when a write transaction has been
committed to a Realm on a different thread for the same file.
It is not posted if `-[RLMRealm autorefresh]` is enabled, or if the Realm is
refreshed before the notification has a chance to run.
Realms with autorefresh disabled should normally install a handler for this
notification which calls `-[RLMRealm refresh]` after doing some work. Refreshing
the Realm is optional, but not refreshing the Realm may lead to large Realm
files. This is because Realm must keep an extra copy of the data for the stale
Realm.
*/
extern RLMNotification const RLMRealmDidChangeNotification
RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(RLMRealmDidChangeNotification, DidChange);
#pragma mark - Other Constants
/** The schema version used for uninitialized Realms */
extern const uint64_t RLMNotVersioned;
/** The corresponding value is the name of an exception thrown by Realm. */
extern NSString * const RLMExceptionName;
/** The corresponding value is a Realm file version. */
extern NSString * const RLMRealmVersionKey;
/** The corresponding key is the version of the underlying database engine. */
extern NSString * const RLMRealmCoreVersionKey;
/** The corresponding key is the Realm invalidated property name. */
extern NSString * const RLMInvalidatedKey;
NS_ASSUME_NONNULL_END

View File

@ -1,33 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
@class RLMArray;
NS_ASSUME_NONNULL_BEGIN
// A base class for Swift generic Lists to make it possible to interact with
// them from obj-c
@interface RLMListBase : NSObject <NSFastEnumeration>
@property (nonatomic, strong) RLMArray *_rlmArray;
- (instancetype)initWithArray:(RLMArray *)array;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,127 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMSchema;
@class RLMArray;
@class RLMObject;
/**
A block type which provides both the old and new versions of an object in the Realm. Object
properties can only be accessed using keyed subscripting.
@see `-[RLMMigration enumerateObjects:block:]`
@param oldObject The object from the original Realm (read-only).
@param newObject The object from the migrated Realm (read-write).
*/
typedef void (^RLMObjectMigrationBlock)(RLMObject * __nullable oldObject, RLMObject * __nullable newObject);
/**
`RLMMigration` instances encapsulate information intended to facilitate a schema migration.
A `RLMMigration` instance is passed into a user-defined `RLMMigrationBlock` block when updating
the version of a Realm. This instance provides access to the old and new database schemas, the
objects in the Realm, and provides functionality for modifying the Realm during the migration.
*/
@interface RLMMigration : NSObject
#pragma mark - Properties
/**
Returns the old `RLMSchema`. This is the schema which describes the Realm before the
migration is applied.
*/
@property (nonatomic, readonly) RLMSchema *oldSchema;
/**
Returns the new `RLMSchema`. This is the schema which describes the Realm after the
migration is applied.
*/
@property (nonatomic, readonly) RLMSchema *newSchema;
#pragma mark - Altering Objects during a Migration
/**
Enumerates all the objects of a given type in the Realm, providing both the old and new versions
of each object. Within the block, object properties can only be accessed using keyed subscripting.
@param className The name of the `RLMObject` class to enumerate.
@warning All objects returned are of a type specific to the current migration and should not be cast
to `className`. Instead, treat them as `RLMObject`s and use keyed subscripting to access
properties.
*/
- (void)enumerateObjects:(NSString *)className block:(__attribute__((noescape)) RLMObjectMigrationBlock)block;
/**
Creates and returns an `RLMObject` instance of type `className` in the Realm being migrated.
The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or
dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed
property. An exception will be thrown if any required properties are not present and those properties were not defined
with default values.
When passing in an `NSArray` as the `value` argument, all properties must be present, valid and in the same order as
the properties defined in the model.
@param className The name of the `RLMObject` class to create.
@param value The value used to populate the object.
*/
- (RLMObject *)createObject:(NSString *)className withValue:(id)value;
/**
Deletes an object from a Realm during a migration.
It is permitted to call this method from within the block passed to `-[enumerateObjects:block:]`.
@param object Object to be deleted from the Realm being migrated.
*/
- (void)deleteObject:(RLMObject *)object;
/**
Deletes the data for the class with the given name.
All objects of the given class will be deleted. If the `RLMObject` subclass no longer exists in your program,
any remaining metadata for the class will be removed from the Realm file.
@param name The name of the `RLMObject` class to delete.
@return A Boolean value indicating whether there was any data to delete.
*/
- (BOOL)deleteDataForClassName:(NSString *)name;
/**
Renames a property of the given class from `oldName` to `newName`.
@param className The name of the class whose property should be renamed. This class must be present
in both the old and new Realm schemas.
@param oldName The old name for the property to be renamed. There must not be a property with this name in the
class as defined by the new Realm schema.
@param newName The new name for the property to be renamed. There must not be a property with this name in the
class as defined by the old Realm schema.
*/
- (void)renamePropertyForClass:(NSString *)className oldName:(NSString *)oldName newName:(NSString *)newName;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,40 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMMigration.h>
#import <Realm/RLMObjectBase.h>
#import <Realm/RLMRealm.h>
namespace realm {
class Schema;
}
NS_ASSUME_NONNULL_BEGIN
@interface RLMMigration ()
@property (nonatomic, strong) RLMRealm *oldRealm;
@property (nonatomic, strong) RLMRealm *realm;
- (instancetype)initWithRealm:(RLMRealm *)realm oldRealm:(RLMRealm *)oldRealm schema:(realm::Schema &)schema;
- (void)execute:(RLMMigrationBlock)block;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,445 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMObjectBase.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMPropertyDescriptor;
@class RLMRealm;
@class RLMResults;
@class RLMObjectSchema;
/**
`RLMObject` is a base class for model objects representing data stored in Realms.
Define your model classes by subclassing `RLMObject` and adding properties to be managed.
Then instantiate and use your custom subclasses instead of using the `RLMObject` class directly.
// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@property BOOL adopted;
@end
// Dog.m
@implementation Dog
@end //none needed
### Supported property types
- `NSString`
- `NSInteger`, `int`, `long`, `float`, and `double`
- `BOOL` or `bool`
- `NSDate`
- `NSData`
- `NSNumber<X>`, where `X` is one of `RLMInt`, `RLMFloat`, `RLMDouble` or `RLMBool`, for optional number properties
- `RLMObject` subclasses, to model many-to-one relationships.
- `RLMArray<X>`, where `X` is an `RLMObject` subclass, to model many-to-many relationships.
### Querying
You can initiate queries directly via the class methods: `allObjects`, `objectsWhere:`, and `objectsWithPredicate:`.
These methods allow you to easily query a custom subclass for instances of that class in the default Realm.
To search in a Realm other than the default Realm, use the `allObjectsInRealm:`, `objectsInRealm:where:`,
and `objectsInRealm:withPredicate:` class methods.
@see `RLMRealm`
### Relationships
See our [Cocoa guide](https://realm.io/docs/objc/latest#relationships) for more details.
### Key-Value Observing
All `RLMObject` properties (including properties you create in subclasses) are
[Key-Value Observing compliant](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html),
except for `realm` and `objectSchema`.
Keep the following tips in mind when observing Realm objects:
1. Unlike `NSMutableArray` properties, `RLMArray` properties do not require
using the proxy object returned from `-mutableArrayValueForKey:`, or defining
KVC mutation methods on the containing class. You can simply call methods on
the `RLMArray` directly; any changes will be automatically observed by the containing
object.
2. Unmanaged `RLMObject` instances cannot be added to a Realm while they have any
observed properties.
3. Modifying managed `RLMObject`s within `-observeValueForKeyPath:ofObject:change:context:`
is not recommended. Properties may change even when the Realm is not in a write
transaction (for example, when `-[RLMRealm refresh]` is called after changes
are made on a different thread), and notifications sent prior to the change
being applied (when `NSKeyValueObservingOptionPrior` is used) may be sent at
times when you *cannot* begin a write transaction.
*/
@interface RLMObject : RLMObjectBase
#pragma mark - Creating & Initializing Objects
/**
Creates an unmanaged instance of a Realm object.
Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm.
@see `[RLMRealm addObject:]`
*/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
/**
Creates an unmanaged instance of a Realm object.
Pass in an `NSArray` or `NSDictionary` instance to set the values of the object's properties.
Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm.
@see `[RLMRealm addObject:]`
*/
- (instancetype)initWithValue:(id)value NS_DESIGNATED_INITIALIZER;
/**
Returns the class name for a Realm object subclass.
@warning Do not override. Realm relies on this method returning the exact class
name.
@return The class name for the model class.
*/
+ (NSString *)className;
/**
Creates an instance of a Realm object with a given value, and adds it to the default Realm.
If nested objects are included in the argument, `createInDefaultRealmWithValue:` will be recursively called
on them.
The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in
`NSJSONSerialization`, or an array containing one element for each managed property. An exception will be thrown if
any required properties are not present and those properties were not defined with default values.
When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the
properties defined in the model.
@param value The value used to populate the object.
@see `defaultPropertyValues`
*/
+ (instancetype)createInDefaultRealmWithValue:(id)value;
/**
Creates an instance of a Realm object with a given value, and adds it to the specified Realm.
If nested objects are included in the argument, `createInRealm:withValue:` will be recursively called
on them.
The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in
`NSJSONSerialization`, or an array containing one element for each managed property. An exception will be thrown if any
required properties are not present and those properties were not defined with default values.
When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the
properties defined in the model.
@param realm The Realm which should manage the newly-created object.
@param value The value used to populate the object.
@see `defaultPropertyValues`
*/
+ (instancetype)createInRealm:(RLMRealm *)realm withValue:(id)value;
/**
Creates or updates a Realm object within the default Realm.
This method may only be called on Realm object types with a primary key defined. If there is already
an object with the same primary key value in the default Realm, its values are updated and the object
is returned. Otherwise, this method creates and populates a new instance of the object in the default Realm.
If nested objects are included in the argument, `createOrUpdateInDefaultRealmWithValue:` will be
recursively called on them if they have primary keys, `createInDefaultRealmWithValue:` if they do not.
If the argument is a Realm object already managed by the default Realm, the argument's type is the same
as the receiver, and the objects have identical values for their managed properties, this method does nothing.
The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or
dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed
property. An exception will be thrown if any required properties are not present and those properties were not defined
with default values.
When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the
properties defined in the model.
@param value The value used to populate the object.
@see `defaultPropertyValues`, `primaryKey`
*/
+ (instancetype)createOrUpdateInDefaultRealmWithValue:(id)value;
/**
Creates or updates an Realm object within a specified Realm.
This method may only be called on Realm object types with a primary key defined. If there is already
an object with the same primary key value in the given Realm, its values are updated and the object
is returned. Otherwise this method creates and populates a new instance of this object in the given Realm.
If nested objects are included in the argument, `createOrUpdateInRealm:withValue:` will be
recursively called on them if they have primary keys, `createInRealm:withValue:` if they do not.
If the argument is a Realm object already managed by the given Realm, the argument's type is the same
as the receiver, and the objects have identical values for their managed properties, this method does nothing.
The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or
dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed
property. An exception will be thrown if any required properties are not present and those properties were not defined
with default values.
When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the
properties defined in the model.
@param realm The Realm which should own the object.
@param value The value used to populate the object.
@see `defaultPropertyValues`, `primaryKey`
*/
+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value;
#pragma mark - Properties
/**
The Realm which manages the object, or `nil` if the object is unmanaged.
*/
@property (nonatomic, readonly, nullable) RLMRealm *realm;
/**
The object schema which lists the managed properties for the object.
*/
@property (nonatomic, readonly) RLMObjectSchema *objectSchema;
/**
Indicates if the object can no longer be accessed because it is now invalid.
An object can no longer be accessed if the object has been deleted from the Realm that manages it, or
if `invalidate` is called on that Realm.
*/
@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
#pragma mark - Customizing your Objects
/**
Returns an array of property names for properties which should be indexed.
Only string, integer, boolean, and `NSDate` properties are supported.
@return An array of property names.
*/
+ (NSArray<NSString *> *)indexedProperties;
/**
Override this method to specify the default values to be used for each property.
@return A dictionary mapping property names to their default values.
*/
+ (nullable NSDictionary *)defaultPropertyValues;
/**
Override this method to specify the name of a property to be used as the primary key.
Only properties of types `RLMPropertyTypeString` and `RLMPropertyTypeInt` can be designated as the primary key.
Primary key properties enforce uniqueness for each value whenever the property is set, which incurs minor overhead.
Indexes are created automatically for primary key properties.
@return The name of the property designated as the primary key.
*/
+ (nullable NSString *)primaryKey;
/**
Override this method to specify the names of properties to ignore. These properties will not be managed by the Realm
that manages the object.
@return An array of property names to ignore.
*/
+ (nullable NSArray<NSString *> *)ignoredProperties;
/**
Override this method to specify the names of properties that are non-optional (i.e. cannot be assigned a `nil` value).
By default, all properties of a type whose values can be set to `nil` are considered optional properties.
To require that an object in a Realm always store a non-`nil` value for a property,
add the name of the property to the array returned from this method.
Properties of `RLMObject` type cannot be non-optional. Array and `NSNumber` properties
can be non-optional, but there is no reason to do so: arrays do not support storing nil, and
if you want a non-optional number you should instead use the primitive type.
@return An array of property names that are required.
*/
+ (NSArray<NSString *> *)requiredProperties;
/**
Override this method to provide information related to properties containing linking objects.
Each property of type `RLMLinkingObjects` must have a key in the dictionary returned by this method consisting
of the property name. The corresponding value must be an instance of `RLMPropertyDescriptor` that describes the class
and property that the property is linked to.
return @{ @"owners": [RLMPropertyDescriptor descriptorWithClass:Owner.class propertyName:@"dogs"] };
@return A dictionary mapping property names to `RLMPropertyDescriptor` instances.
*/
+ (NSDictionary<NSString *, RLMPropertyDescriptor *> *)linkingObjectsProperties;
#pragma mark - Getting & Querying Objects from the Default Realm
/**
Returns all objects of this object type from the default Realm.
@return An `RLMResults` containing all objects of this type in the default Realm.
*/
+ (RLMResults *)allObjects;
/**
Returns all objects of this object type matching the given predicate from the default Realm.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate.
*/
+ (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns all objects of this object type matching the given predicate from the default Realm.
@param predicate The predicate with which to filter the objects.
@return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate.
*/
+ (RLMResults *)objectsWithPredicate:(nullable NSPredicate *)predicate;
/**
Retrieves the single instance of this object type with the given primary key from the default Realm.
Returns the object from the default Realm which has the given primary key, or
`nil` if the object does not exist. This is slightly faster than the otherwise
equivalent `[[SubclassName objectsWhere:@"primaryKeyPropertyName = %@", key] firstObject]`.
This method requires that `primaryKey` be overridden on the receiving subclass.
@return An object of this object type, or `nil` if an object with the given primary key does not exist.
@see `-primaryKey`
*/
+ (nullable instancetype)objectForPrimaryKey:(nullable id)primaryKey;
#pragma mark - Querying Specific Realms
/**
Returns all objects of this object type from the specified Realm.
@param realm The Realm to query.
@return An `RLMResults` containing all objects of this type in the specified Realm.
*/
+ (RLMResults *)allObjectsInRealm:(RLMRealm *)realm;
/**
Returns all objects of this object type matching the given predicate from the specified Realm.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@param realm The Realm to query.
@return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate.
*/
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ...;
/// :nodoc:
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args;
/**
Returns all objects of this object type matching the given predicate from the specified Realm.
@param predicate A predicate to use to filter the elements.
@param realm The Realm to query.
@return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate.
*/
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(nullable NSPredicate *)predicate;
/**
Retrieves the single instance of this object type with the given primary key from the specified Realm.
Returns the object from the specified Realm which has the given primary key, or
`nil` if the object does not exist. This is slightly faster than the otherwise
equivalent `[[SubclassName objectsInRealm:realm where:@"primaryKeyPropertyName = %@", key] firstObject]`.
This method requires that `primaryKey` be overridden on the receiving subclass.
@return An object of this object type, or `nil` if an object with the given primary key does not exist.
@see `-primaryKey`
*/
+ (nullable instancetype)objectInRealm:(RLMRealm *)realm forPrimaryKey:(nullable id)primaryKey;
#pragma mark - Other Instance Methods
/**
Returns YES if another Realm object instance points to the same object as the receiver in the Realm managing
the receiver.
For object types with a primary, key, `isEqual:` is overridden to use this method (along with a corresponding
implementation for `hash`).
@param object The object to compare the receiver to.
@return Whether the object represents the same object as the receiver.
*/
- (BOOL)isEqualToObject:(RLMObject *)object;
#pragma mark - Dynamic Accessors
/// :nodoc:
- (nullable id)objectForKeyedSubscript:(NSString *)key;
/// :nodoc:
- (void)setObject:(nullable id)obj forKeyedSubscript:(NSString *)key;
@end
#pragma mark - RLMArray Property Declaration
/**
Properties on `RLMObject`s of type `RLMArray` must have an associated type. A type is associated
with an `RLMArray` property by defining a protocol for the object type that the array should contain.
To define the protocol for an object, you can use the macro RLM_ARRAY_TYPE:
RLM_ARRAY_TYPE(ObjectType)
...
@property RLMArray<ObjectType *><ObjectType> *arrayOfObjectTypes;
*/
#define RLM_ARRAY_TYPE(RLM_OBJECT_SUBCLASS)\
@protocol RLM_OBJECT_SUBCLASS <NSObject> \
@end
NS_ASSUME_NONNULL_END

View File

@ -1,41 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMRealm;
@class RLMSchema;
@class RLMObjectSchema;
/// :nodoc:
@interface RLMObjectBase : NSObject
@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
+ (NSString *)className;
// Returns whether the class is included in the default set of classes managed by a Realm.
+ (BOOL)shouldIncludeInDefaultSchema;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,82 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMObject.h>
@class RLMObjectSchema, RLMRealm;
NS_ASSUME_NONNULL_BEGIN
/**
Returns the Realm that manages the object, if one exists.
@warning This function is useful only in specialized circumstances, for example, when building components
that integrate with Realm. If you are simply building an app on Realm, it is
recommended to retrieve the Realm that manages the object via `RLMObject`.
@param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`.
@return The Realm which manages this object. Returns `nil `for unmanaged objects.
*/
FOUNDATION_EXTERN RLMRealm * _Nullable RLMObjectBaseRealm(RLMObjectBase * _Nullable object);
/**
Returns an `RLMObjectSchema` which describes the managed properties of the object.
@warning This function is useful only in specialized circumstances, for example, when building components
that integrate with Realm. If you are simply building an app on Realm, it is
recommended to retrieve `objectSchema` via `RLMObject`.
@param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`.
@return The object schema which lists the managed properties for the object.
*/
FOUNDATION_EXTERN RLMObjectSchema * _Nullable RLMObjectBaseObjectSchema(RLMObjectBase * _Nullable object);
/**
Returns the object corresponding to a key value.
@warning This function is useful only in specialized circumstances, for example, when building components
that integrate with Realm. If you are simply building an app on Realm, it is
recommended to retrieve key values via `RLMObject`.
@warning Will throw an `NSUndefinedKeyException` if `key` is not present on the object.
@param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`.
@param key The name of the property.
@return The object for the property requested.
*/
FOUNDATION_EXTERN id _Nullable RLMObjectBaseObjectForKeyedSubscript(RLMObjectBase * _Nullable object, NSString *key);
/**
Sets a value for a key on the object.
@warning This function is useful only in specialized circumstances, for example, when building components
that integrate with Realm. If you are simply building an app on Realm, it is
recommended to set key values via `RLMObject`.
@warning Will throw an `NSUndefinedKeyException` if `key` is not present on the object.
@param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`.
@param key The name of the property.
@param obj The object to set as the value of the key.
*/
FOUNDATION_EXTERN void RLMObjectBaseSetObjectForKeyedSubscript(RLMObjectBase * _Nullable object, NSString *key, id _Nullable obj);
NS_ASSUME_NONNULL_END

View File

@ -1,72 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMProperty;
/**
This class represents Realm model object schemas.
When using Realm, `RLMObjectSchema` instances allow performing migrations and
introspecting the database's schema.
Object schemas map to tables in the core database.
*/
@interface RLMObjectSchema : NSObject<NSCopying>
#pragma mark - Properties
/**
An array of `RLMProperty` instances representing the managed properties of a class described by the schema.
@see `RLMProperty`
*/
@property (nonatomic, readonly, copy) NSArray<RLMProperty *> *properties;
/**
The name of the class the schema describes.
*/
@property (nonatomic, readonly) NSString *className;
/**
The property which serves as the primary key for the class the schema describes, if any.
*/
@property (nonatomic, readonly, nullable) RLMProperty *primaryKeyProperty;
#pragma mark - Methods
/**
Retrieves an `RLMProperty` object by the property name.
@param propertyName The property's name.
@return An `RLMProperty` object, or `nil` if there is no property with the given name.
*/
- (nullable RLMProperty *)objectForKeyedSubscript:(NSString *)propertyName;
/**
Returns whether two `RLMObjectSchema` instances are equal.
*/
- (BOOL)isEqualToObjectSchema:(RLMObjectSchema *)objectSchema;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,68 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMObjectSchema.h>
#import <objc/runtime.h>
NS_ASSUME_NONNULL_BEGIN
// RLMObjectSchema private
@interface RLMObjectSchema () {
@public
bool _isSwiftClass;
}
// writable redecleration
@property (nonatomic, readwrite, copy) NSArray<RLMProperty *> *properties;
@property (nonatomic, readwrite, assign) bool isSwiftClass;
// class used for this object schema
@property (nonatomic, readwrite, assign) Class objectClass;
@property (nonatomic, readwrite, assign) Class accessorClass;
@property (nonatomic, readwrite, assign) Class unmanagedClass;
@property (nonatomic, readwrite, nullable) RLMProperty *primaryKeyProperty;
@property (nonatomic, copy) NSArray<RLMProperty *> *computedProperties;
@property (nonatomic, readonly) NSArray<RLMProperty *> *swiftGenericProperties;
// returns a cached or new schema for a given object class
+ (instancetype)schemaForObjectClass:(Class)objectClass;
@end
@interface RLMObjectSchema (Dynamic)
/**
This method is useful only in specialized circumstances, for example, when accessing objects
in a Realm produced externally. If you are simply building an app on Realm, it is not recommended
to use this method as an [RLMObjectSchema](RLMObjectSchema) is generated automatically for every [RLMObject](RLMObject) subclass.
Initialize an RLMObjectSchema with classname, objectClass, and an array of properties
@warning This method is useful only in specialized circumstances.
@param objectClassName The name of the class used to refer to objects of this type.
@param objectClass The Objective-C class used when creating instances of this type.
@param properties An array of RLMProperty instances describing the managed properties for this type.
@return An initialized instance of RLMObjectSchema.
*/
- (instancetype)initWithClassName:(NSString *)objectClassName objectClass:(Class)objectClass properties:(NSArray *)properties;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,29 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObjectSchema_Private.h"
#import "object_schema.hpp"
@interface RLMObjectSchema ()
// create realm::ObjectSchema copy
- (realm::ObjectSchema)objectStoreCopy;
// initialize with realm::ObjectSchema
+ (instancetype)objectSchemaForObjectStoreSchema:(realm::ObjectSchema const&)objectSchema;
@end

View File

@ -1,102 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#ifdef __cplusplus
extern "C" {
#endif
@class RLMRealm, RLMSchema, RLMObjectBase, RLMResults, RLMProperty;
NS_ASSUME_NONNULL_BEGIN
//
// Accessor Creation
//
// create or get cached accessors for the given schema
void RLMRealmCreateAccessors(RLMSchema *schema);
//
// Options for object creation
//
typedef NS_OPTIONS(NSUInteger, RLMCreationOptions) {
// Normal object creation
RLMCreationOptionsNone = 0,
// If the property is a link or array property, upsert the linked objects
// if they have a primary key, and insert them otherwise.
RLMCreationOptionsCreateOrUpdate = 1 << 0,
// Allow unmanaged objects to be promoted to managed objects
// if false objects are copied during object creation
RLMCreationOptionsPromoteUnmanaged = 1 << 1,
};
//
// Adding, Removing, Getting Objects
//
// add an object to the given realm
void RLMAddObjectToRealm(RLMObjectBase *object, RLMRealm *realm, bool createOrUpdate);
// delete an object from its realm
void RLMDeleteObjectFromRealm(RLMObjectBase *object, RLMRealm *realm);
// deletes all objects from a realm
void RLMDeleteAllObjectsFromRealm(RLMRealm *realm);
// get objects of a given class
RLMResults *RLMGetObjects(RLMRealm *realm, NSString *objectClassName, NSPredicate * _Nullable predicate)
NS_RETURNS_RETAINED;
// get an object with the given primary key
id _Nullable RLMGetObject(RLMRealm *realm, NSString *objectClassName, id _Nullable key) NS_RETURNS_RETAINED;
// create object from array or dictionary
RLMObjectBase *RLMCreateObjectInRealmWithValue(RLMRealm *realm, NSString *className, id _Nullable value, bool createOrUpdate)
NS_RETURNS_RETAINED;
//
// Accessor Creation
//
// switch List<> properties from being backed by unmanaged RLMArrays to RLMArrayLinkView
void RLMInitializeSwiftAccessorGenerics(RLMObjectBase *object);
#ifdef __cplusplus
}
namespace realm {
class Table;
template<typename T> class BasicRowExpr;
using RowExpr = BasicRowExpr<Table>;
}
class RLMClassInfo;
// Create accessors
RLMObjectBase *RLMCreateObjectAccessor(RLMRealm *realm, RLMClassInfo& info,
NSUInteger index) NS_RETURNS_RETAINED;
RLMObjectBase *RLMCreateObjectAccessor(RLMRealm *realm, RLMClassInfo& info,
realm::RowExpr row) NS_RETURNS_RETAINED;
#endif
NS_ASSUME_NONNULL_END

View File

@ -1,98 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMObjectBase_Dynamic.h>
NS_ASSUME_NONNULL_BEGIN
// RLMObject accessor and read/write realm
@interface RLMObjectBase () {
@public
RLMRealm *_realm;
__unsafe_unretained RLMObjectSchema *_objectSchema;
}
// unmanaged initializer
- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema NS_DESIGNATED_INITIALIZER;
// live accessor initializer
- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm
schema:(RLMObjectSchema *)schema NS_DESIGNATED_INITIALIZER;
// shared schema for this class
+ (nullable RLMObjectSchema *)sharedSchema;
// provide injection point for alternative Swift object util class
+ (Class)objectUtilClass:(BOOL)isSwift;
@end
@interface RLMObject ()
// unmanaged initializer
- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema NS_DESIGNATED_INITIALIZER;
// live accessor initializer
- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm
schema:(RLMObjectSchema *)schema NS_DESIGNATED_INITIALIZER;
@end
@interface RLMDynamicObject : RLMObject
@end
// A reference to an object's row that doesn't keep the object accessor alive.
// Used by some Swift property types, such as LinkingObjects, to avoid retain cycles
// with their containing object.
@interface RLMWeakObjectHandle : NSObject
- (instancetype)initWithObject:(RLMObjectBase *)object;
// Consumes the row, so can only usefully be called once.
@property (nonatomic, readonly) RLMObjectBase *object;
@end
// Calls valueForKey: and re-raises NSUndefinedKeyExceptions
FOUNDATION_EXTERN id _Nullable RLMValidatedValueForProperty(id object, NSString *key, NSString *className);
// Compare two RLObjectBases
FOUNDATION_EXTERN BOOL RLMObjectBaseAreEqual(RLMObjectBase * _Nullable o1, RLMObjectBase * _Nullable o2);
// Get ObjectUil class for objc or swift
FOUNDATION_EXTERN Class RLMObjectUtilClass(BOOL isSwift);
FOUNDATION_EXTERN const NSUInteger RLMDescriptionMaxDepth;
@class RLMProperty, RLMArray;
@interface RLMObjectUtil : NSObject
+ (nullable NSArray<NSString *> *)ignoredPropertiesForClass:(Class)cls;
+ (nullable NSArray<NSString *> *)indexedPropertiesForClass:(Class)cls;
+ (nullable NSDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *)linkingObjectsPropertiesForClass:(Class)cls;
+ (nullable NSArray<NSString *> *)getGenericListPropertyNames:(id)obj;
+ (nullable NSDictionary<NSString *, NSString *> *)getLinkingObjectsProperties:(id)object;
+ (nullable NSDictionary<NSString *, NSNumber *> *)getOptionalProperties:(id)obj;
+ (nullable NSArray<NSString *> *)requiredPropertiesForClass:(Class)cls;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,58 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMObject_Private.h"
#import "RLMRealm_Private.hpp"
#import "RLMUtil.hpp"
#import <realm/link_view.hpp> // required by row.hpp
#import <realm/row.hpp>
class RLMObservationInfo;
// RLMObject accessor and read/write realm
@interface RLMObjectBase () {
@public
realm::Row _row;
RLMObservationInfo *_observationInfo;
RLMClassInfo *_info;
}
@end
// FIXME-2.0: This should be folded into initWithRealm:schema:, but changing the
// signature of that is a breaking change for Swift
id RLMCreateManagedAccessor(Class cls, RLMRealm *realm, RLMClassInfo *info) NS_RETURNS_RETAINED;
// throw an exception if the object is invalidated or on the wrong thread
static inline void RLMVerifyAttached(__unsafe_unretained RLMObjectBase *const obj) {
if (!obj->_row.is_attached()) {
@throw RLMException(@"Object has been deleted or invalidated.");
}
[obj->_realm verifyThread];
}
// throw an exception if the object can't be modified for any reason
static inline void RLMVerifyInWriteTransaction(__unsafe_unretained RLMObjectBase *const obj) {
// first verify is attached
RLMVerifyAttached(obj);
if (!obj->_realm.inWriteTransaction) {
@throw RLMException(@"Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.");
}
}

View File

@ -1,153 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import "binding_context.hpp"
#import <realm/row.hpp>
#import <realm/table.hpp>
#import <unordered_map>
@class RLMObjectBase, RLMRealm, RLMSchema, RLMProperty, RLMObjectSchema;
class RLMClassInfo;
class RLMSchemaInfo;
namespace realm {
class History;
class SharedGroup;
}
// RLMObservationInfo stores all of the KVO-related data for RLMObjectBase and
// RLMArray. There is a one-to-one relationship between observed objects and
// RLMObservationInfo instances, so it could be folded into RLMObjectBase, and
// is a separate class mostly to avoid making all accessor objects far larger.
//
// RLMClassInfo stores a vector of pointers to the first observation info
// created for each row. If there are multiple observation infos for a single
// row (such as if there are multiple observed objects backed by a single row,
// or if both an object and an array property of that object are observed),
// they're stored in an intrusive doubly-linked-list in the `next` and `prev`
// members. This is done primarily to make it simpler and faster to loop over
// all of the observed objects for a single row, as that needs to be done for
// every change.
class RLMObservationInfo {
public:
RLMObservationInfo(id object);
RLMObservationInfo(RLMClassInfo &objectSchema, std::size_t row, id object);
~RLMObservationInfo();
realm::Row const& getRow() const {
return row;
}
NSString *columnName(size_t col) const noexcept;
// Send willChange/didChange notifications to all observers for this object/row
// Sends the array versions if indexes is non-nil, normal versions otherwise
void willChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const;
void didChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const;
bool isForRow(size_t ndx) const {
return row && row.get_index() == ndx;
}
void recordObserver(realm::Row& row, RLMClassInfo *objectInfo, RLMObjectSchema *objectSchema, NSString *keyPath);
void removeObserver();
bool hasObservers() const { return observerCount > 0; }
// valueForKey: on observed object and array properties needs to return the
// same object each time for KVO to work at all. Doing this all the time
// requires some odd semantics to avoid reference cycles, so instead we do
// it only to the extent specifically required by KVO. In addition, we
// need to continue to return the same object even if this row is deleted,
// or deleting an object with active observers will explode horribly.
// Once prepareForInvalidation() is called, valueForKey() will always return
// the cached value for object and array properties without checking the
// backing row to verify it's up-to-date.
//
// prepareForInvalidation() must be called on the head of the linked list
// (i.e. on the object pointed to directly by the object schema)
id valueForKey(NSString *key);
void prepareForInvalidation();
private:
// Doubly-linked-list of observed objects for the same row as this
RLMObservationInfo *next = nullptr;
RLMObservationInfo *prev = nullptr;
// Row being observed
realm::Row row;
RLMClassInfo *objectSchema = nullptr;
// Object doing the observing
__unsafe_unretained id object = nil;
// valueForKey: hack
bool invalidated = false;
size_t observerCount = 0;
NSString *lastKey = nil;
__unsafe_unretained RLMProperty *lastProp = nil;
// objects returned from valueForKey() to keep them alive in case observers
// are added and so that they can still be accessed after row is detached
NSMutableDictionary *cachedObjects;
void setRow(realm::Table &table, size_t newRow);
template<typename F>
void forEach(F&& f) const {
// The user's observation handler may release their last reference to
// the object being observed, which will result in the RLMObservationInfo
// being destroyed. As a result, we need to retain the object which owns
// both `this` and the current info we're looking at.
__attribute__((objc_precise_lifetime)) id self = object, current;
for (auto info = prev; info; info = info->prev) {
current = info->object;
f(info->object);
}
for (auto info = this; info; info = info->next) {
current = info->object;
f(info->object);
}
}
// Default move/copy constructors don't work due to the intrusive linked
// list and we don't need them
RLMObservationInfo(RLMObservationInfo const&) = delete;
RLMObservationInfo(RLMObservationInfo&&) = delete;
RLMObservationInfo& operator=(RLMObservationInfo const&) = delete;
RLMObservationInfo& operator=(RLMObservationInfo&&) = delete;
};
// Get the the observation info chain for the given row
// Will simply return info if it's non-null, and will search ojectSchema's array
// for a matching one otherwise, and return null if there are none
RLMObservationInfo *RLMGetObservationInfo(RLMObservationInfo *info, size_t row, RLMClassInfo& objectSchema);
// delete all objects from a single table with change notifications
void RLMClearTable(RLMClassInfo &realm);
// invoke the block, sending notifications for cascading deletes/link nullifications
void RLMTrackDeletions(RLMRealm *realm, dispatch_block_t block);
std::vector<realm::BindingContext::ObserverState> RLMGetObservedRows(RLMSchemaInfo const& schema);
void RLMWillChange(std::vector<realm::BindingContext::ObserverState> const& observed, std::vector<void *> const& invalidated);
void RLMDidChange(std::vector<realm::BindingContext::ObserverState> const& observed, std::vector<void *> const& invalidated);

View File

@ -1,38 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMConstants.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMObjectBase, RLMProperty;
@interface RLMOptionalBase : NSProxy
- (instancetype)init;
@property (nonatomic, weak) RLMObjectBase *object;
@property (nonatomic, unsafe_unretained) RLMProperty *property;
@property (nonatomic, strong, nullable) id underlyingValue;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,21 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import <Foundation/Foundation.h>
using ExpressionVisitor = NSExpression *(*)(NSExpression *);
NSPredicate *transformPredicate(NSPredicate *, ExpressionVisitor);

View File

@ -1,35 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
#ifdef __cplusplus
#import <functional>
#import <map>
#import <memory>
#import <string>
#import <vector>
#import <realm/group.hpp>
#import <realm/link_view.hpp>
#import <realm/row.hpp>
#import <realm/table.hpp>
#import <realm/table_view.hpp>
#endif

View File

@ -1,121 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMConstants.h>
NS_ASSUME_NONNULL_BEGIN
/// :nodoc:
@protocol RLMInt
@end
/// :nodoc:
@protocol RLMBool
@end
/// :nodoc:
@protocol RLMDouble
@end
/// :nodoc:
@protocol RLMFloat
@end
/// :nodoc:
@interface NSNumber ()<RLMInt, RLMBool, RLMDouble, RLMFloat>
@end
/**
`RLMProperty` instances represent properties managed by a Realm in the context of an object schema. Such properties may
be persisted to a Realm file or computed from other data from the Realm.
When using Realm, `RLMProperty` instances allow performing migrations and introspecting the database's schema.
These property instances map to columns in the core database.
*/
@interface RLMProperty : NSObject
#pragma mark - Properties
/**
The name of the property.
*/
@property (nonatomic, readonly) NSString *name;
/**
The type of the property.
@see `RLMPropertyType`
*/
@property (nonatomic, readonly) RLMPropertyType type;
/**
Indicates whether this property is indexed.
@see `RLMObject`
*/
@property (nonatomic, readonly) BOOL indexed;
/**
For `RLMObject` and `RLMArray` properties, the name of the class of object stored in the property.
*/
@property (nonatomic, readonly, copy, nullable) NSString *objectClassName;
/**
For linking objects properties, the property name of the property the linking objects property is linked to.
*/
@property (nonatomic, readonly, copy, nullable) NSString *linkOriginPropertyName;
/**
Indicates whether this property is optional.
*/
@property (nonatomic, readonly) BOOL optional;
#pragma mark - Methods
/**
Returns whether a given property object is equal to the receiver.
*/
- (BOOL)isEqualToProperty:(RLMProperty *)property;
@end
/**
An `RLMPropertyDescriptor` instance represents a specific property on a given class.
*/
@interface RLMPropertyDescriptor : NSObject
/**
Creates and returns a property descriptor.
@param objectClass The class of this property descriptor.
@param propertyName The name of this property descriptor.
*/
+ (instancetype)descriptorWithClass:(Class)objectClass propertyName:(NSString *)propertyName;
/// The class of the property.
@property (nonatomic, readonly) Class objectClass;
/// The name of the property.
@property (nonatomic, readonly) NSString *propertyName;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,111 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMProperty.h>
#import <objc/runtime.h>
@class RLMObjectBase;
NS_ASSUME_NONNULL_BEGIN
BOOL RLMPropertyTypeIsNullable(RLMPropertyType propertyType);
BOOL RLMPropertyTypeIsComputed(RLMPropertyType propertyType);
// private property interface
@interface RLMProperty () {
@public
RLMPropertyType _type;
Ivar _swiftIvar;
}
- (instancetype)initWithName:(NSString *)name
indexed:(BOOL)indexed
linkPropertyDescriptor:(nullable RLMPropertyDescriptor *)linkPropertyDescriptor
property:(objc_property_t)property;
- (instancetype)initSwiftPropertyWithName:(NSString *)name
indexed:(BOOL)indexed
linkPropertyDescriptor:(nullable RLMPropertyDescriptor *)linkPropertyDescriptor
property:(objc_property_t)property
instance:(RLMObjectBase *)objectInstance;
- (instancetype)initSwiftListPropertyWithName:(NSString *)name
ivar:(Ivar)ivar
objectClassName:(nullable NSString *)objectClassName;
- (instancetype)initSwiftOptionalPropertyWithName:(NSString *)name
indexed:(BOOL)indexed
ivar:(Ivar)ivar
propertyType:(RLMPropertyType)propertyType;
- (instancetype)initSwiftLinkingObjectsPropertyWithName:(NSString *)name
ivar:(Ivar)ivar
objectClassName:(nullable NSString *)objectClassName
linkOriginPropertyName:(nullable NSString *)linkOriginPropertyName;
// private setters
@property (nonatomic, readwrite) NSString *name;
@property (nonatomic, readwrite, assign) RLMPropertyType type;
@property (nonatomic, readwrite) BOOL indexed;
@property (nonatomic, readwrite) BOOL optional;
@property (nonatomic, copy, nullable) NSString *objectClassName;
// private properties
@property (nonatomic, assign) NSUInteger index;
@property (nonatomic, assign) char objcType;
@property (nonatomic, copy) NSString *objcRawType;
@property (nonatomic, assign) BOOL isPrimary;
@property (nonatomic, assign) Ivar swiftIvar;
// getter and setter names
@property (nonatomic, copy) NSString *getterName;
@property (nonatomic, copy) NSString *setterName;
@property (nonatomic) SEL getterSel;
@property (nonatomic) SEL setterSel;
- (RLMProperty *)copyWithNewName:(NSString *)name;
@end
@interface RLMProperty (Dynamic)
/**
This method is useful only in specialized circumstances, for example, in conjunction with
+[RLMObjectSchema initWithClassName:objectClass:properties:]. If you are simply building an
app on Realm, it is not recommened to use this method.
Initialize an RLMProperty
@warning This method is useful only in specialized circumstances.
@param name The property name.
@param type The property type.
@param objectClassName The object type used for Object and Array types.
@param linkOriginPropertyName The property name of the origin of a link. Used for linking objects properties.
@return An initialized instance of RLMProperty.
*/
- (instancetype)initWithName:(NSString *)name
type:(RLMPropertyType)type
objectClassName:(nullable NSString *)objectClassName
linkOriginPropertyName:(nullable NSString *)linkOriginPropertyName
indexed:(BOOL)indexed
optional:(BOOL)optional;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,29 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMProperty_Private.h>
#import "property.hpp"
@interface RLMProperty ()
+ (instancetype)propertyForObjectStoreProperty:(const realm::Property&)property;
- (realm::Property)objectStoreCopy;
@end

View File

@ -1,42 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <vector>
namespace realm {
class Group;
class Query;
class SortDescriptor;
class Table;
}
@class RLMObjectSchema, RLMProperty, RLMSchema, RLMSortDescriptor;
extern NSString * const RLMPropertiesComparisonTypeMismatchException;
extern NSString * const RLMUnsupportedTypesFoundInPropertyComparisonException;
realm::Query RLMPredicateToQuery(NSPredicate *predicate, RLMObjectSchema *objectSchema,
RLMSchema *schema, realm::Group &group);
// return property - throw for invalid column name
RLMProperty *RLMValidatedProperty(RLMObjectSchema *objectSchema, NSString *columnName);
// validate the array of RLMSortDescriptors and convert it to a realm::SortDescriptor
realm::SortDescriptor RLMSortDescriptorFromDescriptors(realm::Table& table, NSArray<RLMSortDescriptor *> *descriptors);

View File

@ -1,514 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import "RLMConstants.h"
@class RLMRealmConfiguration, RLMObject, RLMSchema, RLMMigration, RLMNotificationToken;
NS_ASSUME_NONNULL_BEGIN
/**
An `RLMRealm` instance (also referred to as "a Realm") represents a Realm
database.
Realms can either be stored on disk (see `+[RLMRealm realmWithURL:]`) or in
memory (see `RLMRealmConfiguration`).
`RLMRealm` instances are cached internally, and constructing equivalent `RLMRealm`
objects (for example, by using the same path or identifier) multiple times on a single thread
within a single iteration of the run loop will normally return the same
`RLMRealm` object.
If you specifically want to ensure an `RLMRealm` instance is
destroyed (for example, if you wish to open a Realm, check some property, and
then possibly delete the Realm file and re-open it), place the code which uses
the Realm within an `@autoreleasepool {}` and ensure you have no other
strong references to it.
@warning `RLMRealm` instances are not thread safe and cannot be shared across
threads or dispatch queues. Trying to do so will cause an exception to be thrown.
You must call this method on each thread you want
to interact with the Realm on. For dispatch queues, this means that you must
call it in each block which is dispatched, as a queue is not guaranteed to run
all of its blocks on the same thread.
*/
@interface RLMRealm : NSObject
#pragma mark - Creating & Initializing a Realm
/**
Obtains an instance of the default Realm.
The default Realm is used by the `RLMObject` class methods
which do not take an `RLMRealm` parameter, but is otherwise not special. The
default Realm is persisted as *default.realm* under the *Documents* directory of
your Application on iOS, and in your application's *Application Support*
directory on OS X.
The default Realm is created using the default `RLMRealmConfiguration`, which
can be changed via `+[RLMRealmConfiguration setDefaultConfiguration:]`.
@return The default `RLMRealm` instance for the current thread.
*/
+ (instancetype)defaultRealm;
/**
Obtains an `RLMRealm` instance with the given configuration.
@param configuration A configuration object to use when creating the Realm.
@param error If an error occurs, upon return contains an `NSError` object
that describes the problem. If you are not interested in
possible errors, pass in `NULL`.
@return An `RLMRealm` instance.
*/
+ (nullable instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error;
/**
Obtains an `RLMRealm` instance persisted at a specified file URL.
@param fileURL The local URL of the file the Realm should be saved at.
@return An `RLMRealm` instance.
*/
+ (instancetype)realmWithURL:(NSURL *)fileURL;
/**
The `RLMSchema` used by the Realm.
*/
@property (nonatomic, readonly) RLMSchema *schema;
/**
Indicates if the Realm is currently engaged in a write transaction.
@warning Do not simply check this property and then start a write transaction whenever an object needs to be
created, updated, or removed. Doing so might cause a large number of write transactions to be created,
degrading performance. Instead, always prefer performing multiple updates during a single transaction.
*/
@property (nonatomic, readonly) BOOL inWriteTransaction;
/**
The `RLMRealmConfiguration` object that was used to create this `RLMRealm` instance.
*/
@property (nonatomic, readonly) RLMRealmConfiguration *configuration;
/**
Indicates if this Realm contains any objects.
*/
@property (nonatomic, readonly) BOOL isEmpty;
#pragma mark - Notifications
/**
The type of a block to run whenever the data within the Realm is modified.
@see `-[RLMRealm addNotificationBlock:]`
*/
typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *realm);
#pragma mark - Receiving Notification when a Realm Changes
/**
Adds a notification handler for changes in this Realm, and returns a notification token.
Notification handlers are called after each write transaction is committed,
either on the current thread or other threads.
Handler blocks are called on the same thread that they were added on, and may only be added on threads which are
currently within a run loop. Unless you are specifically creating and running a run loop on a background thread, this
will normally only be the main thread.
The block has the following definition:
typedef void(^RLMNotificationBlock)(RLMNotification notification, RLMRealm *realm);
It receives the following parameters:
- `NSString` \***notification**: The name of the incoming notification. See
`RLMRealmNotification` for information on what
notifications are sent.
- `RLMRealm` \***realm**: The Realm for which this notification occurred.
@param block A block which is called to process Realm notifications.
@return A token object which must be retained as long as you wish to continue
receiving change notifications.
*/
- (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block __attribute__((warn_unused_result));
#pragma mark - Transactions
#pragma mark - Writing to a Realm
/**
Begins a write transaction on the Realm.
Only one write transaction can be open at a time. Write transactions cannot be
nested, and trying to begin a write transaction on a Realm which is
already in a write transaction will throw an exception. Calls to
`beginWriteTransaction` from `RLMRealm` instances in other threads will block
until the current write transaction completes.
Before beginning the write transaction, `beginWriteTransaction` updates the
`RLMRealm` instance to the latest Realm version, as if `refresh` had been called, and
generates notifications if applicable. This has no effect if the Realm
was already up to date.
It is rarely a good idea to have write transactions span multiple cycles of
the run loop, but if you do wish to do so you will need to ensure that the
Realm participating in the write transaction is kept alive until the write transaction
is committed.
*/
- (void)beginWriteTransaction;
/**
Commits all write operations in the current write transaction, and ends the
transaction.
@warning This method may only be called during a write transaction.
*/
- (void)commitWriteTransaction NS_SWIFT_UNAVAILABLE("");
/**
Commits all write operations in the current write transaction, and ends the
transaction.
@warning This method may only be called during a write transaction.
@param error If an error occurs, upon return contains an `NSError` object
that describes the problem. If you are not interested in
possible errors, pass in `NULL`.
@return Whether the transaction succeeded.
*/
- (BOOL)commitWriteTransaction:(NSError **)error;
/**
Reverts all writes made during the current write transaction and ends the transaction.
This rolls back all objects in the Realm to the state they were in at the
beginning of the write transaction, and then ends the transaction.
This restores the data for deleted objects, but does not revive invalidated
object instances. Any `RLMObject`s which were added to the Realm will be
invalidated rather than becoming unmanaged.
Given the following code:
ObjectType *oldObject = [[ObjectType objectsWhere:@"..."] firstObject];
ObjectType *newObject = [[ObjectType alloc] init];
[realm beginWriteTransaction];
[realm addObject:newObject];
[realm deleteObject:oldObject];
[realm cancelWriteTransaction];
Both `oldObject` and `newObject` will return `YES` for `isInvalidated`,
but re-running the query which provided `oldObject` will once again return
the valid object.
@warning This method may only be called during a write transaction.
*/
- (void)cancelWriteTransaction;
/**
Performs actions contained within the given block inside a write transaction.
@see `[RLMRealm transactionWithBlock:error:]`
*/
- (void)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block NS_SWIFT_UNAVAILABLE("");
/**
Performs actions contained within the given block inside a write transaction.
Write transactions cannot be nested, and trying to execute a write transaction
on a Realm which is already participating in a write transaction will throw an
exception. Calls to `transactionWithBlock:` from `RLMRealm` instances in other
threads will block until the current write transaction completes.
Before beginning the write transaction, `transactionWithBlock:` updates the
`RLMRealm` instance to the latest Realm version, as if `refresh` had been called, and
generates notifications if applicable. This has no effect if the Realm
was already up to date.
@param block The block containing actions to perform.
@param error If an error occurs, upon return contains an `NSError` object
that describes the problem. If you are not interested in
possible errors, pass in `NULL`.
@return Whether the transaction succeeded.
*/
- (BOOL)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block error:(NSError **)error;
/**
Updates the Realm and outstanding objects managed by the Realm to point to the most recent data.
@return Whether there were any updates for the Realm. Note that `YES` may be returned even if no data actually
changed.
*/
- (BOOL)refresh;
/**
Set this property to `YES` to automatically update this Realm when changes happen in other threads.
If set to `YES` (the default), changes made on other threads will be reflected
in this Realm on the next cycle of the run loop after the changes are
committed. If set to `NO`, you must manually call `-refresh` on the Realm to
update it to get the latest data.
Note that by default, background threads do not have an active run loop and you
will need to manually call `-refresh` in order to update to the latest version,
even if `autorefresh` is set to `YES`.
Even with this property enabled, you can still call `-refresh` at any time to update the
Realm before the automatic refresh would occur.
Notifications are sent when a write transaction is committed whether or not
automatic refreshing is enabled.
Disabling `autorefresh` on a Realm without any strong references to it will not
have any effect, and `autorefresh` will revert back to `YES` the next time the Realm is created.
This is normally irrelevant as it means that there is
nothing to refresh (as managed `RLMObject`s, `RLMArray`s, and `RLMResults` have strong
references to the Realm that manages them), but it means that setting
`RLMRealm.defaultRealm.autorefresh = NO` in
`application:didFinishLaunchingWithOptions:` and only later storing Realm
objects will not work.
Defaults to `YES`.
*/
@property (nonatomic) BOOL autorefresh;
/**
Writes a compacted and optionally encrypted copy of the Realm to the given local URL.
The destination file cannot already exist.
Note that if this method is called from within a write transaction, the *current* data is written, not the data from
the point when the previous write transaction was committed.
@param fileURL Local URL to save the Realm to.
@param key Optional 64-byte encryption key to encrypt the new file with.
@param error If an error occurs, upon return contains an `NSError` object
that describes the problem. If you are not interested in
possible errors, pass in `NULL`.
@return `YES` if the Realm was successfully written to disk, `NO` if an error occurred.
*/
- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error;
/**
Invalidates all `RLMObject`s, `RLMResults`, `RLMLinkingObjects`, and `RLMArray`s managed by the Realm.
A Realm holds a read lock on the version of the data accessed by it, so
that changes made to the Realm on different threads do not modify or delete the
data seen by this Realm. Calling this method releases the read lock,
allowing the space used on disk to be reused by later write transactions rather
than growing the file. This method should be called before performing long
blocking operations on a background thread on which you previously read data
from the Realm which you no longer need.
All `RLMObject`, `RLMResults` and `RLMArray` instances obtained from this
`RLMRealm` instance on the current thread are invalidated. `RLMObject`s and `RLMArray`s
cannot be used. `RLMResults` will become empty. The Realm itself remains valid,
and a new read transaction is implicitly begun the next time data is read from the Realm.
Calling this method multiple times in a row without reading any data from the
Realm, or before ever reading any data from the Realm, is a no-op. This method
may not be called on a read-only Realm.
*/
- (void)invalidate;
#pragma mark - Accessing Objects
#pragma mark - Adding and Removing Objects from a Realm
/**
Adds an object to the Realm.
Once added, this object is considered to be managed by the Realm. It can be retrieved
using the `objectsWhere:` selectors on `RLMRealm` and on subclasses of `RLMObject`.
When added, all child relationships referenced by this object will also be added to
the Realm if they are not already in it.
If the object or any related objects are already being managed by a different Realm
an exception will be thrown. Use `-[RLMObject createInRealm:withObject:]` to insert a copy of a managed object
into a different Realm.
The object to be added must be valid and cannot have been previously deleted
from a Realm (i.e. `isInvalidated` must be `NO`).
@warning This method may only be called during a write transaction.
@param object The object to be added to this Realm.
*/
- (void)addObject:(RLMObject *)object;
/**
Adds all the objects in a collection to the Realm.
This is the equivalent of calling `addObject:` for every object in a collection.
@warning This method may only be called during a write transaction.
@param array An enumerable object such as `NSArray` or `RLMResults` which contains objects to be added to
the Realm.
@see `addObject:`
*/
- (void)addObjects:(id<NSFastEnumeration>)array;
/**
Adds or updates an existing object into the Realm.
The object provided must have a designated primary key. If no objects exist in the Realm
with the same primary key value, the object is inserted. Otherwise, the existing object is
updated with any changed values.
As with `addObject:`, the object cannot already be managed by a different
Realm. Use `-[RLMObject createOrUpdateInRealm:withValue:]` to copy values to
a different Realm.
@warning This method may only be called during a write transaction.
@param object The object to be added or updated.
*/
- (void)addOrUpdateObject:(RLMObject *)object;
/**
Adds or updates all the objects in a collection into the Realm.
This is the equivalent of calling `addOrUpdateObject:` for every object in a collection.
@warning This method may only be called during a write transaction.
@param array An `NSArray`, `RLMArray`, or `RLMResults` of `RLMObject`s (or subclasses) to be added to the Realm.
@see `addOrUpdateObject:`
*/
- (void)addOrUpdateObjectsFromArray:(id)array;
/**
Deletes an object from the Realm. Once the object is deleted it is considered invalidated.
@warning This method may only be called during a write transaction.
@param object The object to be deleted.
*/
- (void)deleteObject:(RLMObject *)object;
/**
Deletes one or more objects from the Realm.
This is the equivalent of calling `deleteObject:` for every object in a collection.
@warning This method may only be called during a write transaction.
@param array An `RLMArray`, `NSArray`, or `RLMResults` of `RLMObject`s (or subclasses) to be deleted.
@see `deleteObject:`
*/
- (void)deleteObjects:(id)array;
/**
Deletes all objects from the Realm.
@warning This method may only be called during a write transaction.
@see `deleteObject:`
*/
- (void)deleteAllObjects;
#pragma mark - Migrations
/**
The type of a migration block used to migrate a Realm.
@param migration A `RLMMigration` object used to perform the migration. The
migration object allows you to enumerate and alter any
existing objects which require migration.
@param oldSchemaVersion The schema version of the Realm being migrated.
*/
typedef void (^RLMMigrationBlock)(RLMMigration *migration, uint64_t oldSchemaVersion);
/**
Returns the schema version for a Realm at a given local URL.
@param fileURL Local URL to a Realm file.
@param key 64-byte key used to encrypt the file, or `nil` if it is unencrypted.
@param error If an error occurs, upon return contains an `NSError` object
that describes the problem. If you are not interested in
possible errors, pass in `NULL`.
@return The version of the Realm at `fileURL`, or `RLMNotVersioned` if the version cannot be read.
*/
+ (uint64_t)schemaVersionAtURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error
NS_REFINED_FOR_SWIFT;
/**
Performs the given Realm configuration's migration block on a Realm at the given path.
This method is called automatically when opening a Realm for the first time and does
not need to be called explicitly. You can choose to call this method to control
exactly when and how migrations are performed.
@param configuration The Realm configuration used to open and migrate the Realm.
@return The error that occurred while applying the migration, if any.
@see RLMMigration
*/
+ (nullable NSError *)migrateRealm:(RLMRealmConfiguration *)configuration
__deprecated_msg("Use `performMigrationForConfiguration:error:`") NS_REFINED_FOR_SWIFT;
/**
Performs the given Realm configuration's migration block on a Realm at the given path.
This method is called automatically when opening a Realm for the first time and does
not need to be called explicitly. You can choose to call this method to control
exactly when and how migrations are performed.
@param configuration The Realm configuration used to open and migrate the Realm.
@return The error that occurred while applying the migration, if any.
@see RLMMigration
*/
+ (BOOL)performMigrationForConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error;
@end
/**
A token which is returned from methods which subscribe to changes to a Realm.
Change subscriptions in Realm return an `RLMNotificationToken` instance,
which can be used to unsubscribe from the changes. You must store a strong
reference to the token for as long as you want to continue to receive notifications.
When you wish to stop, call the `-stop` method. Notifications are also stopped if
the token is deallocated.
*/
@interface RLMNotificationToken : NSObject
/// Stops notifications for the change subscription that returned this token.
- (void)stop;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,99 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMRealm.h>
NS_ASSUME_NONNULL_BEGIN
/**
An `RLMRealmConfiguration` instance describes the different options used to
create an instance of a Realm.
`RLMRealmConfiguration` instances are just plain `NSObject`s. Unlike `RLMRealm`s
and `RLMObject`s, they can be freely shared between threads as long as you do not
mutate them.
Creating configuration objects for class subsets (by setting the
`objectClasses` property) can be expensive. Because of this, you will normally want to
cache and reuse a single configuration object for each distinct configuration rather than
creating a new object each time you open a Realm.
*/
@interface RLMRealmConfiguration : NSObject<NSCopying>
#pragma mark - Default Configuration
/**
Returns the default configuration used to create Realms when no other
configuration is explicitly specified (i.e. `+[RLMRealm defaultRealm]`).
@return The default Realm configuration.
*/
+ (instancetype)defaultConfiguration;
/**
Sets the default configuration to the given `RLMRealmConfiguration`.
@param configuration The new default Realm configuration.
*/
+ (void)setDefaultConfiguration:(RLMRealmConfiguration *)configuration;
#pragma mark - Properties
/// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier`.
@property (nonatomic, copy, nullable) NSURL *fileURL;
/// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL`.
@property (nonatomic, copy, nullable) NSString *inMemoryIdentifier;
/// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled.
@property (nonatomic, copy, nullable) NSData *encryptionKey;
/// Whether to open the Realm in read-only mode.
///
/// This is required to be able to open Realm files which are not writeable or
/// are in a directory which is not writeable. This should only be used on files
/// which will not be modified by anyone while they are open, and not just to
/// get a read-only view of a file which may be written to by another thread or
/// process. Opening in read-only mode requires disabling Realm's reader/writer
/// coordination, so committing a write transaction from another process will
/// result in crashes.
@property (nonatomic) BOOL readOnly;
/// The current schema version.
@property (nonatomic) uint64_t schemaVersion;
/// The block which migrates the Realm to the current version.
@property (nonatomic, copy, nullable) RLMMigrationBlock migrationBlock;
/**
Whether to recreate the Realm file with the provided schema if a migration is required.
This is the case when the stored schema differs from the provided schema or
the stored schema version differs from the version on this configuration.
Setting this property to `YES` deletes the file if a migration would otherwise be required or executed.
@note Setting this property to `YES` doesn't disable file format migrations.
*/
@property (nonatomic) BOOL deleteRealmIfMigrationNeeded;
/// The classes managed by the Realm.
@property (nonatomic, copy, nullable) NSArray *objectClasses;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,42 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMRealmConfiguration.h>
@class RLMSchema;
NS_ASSUME_NONNULL_BEGIN
@interface RLMRealmConfiguration ()
@property (nonatomic, readwrite) bool cache;
@property (nonatomic, readwrite) bool dynamic;
@property (nonatomic, readwrite) bool disableFormatUpgrade;
@property (nonatomic, copy, nullable) RLMSchema *customSchema;
// Get the default confiugration without copying it
+ (RLMRealmConfiguration *)rawDefaultConfiguration;
+ (void)resetRealmConfigurationState;
@end
// Get a path in the platform-appropriate documents directory with the given filename
FOUNDATION_EXTERN NSString *RLMRealmPathForFile(NSString *fileName);
FOUNDATION_EXTERN NSString *RLMRealmPathForFileAndBundleIdentifier(NSString *fileName, NSString *mainBundleIdentifier);
NS_ASSUME_NONNULL_END

View File

@ -1,26 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMRealmConfiguration_Private.h"
#import "shared_realm.hpp"
@interface RLMRealmConfiguration ()
- (realm::Realm::Config&)config;
@property (nonatomic) realm::SchemaMode schemaMode;
@end

View File

@ -1,38 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <memory>
#import <string>
@class RLMRealm;
namespace realm {
class BindingContext;
}
// Add a Realm to the weak cache
void RLMCacheRealm(std::string const& path, RLMRealm *realm);
// Get a Realm for the given path which can be used on the current thread
RLMRealm *RLMGetThreadLocalCachedRealmForPath(std::string const& path);
// Get a Realm for the given path
RLMRealm *RLMGetAnyCachedRealmForPath(std::string const& path);
// Clear the weak cache of Realms
void RLMClearRealmCache();
std::unique_ptr<realm::BindingContext> RLMCreateBindingContext(RLMRealm *realm);

View File

@ -1,118 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMRealm.h>
#import <Realm/RLMObjectSchema.h>
#import <Realm/RLMProperty.h>
@class RLMResults;
NS_ASSUME_NONNULL_BEGIN
@interface RLMRealm (Dynamic)
#pragma mark - Getting Objects from a Realm
/**
Returns all objects of a given type from the Realm.
@warning This method is useful only in specialized circumstances, for example, when building components
that integrate with Realm. The preferred way to get objects of a single class is to use the class
methods on `RLMObject`.
@param className The name of the `RLMObject` subclass to retrieve on (e.g. `MyClass.className`).
@return An `RLMResults` containing all objects in the Realm of the given type.
@see `+[RLMObject allObjects]`
*/
- (RLMResults *)allObjects:(NSString *)className;
/**
Returns all objects matching the given predicate from the Realm.
@warning This method is useful only in specialized circumstances, for example, when building components
that integrate with Realm. The preferred way to get objects of a single class is to use the class
methods on `RLMObject`.
@param className The type of objects you are looking for (name of the class).
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return An `RLMResults` containing results matching the given predicate.
@see `+[RLMObject objectsWhere:]`
*/
- (RLMResults *)objects:(NSString *)className where:(NSString *)predicateFormat, ...;
/**
Returns all objects matching the given predicate from the Realm.
@warning This method is useful only in specialized circumstances, for example, when building components
that integrate with Realm. The preferred way to get objects of a single class is to use the class
methods on `RLMObject`.
@param className The type of objects you are looking for (name of the class).
@param predicate The predicate with which to filter the objects.
@return An `RLMResults` containing results matching the given predicate.
@see `+[RLMObject objectsWhere:]`
*/
- (RLMResults *)objects:(NSString *)className withPredicate:(NSPredicate *)predicate;
/**
Returns the object of the given type with the given primary key from the Realm.
@warning This method is useful only in specialized circumstances, for example, when building components
that integrate with Realm. The preferred way to get an object of a single class is to use the class
methods on `RLMObject`.
@param className The class name for the object you are looking for.
@param primaryKey The primary key value for the object you are looking for.
@return An object, or `nil` if an object with the given primary key does not exist.
@see `+[RLMObject objectForPrimaryKey:]`
*/
- (nullable RLMObject *)objectWithClassName:(NSString *)className forPrimaryKey:(id)primaryKey;
/**
Creates an `RLMObject` instance of type `className` in the Realm, and populates it using a given object.
The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or
dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed
property. An exception will be thrown if any required properties are not present and those properties were not defined
with default values.
When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the
properties defined in the model.
@warning This method is useful only in specialized circumstances, for example, when building components
that integrate with Realm. If you are simply building an app on Realm, it is recommended to
use `[RLMObject createInDefaultRealmWithValue:]`.
@param value The value used to populate the object.
@return An `RLMObject` instance of type `className`.
*/
-(RLMObject *)createObject:(NSString *)className withValue:(id)value;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,54 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMRealm.h>
@class RLMFastEnumerator;
NS_ASSUME_NONNULL_BEGIN
// Disable syncing files to disk. Cannot be re-enabled. Use only for tests.
FOUNDATION_EXTERN void RLMDisableSyncToDisk();
FOUNDATION_EXTERN NSData * _Nullable RLMRealmValidatedEncryptionKey(NSData *key);
// Translate an in-flight exception resulting from opening a SharedGroup to
// an NSError or NSException (if error is nil)
void RLMRealmTranslateException(NSError **error);
// RLMRealm private members
@interface RLMRealm ()
@property (nonatomic, readonly) BOOL dynamic;
@property (nonatomic, readwrite) RLMSchema *schema;
+ (void)resetRealmState;
- (void)registerEnumerator:(RLMFastEnumerator *)enumerator;
- (void)unregisterEnumerator:(RLMFastEnumerator *)enumerator;
- (void)detachAllEnumerators;
- (void)sendNotifications:(RLMNotification)notification;
- (void)verifyThread;
- (void)verifyNotificationsAreSupported;
+ (NSString *)writeableTemporaryPathForFile:(NSString *)fileName;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,36 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMRealm_Private.h"
#import "RLMClassInfo.hpp"
namespace realm {
class Group;
class Realm;
}
@interface RLMRealm () {
@public
std::shared_ptr<realm::Realm> _realm;
RLMSchemaInfo _info;
}
// FIXME - group should not be exposed
@property (nonatomic, readonly) realm::Group &group;
@end

View File

@ -1,332 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
#import <Realm/RLMCollection.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMObject, RLMRealm, RLMNotificationToken;
/**
`RLMResults` is an auto-updating container type in Realm returned from object
queries. It represents the results of the query in the form of a collection of objects.
`RLMResults` can be queried using the same predicates as `RLMObject` and `RLMArray`,
and you can chain queries to further filter results.
`RLMResults` always reflect the current state of the Realm on the current thread,
including during write transactions on the current thread. The one exception to
this is when using `for...in` fast enumeration, which will always enumerate
over the objects which matched the query when the enumeration is begun, even if
some of them are deleted or modified to be excluded by the filter during the
enumeration.
`RLMResults` are lazily evaluated the first time they are accessed; they only
run queries when the result of the query is requested. This means that
chaining several temporary `RLMResults` to sort and filter your data does not
perform any extra work processing the intermediate state.
Once the results have been evaluated or a notification block has been added,
the results are eagerly kept up-to-date, with the work done to keep them
up-to-date done on a background thread whenever possible.
`RLMResults` cannot be directly instantiated.
*/
@interface RLMResults<RLMObjectType: RLMObject *> : NSObject<RLMCollection, NSFastEnumeration>
#pragma mark - Properties
/**
The number of objects in the results collection.
*/
@property (nonatomic, readonly, assign) NSUInteger count;
/**
The class name (i.e. type) of the `RLMObject`s contained in the results collection.
*/
@property (nonatomic, readonly, copy) NSString *objectClassName;
/**
The Realm which manages this results collection.
*/
@property (nonatomic, readonly) RLMRealm *realm;
/**
Indicates if the results collection is no longer valid.
The results collection becomes invalid if `invalidate` is called on the containing `realm`.
An invalidated results collection can be accessed, but will always be empty.
*/
@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
#pragma mark - Accessing Objects from an RLMResults
/**
Returns the object at the index specified.
@param index The index to look up.
@return An `RLMObject` of the type contained in the results collection.
*/
- (RLMObjectType)objectAtIndex:(NSUInteger)index;
/**
Returns the first object in the results collection.
Returns `nil` if called on an empty results collection.
@return An `RLMObject` of the type contained in the results collection.
*/
- (nullable RLMObjectType)firstObject;
/**
Returns the last object in the results collection.
Returns `nil` if called on an empty results collection.
@return An `RLMObject` of the type contained in the results collection.
*/
- (nullable RLMObjectType)lastObject;
#pragma mark - Querying Results
/**
Returns the index of an object in the results collection.
Returns `NSNotFound` if the object is not found in the results collection.
@param object An object (of the same type as returned from the `objectClassName` selector).
*/
- (NSUInteger)indexOfObject:(RLMObjectType)object;
/**
Returns the index of the first object in the results collection matching the predicate.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return The index of the object, or `NSNotFound` if the object is not found in the results collection.
*/
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns the index of the first object in the results collection matching the predicate.
@param predicate The predicate with which to filter the objects.
@return The index of the object, or `NSNotFound` if the object is not found in the results collection.
*/
- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate;
/**
Returns all the objects matching the given predicate in the results collection.
@param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
@return An `RLMResults` of objects that match the given predicate.
*/
- (RLMResults<RLMObjectType> *)objectsWhere:(NSString *)predicateFormat, ...;
/// :nodoc:
- (RLMResults<RLMObjectType> *)objectsWhere:(NSString *)predicateFormat args:(va_list)args;
/**
Returns all the objects matching the given predicate in the results collection.
@param predicate The predicate with which to filter the objects.
@return An `RLMResults` of objects that match the given predicate.
*/
- (RLMResults<RLMObjectType> *)objectsWithPredicate:(NSPredicate *)predicate;
/**
Returns a sorted `RLMResults` from an existing results collection.
@param property The property name to sort by.
@param ascending The direction to sort in.
@return An `RLMResults` sorted by the specified property.
*/
- (RLMResults<RLMObjectType> *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending;
/**
Returns a sorted `RLMResults` from an existing results collection.
@param properties An array of `RLMSortDescriptor`s to sort by.
@return An `RLMResults` sorted by the specified properties.
*/
- (RLMResults<RLMObjectType> *)sortedResultsUsingDescriptors:(NSArray *)properties;
#pragma mark - Notifications
/**
Registers a block to be called each time the results collection changes.
The block will be asynchronously called with the initial results collection,
and then called again after each write transaction which changes either any
of the objects in the results, or which objects are in the results.
The `change` parameter will be `nil` the first time the block is called.
For each call after that, it will contain information about
which rows in the results collection were added, removed or modified. If a
write transaction did not modify any objects in the results collection,
the block is not called at all. See the `RLMCollectionChange` documentation for
information on how the changes are reported and an example of updating a
`UITableView`.
If an error occurs the block will be called with `nil` for the results
parameter and a non-`nil` error. Currently the only errors that can occur are
when opening the Realm on the background worker thread.
At the time when the block is called, the `RLMResults` object will be fully
evaluated and up-to-date, and as long as you do not perform a write transaction
on the same thread or explicitly call `-[RLMRealm refresh]`, accessing it will
never perform blocking work.
Notifications are delivered via the standard run loop, and so can't be
delivered while the run loop is blocked by other activity. When
notifications can't be delivered instantly, multiple notifications may be
coalesced into a single notification. This can include the notification
with the initial results. For example, the following code performs a write
transaction immediately after adding the notification block, so there is no
opportunity for the initial notification to be delivered first. As a
result, the initial notification will reflect the state of the Realm after
the write transaction.
RLMResults<Dog *> *results = [Dog allObjects];
NSLog(@"dogs.count: %zu", dogs.count); // => 0
self.token = [results addNotificationBlock:^(RLMResults *dogs,
RLMCollectionChange *changes,
NSError *error) {
// Only fired once for the example
NSLog(@"dogs.count: %zu", dogs.count); // => 1
}];
[realm transactionWithBlock:^{
Dog *dog = [[Dog alloc] init];
dog.name = @"Rex";
[realm addObject:dog];
}];
// end of run loop execution context
You must retain the returned token for as long as you want updates to continue
to be sent to the block. To stop receiving updates, call `-stop` on the token.
@warning This method cannot be called during a write transaction, or when the
containing Realm is read-only.
@param block The block to be called whenever a change occurs.
@return A token which must be held for as long as you want updates to be delivered.
*/
- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMResults<RLMObjectType> *__nullable results,
RLMCollectionChange *__nullable change,
NSError *__nullable error))block __attribute__((warn_unused_result));
#pragma mark - Aggregating Property Values
/**
Returns the minimum (lowest) value of the given property among all the objects
represented by the results collection.
NSNumber *min = [results minOfProperty:@"age"];
@warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties.
@param property The property whose minimum value is desired. Only properties of types `int`, `float`, `double`, and
`NSDate` are supported.
@return The minimum value of the property.
*/
- (nullable id)minOfProperty:(NSString *)property;
/**
Returns the maximum (highest) value of the given property among all the objects represented by the results collection.
NSNumber *max = [results maxOfProperty:@"age"];
@warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties.
@param property The property whose maximum value is desired. Only properties of types `int`, `float`, `double`, and
`NSDate` are supported.
@return The maximum value of the property.
*/
- (nullable id)maxOfProperty:(NSString *)property;
/**
Returns the sum of the values of a given property over all the objects represented by the results collection.
NSNumber *sum = [results sumOfProperty:@"age"];
@warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties.
@param property The property whose values should be summed. Only properties of types `int`, `float`, and `double` are
supported.
@return The sum of the given property.
*/
- (NSNumber *)sumOfProperty:(NSString *)property;
/**
Returns the average value of a given property over the objects represented by the results collection.
NSNumber *average = [results averageOfProperty:@"age"];
@warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties.
@param property The property whose average value should be calculated. Only properties of types `int`, `float`, and
`double` are supported.
@return The average value of the given property. This will be of type `double` for both `float` and `double`
properties.
*/
- (nullable NSNumber *)averageOfProperty:(NSString *)property;
/// :nodoc:
- (RLMObjectType)objectAtIndexedSubscript:(NSUInteger)index;
#pragma mark - Unavailable Methods
/**
`-[RLMResults init]` is not available because `RLMResults` cannot be created directly.
`RLMResults` can be obtained by querying a Realm.
*/
- (instancetype)init __attribute__((unavailable("RLMResults cannot be created directly")));
/**
`+[RLMResults new]` is not available because `RLMResults` cannot be created directly.
`RLMResults` can be obtained by querying a Realm.
*/
+ (instancetype)new __attribute__((unavailable("RLMResults cannot be created directly")));
@end
/**
`RLMLinkingObjects` is an auto-updating container type. It represents a collection of objects that link to its
parent object.
For more information, please see the "Inverse Relationships" section in the
[documentation](https://realm.io/docs/objc/latest/#relationships).
*/
@interface RLMLinkingObjects<RLMObjectType: RLMObject *> : RLMResults
@end
NS_ASSUME_NONNULL_END

View File

@ -1,32 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMResults.h>
@class RLMObjectSchema;
NS_ASSUME_NONNULL_BEGIN
@interface RLMResults ()
@property (nonatomic, readonly, getter=isAttached) BOOL attached;
+ (instancetype)emptyDetachedResults;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,77 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMObjectSchema;
/**
`RLMSchema` instances represent collections of model object schemas managed by a Realm.
When using Realm, `RLMSchema` instances allow performing migrations and
introspecting the database's schema.
Schemas map to collections of tables in the core database.
*/
@interface RLMSchema : NSObject<NSCopying>
#pragma mark - Properties
/**
An `NSArray` containing `RLMObjectSchema`s for all object types in the Realm.
This property is intended to be used during migrations for dynamic introspection.
@see `RLMObjectSchema`
*/
@property (nonatomic, readonly, copy) NSArray<RLMObjectSchema *> *objectSchema;
#pragma mark - Methods
/**
Returns an `RLMObjectSchema` for the given class name in the schema.
@param className The object class name.
@return An `RLMObjectSchema` for the given class in the schema.
@see `RLMObjectSchema`
*/
- (nullable RLMObjectSchema *)schemaForClassName:(NSString *)className;
/**
Looks up and returns an `RLMObjectSchema` for the given class name in the Realm.
If there is no object of type `className` in the schema, an exception will be thrown.
@param className The object class name.
@return An `RLMObjectSchema` for the given class in this Realm.
@see `RLMObjectSchema`
*/
- (RLMObjectSchema *)objectForKeyedSubscript:(NSString *)className;
/**
Returns whether two `RLMSchema` instances are equivalent.
*/
- (BOOL)isEqualToSchema:(RLMSchema *)schema;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,54 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import <Realm/RLMSchema.h>
NS_ASSUME_NONNULL_BEGIN
@class RLMRealm;
//
// RLMSchema private interface
//
@interface RLMSchema ()
/**
Returns an `RLMSchema` containing only the given `RLMObject` subclasses.
@param classes The classes to be included in the schema.
@return An `RLMSchema` containing only the given classes.
*/
+ (instancetype)schemaWithObjectClasses:(NSArray<Class> *)classes;
@property (nonatomic, readwrite, copy) NSArray<RLMObjectSchema *> *objectSchema;
// schema based on runtime objects
+ (instancetype)sharedSchema;
// schema based upon all currently registered object classes
+ (instancetype)partialSharedSchema;
// class for string
+ (nullable Class)classForString:(NSString *)className;
+ (nullable RLMObjectSchema *)sharedSchemaForClass:(Class)cls;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More