Repository: Roobiq/RBQFetchedResultsController Branch: master Commit: 75612dc62756 Files: 155 Total size: 816.5 KB Directory structure: gitextract_mfzjlkfi/ ├── .gitignore ├── .gitmodules ├── .swift-version ├── CHANGELOG.md ├── Cartfile ├── Documentation/ │ └── html/ │ ├── Blocks/ │ │ ├── RBQChangeNotificationBlock.html │ │ └── RBQNotificationBlock.html │ ├── Categories/ │ │ ├── RLMArray+Utilities.html │ │ ├── RLMObject+Notifications.html │ │ ├── RLMObject+SafeObject.html │ │ ├── RLMObject+Utilities.html │ │ └── RLMRealm+Notifications.html │ ├── Classes/ │ │ ├── RBQEntityChangesObject.html │ │ ├── RBQFetchRequest.html │ │ ├── RBQFetchedResultsController.html │ │ ├── RBQFetchedResultsSectionInfo.html │ │ ├── RBQRealmChangeLogger.html │ │ ├── RBQRealmNotificationManager.html │ │ └── RBQSafeRealmObject.html │ ├── Protocols/ │ │ └── RBQFetchedResultsControllerDelegate.html │ ├── css/ │ │ ├── scss/ │ │ │ ├── _index.scss │ │ │ ├── _layout.scss │ │ │ ├── _normalize.scss │ │ │ ├── _object.scss │ │ │ ├── _print.scss │ │ │ ├── _variables.scss │ │ │ ├── _xcode.scss │ │ │ └── style.scss │ │ ├── style.css │ │ ├── styles.css │ │ └── stylesPrint.css │ ├── hierarchy.html │ ├── index.html │ └── js/ │ └── script.js ├── Examples/ │ ├── ObjC/ │ │ ├── Podfile │ │ ├── RBQFetchedResultsControllerExample/ │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.xib │ │ │ │ └── Main.storyboard │ │ │ ├── ExampleTableViewController.h │ │ │ ├── ExampleTableViewController.m │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── TestObject.h │ │ │ ├── TestObject.m │ │ │ └── main.m │ │ ├── RBQFetchedResultsControllerExample.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── RBQFetchedResultsControllerExampleTests/ │ │ ├── Info.plist │ │ ├── RBQFetchRequestInMemoryTests.m │ │ ├── RBQFetchRequestTests.m │ │ ├── RBQFetchedResultsControllerDelegateTests.m │ │ ├── RBQFetchedResultsControllerTests.m │ │ ├── RBQFetchedResultsControllerWithSectionsDelegateTests.m │ │ ├── RBQFetchedResultsSectionInfoTests.m │ │ ├── RBQSafeRealmObjectTests.m │ │ ├── RBQTestCase.h │ │ └── RBQTestCase.m │ ├── ObjC-carthage/ │ │ ├── RBQFetchedResultsControllerExample/ │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.xib │ │ │ │ └── Main.storyboard │ │ │ ├── ExampleTableViewController.h │ │ │ ├── ExampleTableViewController.m │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── TestObject.h │ │ │ ├── TestObject.m │ │ │ └── main.m │ │ ├── RBQFetchedResultsControllerExample.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── RBQFetchedResultsControllerExampleTests/ │ │ └── Info.plist │ ├── ObjC-cocoapods/ │ │ ├── Podfile │ │ ├── RBQFetchedResultsControllerExample/ │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.xib │ │ │ │ └── Main.storyboard │ │ │ ├── ExampleTableViewController.h │ │ │ ├── ExampleTableViewController.m │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── TestObject.h │ │ │ ├── TestObject.m │ │ │ └── main.m │ │ ├── RBQFetchedResultsControllerExample.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── RBQFetchedResultsControllerExampleTests/ │ │ ├── Info.plist │ │ ├── RBQEntityChangesObjectTests.m │ │ ├── RBQFetchRequestInMemoryTests.m │ │ ├── RBQFetchRequestTests.m │ │ ├── RBQFetchedResultsControllerDelegateTests.m │ │ ├── RBQFetchedResultsControllerTests.m │ │ ├── RBQFetchedResultsSectionInfoTests.m │ │ ├── RBQRealmChangeLoggerTests.m │ │ ├── RBQSafeRealmObjectTests.m │ │ ├── RBQTestCase.h │ │ └── RBQTestCase.m │ ├── Swift/ │ │ ├── .swift-version │ │ ├── Podfile │ │ ├── RBQFRCSwiftExample/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.xib │ │ │ │ └── Main.storyboard │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── MainTableViewController.swift │ │ │ └── RBQFRCSwift-BridgingHeader.h │ │ ├── RBQFRCSwiftExample.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── RBQFRCSwiftExampleTests/ │ │ ├── Info.plist │ │ └── RBQFRCSwiftExampleTests.swift │ ├── Swift-carthage/ │ │ ├── RBQFRCSwiftExample/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.xib │ │ │ │ └── Main.storyboard │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── MainTableViewController.swift │ │ ├── RBQFRCSwiftExample.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── RBQFRCSwiftExampleTests/ │ │ ├── Info.plist │ │ └── RBQFRCSwiftExampleTests.swift │ └── Swift-cocoapods/ │ ├── .swift-version │ ├── Podfile │ ├── RBQFRCSwiftExample/ │ │ ├── AppDelegate.swift │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.xib │ │ │ └── Main.storyboard │ │ ├── Images.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── MainTableViewController.swift │ │ └── RBQFRCSwift-BridgingHeader.h │ ├── RBQFRCSwiftExample.xcodeproj/ │ │ └── project.pbxproj │ └── RBQFRCSwiftExampleTests/ │ ├── Info.plist │ └── RBQFRCSwiftExampleTests.swift ├── LICENSE ├── RBQFetchedResultsController/ │ ├── Info.plist │ ├── ModuleMapFile │ ├── RBQFRC.h │ ├── RBQFetchedResultsControllerTests/ │ │ └── Info.plist │ └── Source/ │ ├── CacheObjects/ │ │ ├── RBQControllerCacheObject.h │ │ ├── RBQControllerCacheObject.m │ │ ├── RBQObjectCacheObject.h │ │ ├── RBQObjectCacheObject.m │ │ ├── RBQSectionCacheObject.h │ │ └── RBQSectionCacheObject.m │ ├── RBQFetchRequest.h │ ├── RBQFetchRequest.m │ ├── RBQFetchedResultsController.h │ ├── RBQFetchedResultsController.m │ └── Swift/ │ ├── FetchRequest.swift │ ├── FetchedResultsController.swift │ ├── Info.plist │ ├── RBQFRCSwift-BridgingHeader.h │ ├── SwiftFetchedResultsController.h │ └── Utilities.swift ├── RBQFetchedResultsController.podspec ├── RBQFetchedResultsController.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ ├── RBQFetchedResultsController.xcscheme │ └── SwiftFetchedResultsController.xcscheme ├── README.md └── SwiftFetchedResultsController.podspec ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # macOS .DS_Store # Xcode build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.moved-aside DerivedData *.hmap *.ipa *.resolved *.xcuserstate xcuserdata *.xccheckout *.xcscmblueprint # Only ignore example workspaces Examples/**/*.xcworkspace # Carthage Carthage/ # CocoaPods Podfile.lock Pods/ ================================================ FILE: .gitmodules ================================================ ================================================ FILE: .swift-version ================================================ 3.0.1 ================================================ FILE: CHANGELOG.md ================================================ ## master * Add your own contribution below ## 5.0.0 * Swift 3 - Ben Chatelain #103 ## 4.0.4 ================================================ FILE: Cartfile ================================================ github "realm/realm-cocoa" github "Roobiq/RealmUtilities" github "Roobiq/RBQSafeRealmObject" ================================================ FILE: Documentation/html/Blocks/RBQChangeNotificationBlock.html ================================================ RBQChangeNotificationBlock Block Reference

RBQFetchedResultsController

“Roobiq”

RBQChangeNotificationBlock Block Reference

Declared in RLMObject+Notifications.h
================================================ FILE: Documentation/html/Blocks/RBQNotificationBlock.html ================================================ RBQNotificationBlock Block Reference

RBQFetchedResultsController

“Roobiq”

RBQNotificationBlock Block Reference

Declared in RBQRealmNotificationManager.h
================================================ FILE: Documentation/html/Categories/RLMArray+Utilities.html ================================================ RLMArray(Utilities) Category Reference

RBQFetchedResultsController

“Roobiq”

RLMArray(Utilities) Category Reference

Declared in RLMArray+Utilities.h

Overview

This utility category provides convenience methods on RLMArray.

– containsObject:

Detect if RLMArray contains a given RLMObject

- (BOOL)containsObject:(RLMObject *)anObject

Parameters

anObject

RLMObject

Return Value

YES if RLMArray contains given object

Discussion

Detect if RLMArray contains a given RLMObject

Declared In

RLMArray+Utilities.h

================================================ FILE: Documentation/html/Categories/RLMObject+Notifications.html ================================================ RLMObject(Notifications) Category Reference

RBQFetchedResultsController

“Roobiq”

RLMObject(Notifications) Category Reference

Declared in RLMObject+Notifications.h

Overview

Category on RLMObject that provides convenience methods to change a RLMObject while automatically notifying RBQRealmChangeLogger

– changeWithNotification:

Convenience method that accepts a RBQChangeNotificationBlock, which contains the current RLMObject as a parameter.

- (void)changeWithNotification:(RBQChangeNotificationBlock)block

Parameters

block

Block contains the RLMObject used to call this method. Edit the RLMObject within the block.

Discussion

Convenience method that accepts a RBQChangeNotificationBlock, which contains the current RLMObject as a parameter.

Edit the parameter object in the block and an automatic notification will be generated for RBQRealmChangeLogger

Declared In

RLMObject+Notifications.h

– changeWithNotificationInTransaction:

Convenience method that accepts a RBQChangeNotificationBlock, which contains the current RLMObject as a parameter.

- (void)changeWithNotificationInTransaction:(RBQChangeNotificationBlock)block

Parameters

block

Block contains the RLMObject used to call this method. Edit the RLMObject within the block.

Discussion

Convenience method that accepts a RBQChangeNotificationBlock, which contains the current RLMObject as a parameter.

The block will be run within the required beginWriteTransaction and commitWriteTransaction calls automatically. Edit the parameter object in the block and an automatic notification will be generated for RBQRealmChangeLogger.

Declared In

RLMObject+Notifications.h

================================================ FILE: Documentation/html/Categories/RLMObject+SafeObject.html ================================================ RLMObject(SafeObject) Category Reference

RBQFetchedResultsController

“Roobiq”

RLMObject(SafeObject) Category Reference

Declared in RLMObject+SafeObject.h

Overview

Category methods for RLMObject to convert into a RBQSafeRealmObject and vice versa

+ rbq_objectFromSafeObject:

Create a RLMObject from a RBQSafeRealmObject

+ (instancetype)rbq_objectFromSafeObject:(RBQSafeRealmObject *)safeObject

Parameters

safeObject

RBQSafeRealmObject instance

Return Value

RLMObject of appropriate subtype

Discussion

Create a RLMObject from a RBQSafeRealmObject

Returns nil if the safe object’s className doesn’t match ours.

Declared In

RLMObject+SafeObject.h

+ rbq_objectInRealm:fromSafeObject:

Create a RLMObject in a specific Realm from a RBQSafeRealmObject

+ (instancetype)rbq_objectInRealm:(RLMRealm *)realm fromSafeObject:(RBQSafeRealmObject *)safeObject

Parameters

realm

Realm in which the returned RLMObject is persisted

safeObject

RBQSafeRealmObject to convert into RLMObject

Return Value

RLMObject of appropriate subtype

Discussion

Create a RLMObject in a specific Realm from a RBQSafeRealmObject

Returns nil if the safe object’s className doesn’t match ours.

Declared In

RLMObject+SafeObject.h

– rbq_safeObject

Create a RBQSafeRealmObject from a RLMObject

- (RBQSafeRealmObject *)rbq_safeObject

Return Value

RBQSafeRealmObject which is a thread-safe representation of the original RLMObject

Discussion

Create a RBQSafeRealmObject from a RLMObject

Declared In

RLMObject+SafeObject.h

================================================ FILE: Documentation/html/Categories/RLMObject+Utilities.html ================================================ RLMObject(Utilities) Category Reference

RBQFetchedResultsController

“Roobiq”

RLMObject(Utilities) Category Reference

Declared in RLMObject+Utilities.h

Overview

This utility category provides convenience methods to retrieve the primary key and original class name for an RLMObject.

+ primaryKeyValueForObject:

Retrieve the primary key for a given RLMObject

+ (id)primaryKeyValueForObject:(RLMObject *)object

Parameters

object

RLMObject with a primary key

Return Value

Primary key value (NSInteger or NSString only)

Discussion

Retrieve the primary key for a given RLMObject

Declared In

RLMObject+Utilities.h

+ classNameForObject:

Retrieve the original class name for a generic RLMObject. Realm dynamically changes the class at run-time, whereas this method returns the programatic class name.

+ (NSString *)classNameForObject:(RLMObject *)object

Parameters

object

A RLMObject

Return Value

Original programatic class name

Discussion

Retrieve the original class name for a generic RLMObject. Realm dynamically changes the class at run-time, whereas this method returns the programatic class name.

Warning: This method returns the class name to be used programatically (such as with NSClassFromString()). Class names within Swift follow the pattern: “AppName.ClassName” whereas Obj-C it is simply “ClassName”. See Apple docs for more info: http://apple.co/1HMPGjg

Declared In

RLMObject+Utilities.h

================================================ FILE: Documentation/html/Categories/RLMRealm+Notifications.html ================================================ RLMRealm(Notifications) Category Reference

RBQFetchedResultsController

“Roobiq”

RLMRealm(Notifications) Category Reference

Declared in RLMRealm+Notifications.h

Overview

Category on RLMRealm that provides convenience methods similar to RLMRealm class methods but include notifying RBQRealmNotificationManager

– addObjectWithNotification:

Convenience method to add an object to the Realm and notify RBQRealmChangeLogger

- (void)addObjectWithNotification:(RLMObject *)object

Parameters

object

Standalone RLMObject to be persisted

Discussion

Convenience method to add an object to the Realm and notify RBQRealmChangeLogger

Declared In

RLMRealm+Notifications.h

– addObjectsWithNotification:

Convenience method to add a collection of RLMObjects to the Realm and notify RBQRealmChangeLogger

- (void)addObjectsWithNotification:(id<NSFastEnumeration>)array

Parameters

array

A collection object that conforms to NSFastEnumeration (e.g. NSArray, RLMArray, RLMResults)

Discussion

Convenience method to add a collection of RLMObjects to the Realm and notify RBQRealmChangeLogger

Declared In

RLMRealm+Notifications.h

– addOrUpdateObjectWithNotification:

Convenience method to add or update a RLMObject to the Realm and notify RBQRealmChangeLogger

- (void)addOrUpdateObjectWithNotification:(RLMObject *)object

Parameters

object

RLMObject to add or update in the Realm

Discussion

Convenience method to add or update a RLMObject to the Realm and notify RBQRealmChangeLogger

If the RLMObject is already persisted, then the new object will be used to update the persisted object.

Declared In

RLMRealm+Notifications.h

– addOrUpdateObjectsFromArrayWithNotification:

Convenience method to add or update a collection of RLMObjects to the Realm and notify RBQRealmChangeLogger

- (void)addOrUpdateObjectsFromArrayWithNotification:(id<NSFastEnumeration>)array

Parameters

array

A collection object that conforms to NSFastEnumeration (e.g. NSArray, RLMArray, RLMResults)

Discussion

Convenience method to add or update a collection of RLMObjects to the Realm and notify RBQRealmChangeLogger

If any RLMObject is already persisted, then the new object will be used to update the persisted object.

Declared In

RLMRealm+Notifications.h

– deleteObjectWithNotification:

Convenience method to delete a RLMObject from the Realm and notify RBQRealmChangeLogger

- (void)deleteObjectWithNotification:(RLMObject *)object

Parameters

object

RLMObject to delete from the Realm

Discussion

Convenience method to delete a RLMObject from the Realm and notify RBQRealmChangeLogger

Declared In

RLMRealm+Notifications.h

– deleteObjectsWithNotification:

Convenience method to delete a collection of RLMObjects from the Realm and notify RBQRealmChangeLogger

- (void)deleteObjectsWithNotification:(id<NSFastEnumeration>)array

Parameters

array

A collection object that conforms to NSFastEnumeration (e.g. NSArray, RLMArray, RLMResults)

Discussion

Convenience method to delete a collection of RLMObjects from the Realm and notify RBQRealmChangeLogger

Declared In

RLMRealm+Notifications.h

================================================ FILE: Documentation/html/Classes/RBQEntityChangesObject.html ================================================ RBQEntityChangesObject Class Reference

RBQFetchedResultsController

“Roobiq”

RBQEntityChangesObject Class Reference

Inherits from NSObject
Declared in RBQRealmNotificationManager.h

Overview

Class used by the RBQRealmNotificationManager to represent the change set for a given entity. This object is passed in the NSDictionary (keyed by the entity name) contained in the RBQNotificationBlock after a change to monitored Realm.

  className

The class name of the entity

@property (readonly, nonatomic) NSString *className

Discussion

The class name of the entity

Declared In

RBQRealmNotificationManager.h

  addedSafeObjects

Collection of RBQSafeRealmObjects representing the added objects

@property (readonly, nonatomic) NSSet *addedSafeObjects

Discussion

Collection of RBQSafeRealmObjects representing the added objects

Declared In

RBQRealmNotificationManager.h

  deletedSafeObjects

Collection of RBQSafeRealmObjects representing the deleted objects

@property (readonly, nonatomic) NSSet *deletedSafeObjects

Discussion

Collection of RBQSafeRealmObjects representing the deleted objects

Declared In

RBQRealmNotificationManager.h

  changedSafeObjects

Collection of RBQSafeRealmObjects representing the changed objects

@property (readonly, nonatomic) NSSet *changedSafeObjects

Discussion

Collection of RBQSafeRealmObjects representing the changed objects

Declared In

RBQRealmNotificationManager.h

================================================ FILE: Documentation/html/Classes/RBQFetchRequest.html ================================================ RBQFetchRequest Class Reference

RBQFetchedResultsController

“Roobiq”

RBQFetchRequest Class Reference

Inherits from NSObject
Declared in RBQFetchRequest.h

Overview

This class is used by the RBQFetchedResultsController to represent the properties of the fetch. The RBQFetchRequest is specific to one RLMObject and uses an NSPredicate and array of RLMSortDescriptors to define the query.

  entityName

RLMObject class name for the fetch request

@property (nonatomic, readonly) NSString *entityName

Discussion

RLMObject class name for the fetch request

Declared In

RBQFetchRequest.h

  realm

The Realm in which the entity for the fetch request is persisted.

@property (nonatomic, readonly) RLMRealm *realm

Discussion

The Realm in which the entity for the fetch request is persisted.

Declared In

RBQFetchRequest.h

  realmPath

Path for the Realm associated with the fetch request

@property (nonatomic, readonly) NSString *realmPath

Discussion

Path for the Realm associated with the fetch request

Declared In

RBQFetchRequest.h

  inMemoryRealmId

The identifier of the in-memory Realm.

@property (nonatomic, readonly) NSString *inMemoryRealmId

Discussion

The identifier of the in-memory Realm.

Warning: return nil if fetch request initialized without in-memory Realm

Declared In

RBQFetchRequest.h

  predicate

Predicate supported by Realm

@property (nonatomic, strong) NSPredicate *predicate

Discussion

Predicate supported by Realm

http://realm.io/docs/cocoa/0.89.2/#querying-with-predicates

Declared In

RBQFetchRequest.h

  sortDescriptors

Array of RLMSortDescriptors

@property (nonatomic, strong) NSArray *sortDescriptors

Discussion

Array of RLMSortDescriptors

http://realm.io/docs/cocoa/0.89.2/#ordering-results

Declared In

RBQFetchRequest.h

+ fetchRequestWithEntityName:inRealm:predicate:

Constructor method to create a fetch request for a given entity name in a specific Realm.

+ (RBQFetchRequest *)fetchRequestWithEntityName:(NSString *)entityName inRealm:(RLMRealm *)realm predicate:(NSPredicate *)predicate

Parameters

entityName

Class name for the RLMObject

realm

RLMRealm in which the RLMObject is persisted (if passing in-memory Realm, make sure to keep a strong reference elsewhere since fetch request only stores the path)

predicate

NSPredicate that represents the search query

Return Value

A new instance of RBQFetchRequest

Discussion

Constructor method to create a fetch request for a given entity name in a specific Realm.

Declared In

RBQFetchRequest.h

+ fetchRequestWithEntityName:inMemoryRealm:predicate:

Constructor method to create a fetch request for a given entity name in an in-memory Realm.

+ (RBQFetchRequest *)fetchRequestWithEntityName:(NSString *)entityName inMemoryRealm:(RLMRealm *)inMemoryRealm predicate:(NSPredicate *)predicate

Parameters

entityName

Class name for the RLMObject

inMemoryRealm

In-memory RLMRealm in which the RLMObject is persisted (caller must retain strong reference as fetch request does not)

predicate

NSPredicate that represents the search query

Return Value

A new instance of RBQFetchRequest

Discussion

Constructor method to create a fetch request for a given entity name in an in-memory Realm.

Declared In

RBQFetchRequest.h

– fetchObjects

Retrieve all the RLMObjects for this fetch request in its realm.

- (RLMResults *)fetchObjects

Return Value

RLMResults for all the objects in the fetch request (not thread-safe).

Discussion

Retrieve all the RLMObjects for this fetch request in its realm.

Declared In

RBQFetchRequest.h

– fetchObjectsInRealm:

Retrieve all the RLMObjects for this fetch request in the specified realm.

- (RLMResults *)fetchObjectsInRealm:(RLMRealm *)realm

Parameters

realm

RLMRealm in which the RLMObjects are persisted

Return Value

RLMResults for all the objects in the fetch request (not thread-safe).

Discussion

Retrieve all the RLMObjects for this fetch request in the specified realm.

Declared In

RBQFetchRequest.h

– evaluateObject:

Should this object be in our fetch results?

- (BOOL)evaluateObject:(RLMObject *)object

Parameters

object

Realm object of appropriate type

Return Value

YES if performing fetch would include this object

Discussion

Should this object be in our fetch results?

Intended to be used by the RBQFetchedResultsController to evaluate incremental changes. For simple fetch requests this just evaluates the NSPredicate, but subclasses may have a more complicated implementaiton.

Declared In

RBQFetchRequest.h

– initWithEntityName:inRealm:

Create RBQFetchRequest in RLMRealm instance with an entity name

- (instancetype)initWithEntityName:(NSString *)entityName inRealm:(RLMRealm *)realm

Parameters

entityName

Class name for the RLMObject

realm

RLMRealm in which the RLMObject is persisted

Return Value

A new instance of RBQFetchRequest

Discussion

Create RBQFetchRequest in RLMRealm instance with an entity name

Declared In

RBQFetchRequest.h

================================================ FILE: Documentation/html/Classes/RBQFetchedResultsController.html ================================================ RBQFetchedResultsController Class Reference

RBQFetchedResultsController

“Roobiq”

RBQFetchedResultsController Class Reference

Inherits from NSObject
Declared in RBQFetchedResultsController.h

Overview

The class is used to monitor changes from a RBQRealmNotificationManager to convert these changes into specific index path or section index changes. Typically this is used to back a UITableView and support animations when items are inserted, deleted, or changed.

  fetchRequest

The fetch request for the controller

@property (nonatomic, readonly) RBQFetchRequest *fetchRequest

Discussion

The fetch request for the controller

Declared In

RBQFetchedResultsController.h

  sectionNameKeyPath

The section name key path used to create the sections. Can be nil if no sections.

@property (nonatomic, readonly) NSString *sectionNameKeyPath

Discussion

The section name key path used to create the sections. Can be nil if no sections.

Declared In

RBQFetchedResultsController.h

  delegate

The delegate to pass the index path and section changes to.

@property (nonatomic, weak) id<RBQFetchedResultsControllerDelegate> delegate

Discussion

The delegate to pass the index path and section changes to.

Declared In

RBQFetchedResultsController.h

  cacheName

The name of the cache used internally to represent the tableview structure.

@property (nonatomic, readonly) NSString *cacheName

Discussion

The name of the cache used internally to represent the tableview structure.

Declared In

RBQFetchedResultsController.h

  fetchedObjects

All the objects that match the fetch request.

@property (nonatomic, readonly) RLMResults *fetchedObjects

Discussion

All the objects that match the fetch request.

Declared In

RBQFetchedResultsController.h

+ deleteCacheWithName:

Deletes the cached section information with the given name

+ (void)deleteCacheWithName:(NSString *)name

Parameters

name

The name of the cache file to delete. If name is nil, deletes all cache files.

Discussion

Deletes the cached section information with the given name

If name is not nil, then the cache will be cleaned, but not deleted from disk.

If name is nil, then all caches will be deleted by removing the files from disk.

Warning: If clearing all caches (name is nil), it is recommended to do this in didFinishLaunchingWithOptions: in AppDelegate because RLMRealm files cannot be deleted from disk safely, if there are strong references to them.

Declared In

RBQFetchedResultsController.h

+ allCacheRealmPaths

Retrieves all the paths for the Realm files being used as FRC caches on disk.

+ (NSArray *)allCacheRealmPaths

Return Value

NSArray of NSStrings representing the paths on disk for all FRC cache Realm files

Discussion

Retrieves all the paths for the Realm files being used as FRC caches on disk.

The typical use case for this method is to use the paths to perform migrations in AppDelegate. The FRC cache files need to be migrated along with your other Realm files because by default Realm includes all of the properties defined in your model in all Realm files. Thus the FRC cache files will throw an exception if they are not migrated. Call setSchemaVersion:forRealmAtPath:withMigrationBlock: for each path returned in the array.

Declared In

RBQFetchedResultsController.h

– initWithFetchRequest:sectionNameKeyPath:cacheName:

Constructor method to initialize the controller

- (id)initWithFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)name

Parameters

fetchRequest

the RBQFetchRequest for the controller

sectionNameKeyPath

A key path on result objects that returns the section name. Pass nil to indicate that the controller should generate a single section. If this key path is not the same as that specified by the first sort descriptor in fetchRequest, they must generate the same relative orderings.

name

the cache name (if nil, cache will not be persisted and built using an in-memory Realm)

Return Value

A new instance of RBQFetchedResultsController

Discussion

Constructor method to initialize the controller

Warning: Specify a cache name if deletion of the cache later on is necessary

Declared In

RBQFetchedResultsController.h

– initWithFetchRequest:sectionNameKeyPath:inMemoryRealmCache:

Constructor method to initialize the controller using an explicit in-memory Realm rather than the persisted cache.

- (id)initWithFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath inMemoryRealmCache:(RLMRealm *)inMemoryRealm

Parameters

fetchRequest

the RBQFetchRequest for the controller

sectionNameKeyPath

the section name key path used to create sections (can be nil)

inMemoryRealm

the in-memory Realm to be used for the internal cache

Return Value

A new instance of RBQFetchedResultsController

Discussion

Constructor method to initialize the controller using an explicit in-memory Realm rather than the persisted cache.

Warning: This should only be used if access to the in-memory Realm for the cache instance is necessary. initWithFetchRequest:sectionNameKeyPath:cacheName will internally use an in-memory cache if cacheName is nil

Declared In

RBQFetchedResultsController.h

– performFetch

Method to tell the controller to perform the fetch

- (BOOL)performFetch

Return Value

Indicates if the fetch was successful

Discussion

Method to tell the controller to perform the fetch

Declared In

RBQFetchedResultsController.h

– reset

Call this method to force the cache to be rebuilt.

- (void)reset

Discussion

Call this method to force the cache to be rebuilt.

A potential use case would be to call this in a @catch after trying to call endUpdates for the table view. If an exception is thrown, then the cache will be rebuilt and you can call reloadData on the table view.

Declared In

RBQFetchedResultsController.h

– numberOfRowsForSectionIndex:

Method to retrieve the number of rows for a given section index

- (NSInteger)numberOfRowsForSectionIndex:(NSInteger)index

Parameters

index

section index

Return Value

number of rows in the section

Discussion

Method to retrieve the number of rows for a given section index

Declared In

RBQFetchedResultsController.h

– numberOfSections

Method to retrieve the number of sections represented by the fetch request

- (NSInteger)numberOfSections

Return Value

number of sections

Discussion

Method to retrieve the number of sections represented by the fetch request

Declared In

RBQFetchedResultsController.h

– titleForHeaderInSection:

Method to retrieve the title for a given section index

- (NSString *)titleForHeaderInSection:(NSInteger)section

Parameters

section

section index

Return Value

The title of the section

Discussion

Method to retrieve the title for a given section index

Declared In

RBQFetchedResultsController.h

– sectionIndexForSectionName:

Method to retrieve the section index given a section name

- (NSUInteger)sectionIndexForSectionName:(NSString *)sectionName

Parameters

sectionName

the name of the section

Return Value

the index of the section (returns NSNotFound if no section with the given name)

Discussion

Method to retrieve the section index given a section name

Warning: Returns NSNotFound if there is not a section with the given name

Declared In

RBQFetchedResultsController.h

– safeObjectAtIndexPath:

Retrieve the RBQSafeRealmObject for a given index path

- (RBQSafeRealmObject *)safeObjectAtIndexPath:(NSIndexPath *)indexPath

Parameters

indexPath

the index path of the object

Return Value

RBQSafeRealmObject

Discussion

Retrieve the RBQSafeRealmObject for a given index path

Declared In

RBQFetchedResultsController.h

– objectAtIndexPath:

Retrieve the RLMObject for a given index path

- (id)objectAtIndexPath:(NSIndexPath *)indexPath

Parameters

indexPath

the index path of the object

Return Value

RLMObject

Discussion

Retrieve the RLMObject for a given index path

Warning: Returned object is not thread-safe.

Declared In

RBQFetchedResultsController.h

– objectInRealm:atIndexPath:

Retrieve the RLMObject in a specific Realm for a given index path

- (id)objectInRealm:(RLMRealm *)realm atIndexPath:(NSIndexPath *)indexPath

Parameters

realm

the Realm in which the RLMObject is persisted

indexPath

the index path of the object

Return Value

RLMObject

Discussion

Retrieve the RLMObject in a specific Realm for a given index path

Declared In

RBQFetchedResultsController.h

– indexPathForSafeObject:

Retrieve the index path for a safe object in the fetch request

- (NSIndexPath *)indexPathForSafeObject:(RBQSafeRealmObject *)safeObject

Parameters

safeObject

RBQSafeRealmObject

Return Value

index path of the object

Discussion

Retrieve the index path for a safe object in the fetch request

Declared In

RBQFetchedResultsController.h

– indexPathForObject:

Retrieve the index path for a RLMObject in the fetch request

- (NSIndexPath *)indexPathForObject:(RLMObject *)object

Parameters

object

RLMObject

Return Value

index path of the object

Discussion

Retrieve the index path for a RLMObject in the fetch request

Declared In

RBQFetchedResultsController.h

– updateFetchRequest:sectionNameKeyPath:andPeformFetch:

Convenience method to safely update the fetch request for an existing RBQFetchResultsController

- (void)updateFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath andPeformFetch:(BOOL)performFetch

Parameters

fetchRequest

a new instance of RBQFetchRequest

sectionNameKeyPath

the section name key path for this fetch request (if nil, no sections will be shown)

performFetch

indicates whether you want to immediately performFetch using the new fetch request to rebuild the cache

Discussion

Convenience method to safely update the fetch request for an existing RBQFetchResultsController

Declared In

RBQFetchedResultsController.h

================================================ FILE: Documentation/html/Classes/RBQFetchedResultsSectionInfo.html ================================================ RBQFetchedResultsSectionInfo Class Reference

RBQFetchedResultsController

“Roobiq”

RBQFetchedResultsSectionInfo Class Reference

Inherits from NSObject
Declared in RBQFetchedResultsController.h

Overview

This class is used by the RBQFetchedResultsController to pass along section info.

  numberOfObjects

The number of objects in the section.

@property (nonatomic, readonly) NSUInteger numberOfObjects

Discussion

The number of objects in the section.

Declared In

RBQFetchedResultsController.h

  objects

The objects in the section (generated on-demand and not thread-safe).

@property (nonatomic, readonly) RLMResults *objects

Discussion

The objects in the section (generated on-demand and not thread-safe).

Declared In

RBQFetchedResultsController.h

  name

The name of the section.

@property (nonatomic, readonly) NSString *name

Discussion

The name of the section.

Declared In

RBQFetchedResultsController.h

================================================ FILE: Documentation/html/Classes/RBQRealmChangeLogger.html ================================================ RBQRealmChangeLogger Class Reference

RBQFetchedResultsController

“Roobiq”

RBQRealmChangeLogger Class Reference

Inherits from NSObject
Declared in RBQRealmNotificationManager.h

Overview

This class is used to track changes to a given RLMRealm. Since Realm doesn’t support automatic change tracking, this class allows the developer to log object changes, which will be passed along to the RBQRealmNotificationManager who in turn broadcasts it to any listeners

Since RLMObjects are not thread-safe, when an object is logged to the manager, it is internally transformed into an RBQSafeRealmObject that is thread-safe and this will then be passed to any listeners once the Realm being monitored updates.

Warning: Only RLMObjects with primary keys can be logged because the primary key is required to create a RBQSafeRealmObject.

+ defaultLogger

Creates or retrieves the logger instance for the default Realm on the current thread

+ (instancetype)defaultLogger

Return Value

Instance of RBQRealmChangeLogger

Discussion

Creates or retrieves the logger instance for the default Realm on the current thread

Declared In

RBQRealmNotificationManager.h

+ loggerForRealm:

Creates or retrieves the logger instance for a specific Realm on the current thread

+ (instancetype)loggerForRealm:(RLMRealm *)realm

Parameters

realm

A RLMRealm instance

Return Value

Instance of RBQRealmChangeLogger

Discussion

Creates or retrieves the logger instance for a specific Realm on the current thread

Declared In

RBQRealmNotificationManager.h

– didAddObject:

Register an addition for a given RLMObject

- (void)didAddObject:(RLMObject *)addedObject

Parameters

addedObject

Added RLMObject

Discussion

Register an addition for a given RLMObject

Warning: Can be called before or after the addition to Realm

Declared In

RBQRealmNotificationManager.h

– didAddObjects:

Register a collection of RLMObject additions

- (void)didAddObjects:(id<NSFastEnumeration>)addedObjects

Parameters

addedObjects

RLMArray, RLMResults, NSSet, or NSArray of added RLMObjects

Discussion

Register a collection of RLMObject additions

Warning: Can be called before or after the additions to Realm

Declared In

RBQRealmNotificationManager.h

– willDeleteObject:

Register a delete for a given RLMObject

- (void)willDeleteObject:(RLMObject *)deletedObject

Parameters

deletedObject

To be deleted RLMObject

Discussion

Register a delete for a given RLMObject

Warning: Must be called before the delete in Realm (since the RLMObject will then be invalidated).

Declared In

RBQRealmNotificationManager.h

– willDeleteObjects:

Register a collection of RLMObject deletes

- (void)willDeleteObjects:(id<NSFastEnumeration>)deletedObjects

Parameters

deletedObjects

RLMArray, RLMResults, NSSet, or NSArray of deleted RLMObjects

Discussion

Register a collection of RLMObject deletes

Warning: Must be called before the delete in Realm (since the RLMObject will then be invalidated).

Declared In

RBQRealmNotificationManager.h

– didChangeObject:

Register a change for a given RLMObject

- (void)didChangeObject:(RLMObject *)changedObject

Parameters

changedObject

Changed RLMObject

Discussion

Register a change for a given RLMObject

Warning: Can be called before or after change to Realm

Declared In

RBQRealmNotificationManager.h

– didChangeObjects:

Register a collection of RLMObject changes

- (void)didChangeObjects:(id<NSFastEnumeration>)changedObjects

Parameters

changedObjects

RLMArray, RLMResults, NSSet, or NSArray of changed RLMObjects

Discussion

Register a collection of RLMObject changes

Warning: Can be called before or after change to Realm

Declared In

RBQRealmNotificationManager.h

– didAddObjects:willDeleteObjects:didChangeObjects:

Convenience method to pass array of objects changed. Will ignore nil values;

- (void)didAddObjects:(id<NSFastEnumeration>)addedObjects willDeleteObjects:(id<NSFastEnumeration>)deletedObjects didChangeObjects:(id<NSFastEnumeration>)changedObjects

Parameters

addedObjects

RLMArray, RLMResults, NSSet, or NSArray of added RLMObjects

deletedObjects

RLMArray, RLMResults, NSSet, or NSArray of deleted RLMObjects

changedObjects

RLMArray, RLMResults, NSSet, or NSArray of changed RLMObjects

Discussion

Convenience method to pass array of objects changed. Will ignore nil values;

Declared In

RBQRealmNotificationManager.h

================================================ FILE: Documentation/html/Classes/RBQRealmNotificationManager.html ================================================ RBQRealmNotificationManager Class Reference

RBQFetchedResultsController

“Roobiq”

RBQRealmNotificationManager Class Reference

Inherits from NSObject
Declared in RBQRealmNotificationManager.h

Overview

This class works in conjunction with any instances of RBQRealmChangeLogger to broadcast any changes to the registered listeners

  entityChanges

Current representation of changes logged to the RBQRealmNotificationManager instance.

@property (readonly, nonatomic) NSDictionary *entityChanges

Discussion

Current representation of changes logged to the RBQRealmNotificationManager instance.

Declared In

RBQRealmNotificationManager.h

+ defaultManager

Retrieve the singleton RBQRealmNotificationManager that passes changes from all Realm loggers

+ (instancetype)defaultManager

Return Value

Singleton RBQRealmNotificationManager

Discussion

Retrieve the singleton RBQRealmNotificationManager that passes changes from all Realm loggers

Declared In

RBQRealmNotificationManager.h

– addNotificationBlock:

Use this method to add a notification block that will fire every time the Realm for this RBQNotificationManager updates. The block passes the changes from the Realm update that were logged to the RBQRealmNotificationManager.

- (RBQNotificationToken *)addNotificationBlock:(RBQNotificationBlock)block

Parameters

block

RBQNotificationBlock that passes a NSDictionary keyed by entity name. The object for the key is a RBQEntityChangesObject which contains NSSets of all the various changes to the entity.

Return Value

A new instance of RBQNotificationToken.

Discussion

Use this method to add a notification block that will fire every time the Realm for this RBQNotificationManager updates. The block passes the changes from the Realm update that were logged to the RBQRealmNotificationManager.

Warning: You must hold onto a strong reference to the returned token or it will be deallocated, preventing any changes from propogating.

Declared In

RBQRealmNotificationManager.h

– removeNotification:

De-register a notification given a RBQNotificationToken.

- (void)removeNotification:(RBQNotificationToken *)token

Parameters

token

The RBQNotificationToken to be de-registered.

Discussion

De-register a notification given a RBQNotificationToken.

Declared In

RBQRealmNotificationManager.h

================================================ FILE: Documentation/html/Classes/RBQSafeRealmObject.html ================================================ RBQSafeRealmObject Class Reference

RBQFetchedResultsController

“Roobiq”

RBQSafeRealmObject Class Reference

Inherits from NSObject
Conforms to NSCopying
Declared in RBQSafeRealmObject.h

Overview

An RBQSafeRealmObject acts as a thread-safe representation of a RLMObject.

Warning: RBQSafeRealmObjects can only be created from RLMObjects that contain a primary key. Attempting to create a RBQSafeRealmObject without a primary key will result in an exception.

  className

Original RLMObject’s class name

@property (nonatomic, readonly) NSString *className

Discussion

Original RLMObject’s class name

Declared In

RBQSafeRealmObject.h

  primaryKeyValue

Original RLMObject’s primary key value

@property (nonatomic, readonly) id primaryKeyValue

Discussion

Original RLMObject’s primary key value

Declared In

RBQSafeRealmObject.h

  primaryKeyType

Original RLMObject’s primary key property

@property (nonatomic, readonly) RLMPropertyType primaryKeyType

Discussion

Original RLMObject’s primary key property

Declared In

RBQSafeRealmObject.h

  realm

The Realm in which this object is persisted

@property (nonatomic, readonly) RLMRealm *realm

Discussion

The Realm in which this object is persisted

Declared In

RBQSafeRealmObject.h

– initWithClassName:primaryKeyValue:primaryKeyType:realm:

Constructor method to create an instance of RBQSafeRealmObject

- (id)initWithClassName:(NSString *)className primaryKeyValue:(id)primaryKeyValue primaryKeyType:(RLMPropertyType)primaryKeyType realm:(RLMRealm *)realm

Parameters

className

class name for the original RLMObject

primaryKeyValue

primary key value for the original RLMObject

primaryKeyType

primary key type for the original RLMObject

realm

Realm in which the original RLMObject is persisted

Return Value

A new instance of RBQSafeRealmObject

Discussion

Constructor method to create an instance of RBQSafeRealmObject

Declared In

RBQSafeRealmObject.h

+ safeObjectFromObject:

Create a RBQSafeObject from a RLMObject

+ (instancetype)safeObjectFromObject:(RLMObject *)object

Parameters

object

The RLMObject to transform into RBQSafeObject

Return Value

RBQSafeObject which is a thread-safe

Discussion

Create a RBQSafeObject from a RLMObject

Declared In

RBQSafeRealmObject.h

+ objectfromSafeObject:

Create a RLMObject from a RBQSafeObject

+ (id)objectfromSafeObject:(RBQSafeRealmObject *)safeObject

Parameters

safeObject

RBQSafeRealmObject instance

Return Value

RLMObject (not thread-safe)

Discussion

Create a RLMObject from a RBQSafeObject

Declared In

RBQSafeRealmObject.h

+ objectInRealm:fromSafeObject:

Create a RLMObject in a specific Realm from a RBQSafeObject

+ (id)objectInRealm:(RLMRealm *)realm fromSafeObject:(RBQSafeRealmObject *)safeObject

Parameters

realm

Realm in which the returned RLMObject is persisted

safeObject

RBQSafeRealm object to convert into RLMObject

Return Value

Converted RLMObject

Discussion

Create a RLMObject in a specific Realm from a RBQSafeObject

Declared In

RBQSafeRealmObject.h

– RLMObject

Quickly convert a RBQSafeRealm object into its RLMObject

- (id)RLMObject

Return Value

RLMObject

Discussion

Quickly convert a RBQSafeRealm object into its RLMObject

Declared In

RBQSafeRealmObject.h

– isEqualToObject:

Equality test for RBQSafeObject

- (BOOL)isEqualToObject:(RBQSafeRealmObject *)object

Parameters

object

RBQSafeRealmObject to compare

Return Value

YES if both objects contain the same primary key

Discussion

Equality test for RBQSafeObject

Declared In

RBQSafeRealmObject.h

================================================ FILE: Documentation/html/Protocols/RBQFetchedResultsControllerDelegate.html ================================================ RBQFetchedResultsControllerDelegate Protocol Reference

RBQFetchedResultsController

“Roobiq”

RBQFetchedResultsControllerDelegate Protocol Reference

Conforms to NSObject
Declared in RBQFetchedResultsController.h

Overview

Delegate to pass along the changes identified by the RBQFetchedResultsController.

– controllerWillChangeContent:

Indicates that the controller has started identifying changes.

- (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller

Parameters

controller

controller instance that noticed the change on its fetched objects

Discussion

Indicates that the controller has started identifying changes.

Declared In

RBQFetchedResultsController.h

– controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

Notifies the delegate that a fetched object has been changed due to an add, remove, move, or update. Enables RBQFetchedResultsController change tracking.

- (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath

Parameters

controller

controller instance that noticed the change on its fetched objects

anObject

changed object represented as a RBQSafeRealmObject for thread safety

indexPath

indexPath of changed object (nil for inserts)

type

indicates if the change was an insert, delete, move, or update

newIndexPath

the destination path for inserted or moved objects, nil otherwise

Discussion

Notifies the delegate that a fetched object has been changed due to an add, remove, move, or update. Enables RBQFetchedResultsController change tracking.

Changes are reported with the following heuristics:

On add and remove operations, only the added/removed object is reported. It’s assumed that all objects that come after the affected object are also moved, but these moves are not reported.

A move is reported when the changed attribute on the object is one of the sort descriptors used in the fetch request. An update of the object is assumed in this case, but no separate update message is sent to the delegate.

An update is reported when an object’s state changes, but the changed attributes aren’t part of the sort keys.

Declared In

RBQFetchedResultsController.h

– controller:didChangeSection:atIndex:forChangeType:

The fetched results controller reports changes to its section before changes to the fetched result objects.

- (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(RBQFetchedResultsSectionInfo *)section atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

Parameters

controller

controller controller instance that noticed the change on its fetched objects

section

changed section represented as a RBQFetchedResultsSectionInfo object

sectionIndex

the section index of the changed section

type

indicates if the change was an insert or delete

Discussion

The fetched results controller reports changes to its section before changes to the fetched result objects.

Declared In

RBQFetchedResultsController.h

– controllerDidChangeContent:

This method is called at the end of processing changes by the controller

- (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller

Parameters

controller

controller instance that noticed the change on its fetched objects

Discussion

This method is called at the end of processing changes by the controller

Declared In

RBQFetchedResultsController.h

================================================ FILE: Documentation/html/css/scss/_index.scss ================================================ .index-container { display: flex; flex-direction: row; flex-wrap: wrap; @media (max-width: $mobile-max-width) { flex-direction: column; } .index-column { flex: 1 1 33%; } } ================================================ FILE: Documentation/html/css/scss/_layout.scss ================================================ * { box-sizing: border-box; } .clear { clear: both; } .clearfix { &:before, &:after { clear: both; display: table; content: ""; } } .xcode .hide-in-xcode { display: none; } body { font: 62.5% $body-font; background: $body-background; } h1, h2, h3 { font-weight: 300; color: #808080; } h1 { font-size: 2em; color: #000; } h4 { font-size: 13px; line-height: 1.5; margin: 21px 0 0 0; } a { color: $tint-color; text-decoration: none; } pre, code { font-family: $code-font; word-wrap: break-word; } pre > code, .method-declaration code { display: inline-block; font-size: .85em; padding: 4px 0 4px 10px; border-left: 5px solid rgba(0, 155, 51, .2); &:before { content: "Objective-C"; display: block; font: 9px/1 $body-font; color: #009b33; text-transform: uppercase; letter-spacing: 2px; padding-bottom: 6px; } } pre > code { font-size: inherit; } table, th, td { border: 1px solid #e9e9e9; } table { width: 100%; } th, td { padding: 7px; > :first-child { margin-top: 0; } > :last-child { margin-bottom: 0; } } .container { @extend .clearfix; max-width: 980px; padding: 0 10px; margin: 0 auto; @media (max-width: $mobile-max-width) { padding: 0; } } header { position: fixed; top: 0; left: 0; width: 100%; z-index: 2; background: #414141; color: #fff; font-size: 1.1em; line-height: 25px; letter-spacing: .05em; #library-title { float: left; } #developer-home { float: right; } h1 { font-size: inherit; font-weight: inherit; margin: 0; } p { margin: 0; } h1, a { color: inherit; } @media (max-width: $mobile-max-width) { position: absolute; .container { padding: 0 10px; } } } aside { position: fixed; top: 25px; left: 0; width: 100%; height: 25px; z-index: 2; font-size: 1.1em; @media (max-width: $mobile-max-width) { position: absolute; } #header-buttons { background: rgba(255, 255, 255, .8); margin: 0 1px; padding: 0; list-style: none; text-align: right; line-height: 32px; li { display: inline-block; cursor: pointer; padding: 0 10px; } label, select { cursor: inherit; } #on-this-page { position: relative; .chevron { display: inline-block; width: 14px; height: 4px; position: relative; .chevy { background: #878787; height: 2px; position: absolute; width: 10px; &.chevron-left { left: 0; transform: rotateZ(45deg) scale(0.6); } &.chevron-right { right: 0; transform: rotateZ(-45deg) scale(0.6); } } } #jump-to { opacity: 0; font-size: 16px; position: absolute; top: 5px; left: 0; width: 100%; height: 100%; } } } } article { margin-top: 25px; #content { @extend .clearfix; background: $content-background; border: 1px solid $content-border; padding: 15px 25px 30px 25px; font-size: 1.4em; line-height: 1.45; position: relative; @media (max-width: $mobile-max-width) { padding: 15px 10px 20px 10px; } .navigation-top { position: absolute; top: 15px; right: 25px; } .title { margin: 21px 0 0 0; padding: 15px 0; } p { color: #414141; margin: 0 0 15px 0; } th, td { p:last-child { margin-bottom: 0; } } main { ul { list-style: none; margin-left: 24px; margin-bottom: 12px; padding: 0; li { position: relative; padding-left: 1.3em; &:before { content: "\02022"; color: #414141; font-size: 1.08em; line-height: 1; position: absolute; left: 0; padding-top: 2px; } } } } footer { @extend .clearfix; .footer-copyright { margin: 70px 25px 10px 0; } p { font-size: .71em; color: #a0a0a0; } } } } ================================================ FILE: Documentation/html/css/scss/_normalize.scss ================================================ /* ========================================================================== Normalize.scss settings ========================================================================== */ /** * Includes legacy browser support IE6/7 * * Set to false if you want to drop support for IE6 and IE7 */ $legacy_browser_support: false !default; /* Base ========================================================================== */ /** * 1. Set default font family to sans-serif. * 2. Prevent iOS text size adjust after orientation change, without disabling * user zoom. * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using * `em` units. */ html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ @if $legacy_browser_support { *font-size: 100%; /* 3 */ } } /** * Remove default margin. */ body { margin: 0; } /* HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined for any HTML5 element in IE 8/9. * Correct `block` display not defined for `details` or `summary` in IE 10/11 * and Firefox. * Correct `block` display not defined for `main` in IE 11. */ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } /** * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */ audio, canvas, progress, video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ @if $legacy_browser_support { *display: inline; *zoom: 1; } } /** * Prevents modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address `[hidden]` styling not present in IE 8/9/10. * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */ [hidden], template { display: none; } /* Links ========================================================================== */ /** * Remove the gray background color from active links in IE 10. */ a { background-color: transparent; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a { &:active, &:hover { outline: 0; }; } /* Text-level semantics ========================================================================== */ /** * Address styling not present in IE 8/9/10/11, Safari, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. */ b, strong { font-weight: bold; } @if $legacy_browser_support { blockquote { margin: 1em 40px; } } /** * Address styling not present in Safari and Chrome. */ dfn { font-style: italic; } /** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari, and Chrome. */ h1 { font-size: 2em; margin: 0.67em 0; } @if $legacy_browser_support { h2 { font-size: 1.5em; margin: 0.83em 0; } h3 { font-size: 1.17em; margin: 1em 0; } h4 { font-size: 1em; margin: 1.33em 0; } h5 { font-size: 0.83em; margin: 1.67em 0; } h6 { font-size: 0.67em; margin: 2.33em 0; } } /** * Addresses styling not present in IE 8/9. */ mark { background: #ff0; color: #000; } @if $legacy_browser_support { /** * Addresses margins set differently in IE 6/7. */ p, pre { *margin: 1em 0; } /* * Addresses CSS quotes not supported in IE 6/7. */ q { *quotes: none; } /* * Addresses `quotes` property not supported in Safari 4. */ q:before, q:after { content: ''; content: none; } } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } @if $legacy_browser_support { /* ========================================================================== Lists ========================================================================== */ /* * Addresses margins set differently in IE 6/7. */ dl, menu, ol, ul { *margin: 1em 0; } dd { *margin: 0 0 0 40px; } /* * Addresses paddings set differently in IE 6/7. */ menu, ol, ul { *padding: 0 0 0 40px; } /* * Corrects list images handled incorrectly in IE 7. */ nav ul, nav ol { *list-style: none; *list-style-image: none; } } /* Embedded content ========================================================================== */ /** * 1. Remove border when inside `a` element in IE 8/9/10. * 2. Improves image quality when scaled in IE 7. */ img { border: 0; @if $legacy_browser_support { *-ms-interpolation-mode: bicubic; /* 2 */ } } /** * Correct overflow not hidden in IE 9/10/11. */ svg:not(:root) { overflow: hidden; } /* Grouping content ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari. */ figure { margin: 1em 40px; } /** * Address differences between Firefox and other browsers. */ hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } /** * Contain overflow in all browsers. */ pre { overflow: auto; } /** * Address odd `em`-unit font size rendering in all browsers. * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. */ code, kbd, pre, samp { font-family: monospace, monospace; @if $legacy_browser_support { _font-family: 'courier new', monospace; } font-size: 1em; } /* Forms ========================================================================== */ /** * Known limitation: by default, Chrome and Safari on OS X allow very limited * styling of `select`, unless a `border` property is set. */ /** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. * 4. Improves appearance and consistency in all browsers. */ button, input, optgroup, select, textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */ @if $legacy_browser_support { vertical-align: baseline; /* 3 */ *vertical-align: middle; /* 3 */ } } /** * Address `overflow` set to `hidden` in IE 8/9/10/11. */ button { overflow: visible; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. * 4. Removes inner spacing in IE 7 without affecting normal text inputs. * Known issue: inner spacing remains in IE 6. */ button, html input[type="button"], /* 1 */ input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ @if $legacy_browser_support { *overflow: visible; /* 4 */ } } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ input { line-height: normal; } /** * 1. Address box sizing set to `content-box` in IE 8/9/10. * 2. Remove excess padding in IE 8/9/10. * Known issue: excess padding remains in IE 6. */ input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ @if $legacy_browser_support { *height: 13px; /* 3 */ *width: 13px; /* 3 */ } } /** * Fix the cursor style for Chrome's increment/decrement buttons. For certain * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } /** * Remove inner padding and search cancel button in Safari and Chrome on OS X. * Safari (but not Chrome) clips the cancel button when the search input has * padding (and `textfield` appearance). */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9/10/11. * 2. Remove padding so people aren't caught out if they zero out fieldsets. * 3. Corrects text not wrapping in Firefox 3. * 4. Corrects alignment displayed oddly in IE 6/7. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ @if $legacy_browser_support { white-space: normal; /* 3 */ *margin-left: -7px; /* 4 */ } } /** * Remove default vertical scrollbar in IE 8/9/10/11. */ textarea { overflow: auto; } /** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */ optgroup { font-weight: bold; } /* Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } ================================================ FILE: Documentation/html/css/scss/_object.scss ================================================ .section-specification { table { width: auto; th { text-align: left; } } } .method-title { margin-left: -15px; margin-bottom: 8px; transition: margin-left .3s ease-out; .section-method.hide & { margin-left: 0; } code { font-weight: 400; font-size: .85em; } } .method-info { background: $object-background; border-bottom: 1px solid $object-border; margin: 0 -25px; padding: 20px 25px 0 25px; transition: height .3s ease-out; position: relative; .pointy-thing { background: $content-background; height: 10px; border-bottom: 1px solid $object-border; margin: -20px -25px 16px -25px; &:before { display: inline-block; content: ""; background: $object-background; border: 1px solid $object-border; border-bottom: 0; border-right: 0; position: absolute; left: 21px; top: 3px; width: 12px; height: 12px; transform: rotate(45deg); } } .method-subsection { margin-bottom: 15px; .argument-name { width: 1px; text-align: right; code { color: #808080; font-style: italic; font-weight: 400; } } } } .section-method { &.hide .method-info { height: 0 !important; overflow: hidden; display: none; } &.hide.animating .method-info { display: block; } &.animating .method-info { overflow: hidden; } } ================================================ FILE: Documentation/html/css/scss/_print.scss ================================================ @media print { body { background: #fff; padding: 8px; } header { position: static; background: #fff; color: #000; } aside { display: none; } .container { max-width: none; padding: 0; } article { margin-top: 0; #content { border: 0; background: #fff; padding: 15px 0 0 0; .title { margin-top: 0; padding-top: 0; } } } .method-info { &, & .pointy-thing { background: #fff; } } } ================================================ FILE: Documentation/html/css/scss/_variables.scss ================================================ $body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; $code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; $body-background: #f2f2f2; $content-background: #fff; $content-border: #e9e9e9; $tint-color: #08c; $object-background: #f9f9f9; $object-border: #e9e9e9; $mobile-max-width: 650px; ================================================ FILE: Documentation/html/css/scss/_xcode.scss ================================================ .xcode { header, aside { display: none; } .container { padding: 0; } article { margin-top: 0; #content { border: 0; margin: 0; } } .method-info { &, .section-method.hide & { max-height: auto; overflow: visible; &.hiding { display: block; } } } } ================================================ FILE: Documentation/html/css/scss/style.scss ================================================ @import "variables", "normalize", "layout", "index", "object", "print", "xcode"; ================================================ FILE: Documentation/html/css/style.css ================================================ html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}.clear{clear:both}.clearfix:before,.container:before,article #content:before,article #content footer:before,.clearfix:after,.container:after,article #content:after,article #content footer:after{clear:both;display:table;content:""}.xcode .hide-in-xcode{display:none}body{font:62.5% -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;background:#f2f2f2}h1,h2,h3{font-weight:300;color:gray}h1{font-size:2em;color:#000}h4{font-size:13px;line-height:1.5;margin:21px 0 0}a{color:#08c;text-decoration:none}pre,code{font-family:Source Code Pro,Monaco,Menlo,Consolas,monospace;word-wrap:break-word}pre>code,.method-declaration code{display:inline-block;font-size:.85em;padding:4px 0 4px 10px;border-left:5px solid rgba(0,155,51,.2)}pre>code:before,.method-declaration code:before{content:"Objective-C";display:block;font:9px/1 -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;color:#009b33;text-transform:uppercase;letter-spacing:2px;padding-bottom:6px}pre>code{font-size:inherit}table,th,td{border:1px solid #e9e9e9}table{width:100%}th,td{padding:7px}th>:first-child,td>:first-child{margin-top:0}th>:last-child,td>:last-child{margin-bottom:0}.container{max-width:980px;padding:0 10px;margin:0 auto}@media(max-width:650px){.container{padding:0}}header{position:fixed;top:0;left:0;width:100%;z-index:2;background:#414141;color:#fff;font-size:1.1em;line-height:25px;letter-spacing:.05em}header #library-title{float:left}header #developer-home{float:right}header h1{font-size:inherit;font-weight:inherit;margin:0}header p{margin:0}header h1,header a{color:inherit}@media(max-width:650px){header{position:absolute}header .container{padding:0 10px}}aside{position:fixed;top:25px;left:0;width:100%;height:25px;z-index:2;font-size:1.1em}aside #header-buttons{background:rgba(255,255,255,.8);margin:0 1px;padding:0;list-style:none;text-align:right;line-height:32px}aside #header-buttons li{display:inline-block;cursor:pointer;padding:0 10px}aside #header-buttons label,aside #header-buttons select{cursor:inherit}aside #header-buttons #on-this-page{position:relative}aside #header-buttons #on-this-page .chevron{display:inline-block;width:14px;height:4px;position:relative}aside #header-buttons #on-this-page .chevron .chevy{background:#878787;height:2px;position:absolute;width:10px}aside #header-buttons #on-this-page .chevron .chevy.chevron-left{left:0;-webkit-transform:rotateZ(45deg) scale(.6);transform:rotateZ(45deg) scale(.6)}aside #header-buttons #on-this-page .chevron .chevy.chevron-right{right:0;-webkit-transform:rotateZ(-45deg) scale(.6);transform:rotateZ(-45deg) scale(.6)}aside #header-buttons #on-this-page #jump-to{opacity:0;filter:alpha(opacity=0);font-size:16px;position:absolute;top:5px;left:0;width:100%;height:100%}article{margin-top:25px}article #content{background:#fff;border:1px solid #e9e9e9;padding:15px 25px 30px;font-size:1.4em;line-height:1.45;position:relative}@media(max-width:650px){article #content{padding:15px 10px 20px}}article #content .navigation-top{position:absolute;top:15px;right:25px}article #content .title{margin:21px 0 0;padding:15px 0}article #content p{color:#414141;margin:0 0 15px}article #content th p:last-child,article #content td p:last-child{margin-bottom:0}article #content main ul{list-style:none;margin-left:24px;margin-bottom:12px;padding:0}article #content main ul li{position:relative;padding-left:1.3em}article #content main ul li:before{content:"\02022";color:#414141;font-size:1.08em;line-height:1;position:absolute;left:0;padding-top:2px}article #content footer .footer-copyright{margin:70px 25px 10px 0}article #content footer p{font-size:.71em;color:#a0a0a0}.index-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}@media(max-width:650px){.index-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}.index-container .index-column{-webkit-box-flex:1;-webkit-flex:1 1 33%;-ms-flex:1 1 33%;flex:1 1 33%}.section-specification table{width:auto}.section-specification table th{text-align:left}.method-title{margin-left:-15px;margin-bottom:8px;-webkit-transition:margin-left .3s ease-out;transition:margin-left .3s ease-out}.section-method.hide .method-title{margin-left:0}.method-title code{font-weight:400;font-size:.85em}.method-info{background:#f9f9f9;border-bottom:1px solid #e9e9e9;margin:0 -25px;padding:20px 25px 0;-webkit-transition:height .3s ease-out;transition:height .3s ease-out;position:relative}.method-info .pointy-thing{background:#fff;height:10px;border-bottom:1px solid #e9e9e9;margin:-20px -25px 16px}.method-info .pointy-thing:before{display:inline-block;content:"";background:#f9f9f9;border:1px solid #e9e9e9;border-bottom:0;border-right:0;position:absolute;left:21px;top:3px;width:12px;height:12px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.method-info .method-subsection{margin-bottom:15px}.method-info .method-subsection .argument-name{width:1px;text-align:right}.method-info .method-subsection .argument-name code{color:gray;font-style:italic;font-weight:400}.section-method.hide .method-info{height:0!important;overflow:hidden;display:none}.section-method.hide.animating .method-info{display:block}.section-method.animating .method-info{overflow:hidden}@media print{body{background:#fff;padding:8px}header{position:static;background:#fff;color:#000}aside{display:none}.container{max-width:none;padding:0}article{margin-top:0}article #content{border:0;background:#fff;padding:15px 0 0}article #content .title{margin-top:0;padding-top:0}.method-info,.method-info .pointy-thing{background:#fff}}.xcode header,.xcode aside{display:none}.xcode .container{padding:0}.xcode article{margin-top:0}.xcode article #content{border:0;margin:0}.xcode .section-method.hide .method-info,.xcode .section-method.hide.animating .method-info,.xcode .section-method.animating .method-info{height:auto!important;overflow:visible;display:block}.xcode .section-method.hide .method-title{margin-left:-15px} /*# sourceMappingURL=to.css.map */ ================================================ FILE: Documentation/html/css/styles.css ================================================ body { font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; font-size: 13px; } code { font-family: Courier, Consolas, monospace; font-size: 13px; color: #666; } pre { font-family: Courier, Consolas, monospace; font-size: 13px; line-height: 18px; tab-interval: 0.5em; border: 1px solid #C7CFD5; background-color: #F1F5F9; color: #666; padding: 0.3em 1em; } ul { list-style-type: square; } li { margin-bottom: 10px; } a, a code { text-decoration: none; color: #36C; } a:hover, a:hover code { text-decoration: underline; color: #36C; } h2 { border-bottom: 1px solid #8391A8; color: #3C4C6C; font-size: 187%; font-weight: normal; margin-top: 1.75em; padding-bottom: 2px; } table { margin-bottom: 4em; border-collapse:collapse; vertical-align: middle; } td { border: 1px solid #9BB3CD; padding: .667em; font-size: 100%; } th { border: 1px solid #9BB3CD; padding: .3em .667em .3em .667em; background: #93A5BB; font-size: 103%; font-weight: bold; color: white; text-align: left; } /* @group Common page elements */ #top_header { height: 91px; left: 0; min-width: 598px; position: absolute; right: 0; top: 0; z-index: 900; } #footer { clear: both; padding-top: 20px; text-align: center; } #contents, #overview_contents { -webkit-overflow-scrolling: touch; border-top: 1px solid #2B334F; position: absolute; top: 91px; left: 0; right: 0; bottom: 0; overflow-x: hidden; overflow-y: auto; padding-left: 2em; padding-right: 2em; padding-top: 1em; min-width: 550px; } #contents.isShowingTOC { left: 230px; min-width: 320px; } .copyright { font-size: 12px; } .generator { font-size: 11px; } .main-navigation ul li { display: inline; margin-left: 15px; list-style: none; } .navigation-top { clear: both; float: right; } .navigation-bottom { clear: both; float: right; margin-top: 20px; margin-bottom: -10px; } .open > .disclosure { background-image: url("../img/disclosure_open.png"); } .disclosure { background: url("../img/disclosure.png") no-repeat scroll 0 0; } .disclosure, .nodisclosure { display: inline-block; height: 8px; margin-right: 5px; position: relative; width: 9px; } /* @end */ /* @group Header */ #top_header #library { background: url("../img/library_background.png") repeat-x 0 0 #485E78; background-color: #ccc; height: 35px; font-size: 115%; } #top_header #library #libraryTitle { color: #FFFFFF; margin-left: 15px; text-shadow: 0 -1px 0 #485E78; top: 8px; position: absolute; } #top_header #library #developerHome { color: #92979E; right: 15px; top: 8px; position: absolute; } #top_header #library a:hover { text-decoration: none; } #top_header #title { background: url("../img/title_background.png") repeat-x 0 0 #8A98A9; border-bottom: 1px solid #B6B6B6; height: 25px; overflow: hidden; } #top_header h1 { font-size: 115%; font-weight: normal; margin: 0; padding: 3px 0 2px; text-align: center; text-shadow: 0 1px 0 #D5D5D5; white-space: nowrap; } #headerButtons { background-color: #D8D8D8; background-image: url("../img/button_bar_background.png"); border-bottom: 1px solid #EDEDED; border-top: 1px solid #2B334F; font-size: 8pt; height: 28px; left: 0; list-style: none outside none; margin: 0; overflow: hidden; padding: 0; position: absolute; right: 0; top: 61px; } #headerButtons li { background-repeat: no-repeat; display: inline; margin-top: 0; margin-bottom: 0; padding: 0; } #toc_button button { border-color: #ACACAC; border-style: none solid none none; border-width: 0 1px 0 0; height: 28px; margin: 0; padding-left: 30px; text-align: left; width: 230px; } li#jumpto_button { left: 230px; margin-left: 0; position: absolute; } li#jumpto_button select { height: 22px; margin: 5px 2px 0 10px; max-width: 300px; } /* @end */ /* @group Table of contents */ #tocContainer.isShowingTOC { border-right: 1px solid #ACACAC; display: block; overflow-x: hidden; overflow-y: auto; padding: 0; } #tocContainer { background-color: #E4EBF7; border-top: 1px solid #2B334F; bottom: 0; display: none; left: 0; overflow: hidden; position: absolute; top: 91px; width: 229px; } #tocContainer > ul#toc { font-size: 11px; margin: 0; padding: 12px 0 18px; width: 209px; -moz-user-select: none; -webkit-user-select: none; user-select: none; } #tocContainer > ul#toc > li { margin: 0; padding: 0 0 7px 30px; text-indent: -15px; } #tocContainer > ul#toc > li > .sectionName a { color: #000000; font-weight: bold; } #tocContainer > ul#toc > li > .sectionName a:hover { text-decoration: none; } #tocContainer > ul#toc li.children > ul { display: none; height: 0; } #tocContainer > ul#toc > li > ul { margin: 0; padding: 0; } #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { margin-left: 0; margin-bottom: 0; padding-left: 15px; } #tocContainer > ul#toc > li ul { list-style: none; margin-right: 0; padding-right: 0; } #tocContainer > ul#toc li.children.open > ul { display: block; height: auto; margin-left: -15px; padding-left: 0; } #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { margin-left: 0; padding-left: 15px; } #tocContainer li ul li { margin-top: 0.583em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #tocContainer li ul li span.sectionName { white-space: normal; } #tocContainer > ul#toc > li > ul > li > .sectionName a { font-weight: bold; } #tocContainer > ul#toc > li > ul a { color: #4F4F4F; } /* @end */ /* @group Index formatting */ .index-title { font-size: 13px; font-weight: normal; } .index-column { float: left; width: 30%; min-width: 200px; font-size: 11px; } .index-column ul { margin: 8px 0 0 0; padding: 0; list-style: none; } .index-column ul li { margin: 0 0 3px 0; padding: 0; } .hierarchy-column { min-width: 400px; } .hierarchy-column ul { margin: 3px 0 0 15px; } .hierarchy-column ul li { list-style-type: square; } /* @end */ /* @group Common formatting elements */ .title { font-weight: normal; font-size: 215%; margin-top:0; } .subtitle { font-weight: normal; font-size: 180%; color: #3C4C6C; border-bottom: 1px solid #5088C5; } .subsubtitle { font-weight: normal; font-size: 145%; height: 0.7em; } .note { border: 1px solid #5088C5; background-color: white; margin: 1.667em 0 1.75em 0; padding: 0 .667em .083em .750em; } .warning { border: 1px solid #5088C5; background-color: #F0F3F7; margin-bottom: 0.5em; padding: 0.3em 0.8em; } .bug { border: 1px solid #000; background-color: #ffffcc; margin-bottom: 0.5em; padding: 0.3em 0.8em; } .deprecated { color: #F60425; } /* @end */ /* @group Common layout */ .section { margin-top: 3em; } /* @end */ /* @group Object specification section */ .section-specification { margin-left: 2.5em; margin-right: 2.5em; font-size: 12px; } .section-specification table { margin-bottom: 0em; border-top: 1px solid #d6e0e5; } .section-specification td { vertical-align: top; border-bottom: 1px solid #d6e0e5; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; padding: .6em; } .section-specification .specification-title { font-weight: bold; } /* @end */ /* @group Tasks section */ .task-list { list-style-type: none; padding-left: 0px; } .task-list li { margin-bottom: 3px; } .task-item-suffix { color: #996; font-size: 12px; font-style: italic; margin-left: 0.5em; } span.tooltip span.tooltip { font-size: 1.0em; display: none; padding: 0.3em; border: 1px solid #aaa; background-color: #fdfec8; color: #000; text-align: left; } span.tooltip:hover span.tooltip { display: block; position: absolute; margin-left: 2em; } /* @end */ /* @group Method section */ .section-method { margin-top: 2.3em; } .method-title { margin-bottom: 1.5em; } .method-subtitle { margin-top: 0.7em; margin-bottom: 0.2em; } .method-subsection p { margin-top: 0.4em; margin-bottom: 0.8em; } .method-declaration { margin-top:1.182em; margin-bottom:.909em; } .method-declaration code { font:14px Courier, Consolas, monospace; color:#000; } .declaration { color: #000; } .argument-def { margin-top: 0.3em; margin-bottom: 0.3em; } .argument-def dd { margin-left: 1.25em; } .see-also-section ul { list-style-type: none; padding-left: 0px; margin-top: 0; } .see-also-section li { margin-bottom: 3px; } .declared-in-ref { color: #666; } #tocContainer.hideInXcode { display: none; border: 0px solid black; } #top_header.hideInXcode { display: none; } #contents.hideInXcode { border: 0px solid black; top: 0px; left: 0px; } /* @end */ ================================================ FILE: Documentation/html/css/stylesPrint.css ================================================ header { display: none; } div.main-navigation, div.navigation-top { display: none; } div#overview_contents, div#contents.isShowingTOC, div#contents { overflow: visible; position: relative; top: 0px; border: none; left: 0; } #tocContainer.isShowingTOC { display: none; } nav { display: none; } ================================================ FILE: Documentation/html/hierarchy.html ================================================ RBQFetchedResultsController Hierarchy

RBQFetchedResultsController

“Roobiq”

================================================ FILE: Documentation/html/index.html ================================================ RBQFetchedResultsController Reference

RBQFetchedResultsController

“Roobiq”

================================================ FILE: Documentation/html/js/script.js ================================================ function $() { return document.querySelector.apply(document, arguments); } if (navigator.userAgent.indexOf("Xcode") != -1) { document.documentElement.classList.add("xcode"); } var jumpTo = $("#jump-to"); if (jumpTo) { jumpTo.addEventListener("change", function(e) { location.hash = this.options[this.selectedIndex].value; }); } function hashChanged() { if (/^#\/\/api\//.test(location.hash)) { var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); if (!element) { return; } element = element.parentNode; element.classList.remove("hide"); fixScrollPosition(element); } } function fixScrollPosition(element) { var scrollTop = element.offsetTop - 150; document.documentElement.scrollTop = scrollTop; document.body.scrollTop = scrollTop; } [].forEach.call(document.querySelectorAll(".section-method"), function(element) { element.classList.add("hide"); element.querySelector(".method-title a").addEventListener("click", function(e) { var info = element.querySelector(".method-info"), infoContainer = element.querySelector(".method-info-container"); element.classList.add("animating"); info.style.height = (infoContainer.clientHeight + 40) + "px"; fixScrollPosition(element); element.classList.toggle("hide"); setTimeout(function() { element.classList.remove("animating"); info.style.height = "auto"; }, 300); }); }); window.addEventListener("hashchange", hashChanged); hashChanged(); ================================================ FILE: Examples/ObjC/Podfile ================================================ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'RBQFetchedResultsControllerExample' do pod 'RealmUtilities' pod 'RBQSafeRealmObject' target 'RBQFetchedResultsControllerExampleTests' do inherit! :search_paths end end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/AppDelegate.h ================================================ // // AppDelegate.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/AppDelegate.m ================================================ // // AppDelegate.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/ExampleTableViewController.h ================================================ // // ExampleTableViewController.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface ExampleTableViewController : UITableViewController @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/ExampleTableViewController.m ================================================ // // ExampleTableViewController.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "ExampleTableViewController.h" #import "RBQFetchedResultsController.h" #import "TestObject.h" #import "RLMObject+Utilities.h" id NULL_IF_NIL(id x) {return x ? x : NSNull.null;} @interface ExampleTableViewController () @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @end @implementation ExampleTableViewController - (void)viewDidLoad { [super viewDidLoad]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [realm addObject:object]; } [realm commitWriteTransaction]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:realm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"testCache"]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return [self.fetchedResultsController numberOfSections]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.fetchedResultsController numberOfRowsForSectionIndex:section]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.fetchedResultsController titleForHeaderInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"customCell" forIndexPath:indexPath]; // Configure the cell... TestObject *objectForCell = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = objectForCell.title; return cell; } // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source [self deleteObjectAtIndexPath:indexPath]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view [self insertObject]; } } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Beginning updates"); [self.tableView beginUpdates]; } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(RBQFetchedResultsSectionInfo *)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { UITableView *tableView = self.tableView; if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); NSIndexSet *insertedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView insertSections:insertedSection withRowAnimation:UITableViewRowAnimationFade]; } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); NSIndexSet *deletedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView deleteSections:deletedSection withRowAnimation:UITableViewRowAnimationFade]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Ending updates"); NSLog(@"Fetched %ld Items After Change", (unsigned long)self.fetchedResultsController.fetchedObjects.count); @try { [self.tableView endUpdates]; } @catch (NSException *ex) { NSLog(@"RBQFecthResultsTVC caught exception updating table view: %@. Falling back to reload.", ex); [self.fetchedResultsController reset]; [self.tableView reloadData]; } } #pragma mark - UIBarButton Actions - (IBAction)didClickDeleteButton:(UIBarButtonItem *)sender { // Delete the object in the first row // NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; // [self deleteObjectAtIndexPath:firstObjectIndexPath]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NSLog(@"DID BEGIN DELETE"); // Test deleting a section (comment out above to test) RLMResults *objectInFirstSection = [TestObject objectsWhere:@"%K == %@",@"sectionName",@"First Section"]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObjects:objectInFirstSection]; [realm commitWriteTransaction]; NSLog(@"DID END DELETE"); }); } - (IBAction)didClickInsertButton:(UIBarButtonItem *)sender { NSLog(@"DID BEGIN INSERT"); NSLog(@"Fetched %ld Items Before Insert", (unsigned long)self.fetchedResultsController.fetchedObjects.count); [self insertObject]; NSLog(@"DID END INSERT"); } #pragma mark - Private - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; if (!object) { return; } RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObject:object]; [realm commitWriteTransaction]; } - (void)insertObject { RLMRealm *realm = [RLMRealm defaultRealm]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; if (object.sortIndex > 0) { [realm beginWriteTransaction]; NSInteger sortIndex = object.sortIndex - 1; NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)sortIndex]; TestObject *newObject = [TestObject objectInRealm:realm forPrimaryKey:[NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]]; if (!newObject) { newObject = [[TestObject alloc] init]; newObject.title = title; newObject.sortIndex = sortIndex; newObject.sectionName = @"First Section"; newObject.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; newObject.inTable = YES; [realm addObject:newObject]; } else { newObject.inTable = YES; } [realm commitWriteTransaction]; } // Test Moves else { [realm beginWriteTransaction]; NSIndexPath *indexPathFifthRow = [NSIndexPath indexPathForRow:5 inSection:0]; NSIndexPath *indexPathThirdRow = [NSIndexPath indexPathForRow:3 inSection:0]; NSIndexPath *indexPathSixthRow = [NSIndexPath indexPathForRow:6 inSection:0]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *firstObject = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; TestObject *thirdObject = [self.fetchedResultsController objectAtIndexPath:indexPathThirdRow]; TestObject *fifthObject = [self.fetchedResultsController objectAtIndexPath:indexPathFifthRow]; TestObject *sixthObject = [self.fetchedResultsController objectAtIndexPath:indexPathSixthRow]; RLMResults *ninthObject = [TestObject objectsInRealm:realm where:@"%K == %@",@"title",@"Cell 9"]; fifthObject.sortIndex += 1; sixthObject.sortIndex -= 1; firstObject.inTable = NO; thirdObject.title = @"Testing Move And Update"; if (ninthObject.firstObject) { TestObject *object = ninthObject.firstObject; if ([object.sectionName isEqualToString:@"First Section"]) { object.sectionName = @"Second Section"; } else { object.sectionName = @"First Section"; } } //Test an inserted section that's not first // TestObject *extraObjectInSection = [TestObject testObjectWithTitle:@"Test Section" sortIndex:3 inTable:YES]; // extraObjectInSection.sectionName = @"Middle Section"; // [realm addObject:extraObjectInSection]; // // [[RBQRealmNotificationManager defaultManager] didAddObjects:@[extraObjectInSection] // willDeleteObjects:nil // didChangeObjects:@[NULL_IF_NIL(fifthObject), // NULL_IF_NIL(sixthObject), // NULL_IF_NIL(firstObject), // NULL_IF_NIL(thirdObject)]]; [realm commitWriteTransaction]; } } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/TestObject.h ================================================ // // TestObject.h // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import @interface TestObject : RLMObject @property NSString *title; @property NSInteger sortIndex; @property NSString *sectionName; @property NSString *key; @property BOOL inTable; + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable; @end // This protocol enables typed collections. i.e.: // RLMArray RLM_ARRAY_TYPE(TestObject) ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/TestObject.m ================================================ // // TestObject.m // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "TestObject.h" @implementation TestObject + (NSString *)primaryKey { return @"key"; } // Specify default values for properties //+ (NSDictionary *)defaultPropertyValues //{ // return @{}; //} // Specify properties to ignore (Realm won't persist these) //+ (NSArray *)ignoredProperties //{ // return @[]; //} + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable { TestObject *object = [[TestObject alloc] init]; object.sortIndex = sortIndex; object.title = title; object.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; object.inTable = inTable; return object; } - (id)copyWithZone:(nullable NSZone *)zone { TestObject *object = [[TestObject allocWithZone:zone] init]; object.title = self.title; object.sortIndex = self.sortIndex; object.sectionName = self.sectionName; object.key = self.key; object.inTable = self.inTable; return object; } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample/main.m ================================================ // // main.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 21AECE7723EDC5BE1F493DD7 /* libPods-RBQFetchedResultsControllerExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EDEDEB02FA7C4B3DDFF2E01 /* libPods-RBQFetchedResultsControllerExampleTests.a */; }; 4921A5F91B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */; }; 4921A5FF1B1A781F00CA32B7 /* RBQTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */; }; 49527C091B17F47500C115A3 /* RBQSafeRealmObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */; }; 49527C0F1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */; }; 49DF57321B17B09900BA8DDC /* RBQFetchRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */; }; 5DBE72B3A704D041106459BA /* libPods-RBQFetchedResultsControllerExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E06FD3669B0EDC2C9E99680 /* libPods-RBQFetchedResultsControllerExample.a */; }; 660F4C0A1B19413B00492DAE /* RBQFetchRequestInMemoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */; }; 667F380B1A5B2682008E3052 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380A1A5B2682008E3052 /* main.m */; }; 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380D1A5B2682008E3052 /* AppDelegate.m */; }; 667F38141A5B2682008E3052 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 667F38121A5B2682008E3052 /* Main.storyboard */; }; 667F38161A5B2682008E3052 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 667F38151A5B2682008E3052 /* Images.xcassets */; }; 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 667F38171A5B2682008E3052 /* LaunchScreen.xib */; }; 667F38401A5B26C5008E3052 /* TestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F383E1A5B26C5008E3052 /* TestObject.m */; }; 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */; }; A0519B981C56F84800307EB5 /* RBQControllerCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B6E1C56F84800307EB5 /* RBQControllerCacheObject.m */; }; A0519B991C56F84800307EB5 /* RBQObjectCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B701C56F84800307EB5 /* RBQObjectCacheObject.m */; }; A0519B9A1C56F84800307EB5 /* RBQSectionCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B721C56F84800307EB5 /* RBQSectionCacheObject.m */; }; A0519B9B1C56F84800307EB5 /* RBQFetchedResultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B741C56F84800307EB5 /* RBQFetchedResultsController.m */; }; A0519B9C1C56F84800307EB5 /* RBQFetchRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B761C56F84800307EB5 /* RBQFetchRequest.m */; }; A0C5E0A91CD7CE6300CD2892 /* RBQFetchedResultsControllerDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A0C5E0A81CD7CE6300CD2892 /* RBQFetchedResultsControllerDelegateTests.m */; }; A0C5E0AB1CD7CF3200CD2892 /* RBQFetchedResultsControllerWithSectionsDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A0C5E0AA1CD7CF3200CD2892 /* RBQFetchedResultsControllerWithSectionsDelegateTests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 667F37FD1A5B2682008E3052 /* Project object */; proxyType = 1; remoteGlobalIDString = 667F38041A5B2682008E3052; remoteInfo = RBQFetchedResultsControllerExample; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsControllerTests.m; sourceTree = ""; }; 4921A5FD1B1A781F00CA32B7 /* RBQTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQTestCase.h; sourceTree = ""; }; 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQTestCase.m; sourceTree = ""; }; 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQSafeRealmObjectTests.m; sourceTree = ""; }; 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsSectionInfoTests.m; sourceTree = ""; }; 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchRequestTests.m; sourceTree = ""; }; 5E06FD3669B0EDC2C9E99680 /* libPods-RBQFetchedResultsControllerExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RBQFetchedResultsControllerExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchRequestInMemoryTests.m; sourceTree = ""; }; 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFetchedResultsControllerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 667F38091A5B2682008E3052 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667F380A1A5B2682008E3052 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 667F380C1A5B2682008E3052 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 667F380D1A5B2682008E3052 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 667F38131A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 667F38151A5B2682008E3052 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 667F38181A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFetchedResultsControllerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 667F38231A5B2682008E3052 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667F383D1A5B26C5008E3052 /* TestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObject.h; sourceTree = ""; }; 667F383E1A5B26C5008E3052 /* TestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObject.m; sourceTree = ""; }; 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleTableViewController.h; sourceTree = ""; }; 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleTableViewController.m; sourceTree = ""; }; 69F4B4DCBE4F173C83ACADF0 /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig"; sourceTree = ""; }; 7EDEDEB02FA7C4B3DDFF2E01 /* libPods-RBQFetchedResultsControllerExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RBQFetchedResultsControllerExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A0519B6D1C56F84800307EB5 /* RBQControllerCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQControllerCacheObject.h; sourceTree = ""; }; A0519B6E1C56F84800307EB5 /* RBQControllerCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQControllerCacheObject.m; sourceTree = ""; }; A0519B6F1C56F84800307EB5 /* RBQObjectCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQObjectCacheObject.h; sourceTree = ""; }; A0519B701C56F84800307EB5 /* RBQObjectCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQObjectCacheObject.m; sourceTree = ""; }; A0519B711C56F84800307EB5 /* RBQSectionCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQSectionCacheObject.h; sourceTree = ""; }; A0519B721C56F84800307EB5 /* RBQSectionCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQSectionCacheObject.m; sourceTree = ""; }; A0519B731C56F84800307EB5 /* RBQFetchedResultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchedResultsController.h; path = ../../RBQFetchedResultsController/Source/RBQFetchedResultsController.h; sourceTree = ""; }; A0519B741C56F84800307EB5 /* RBQFetchedResultsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchedResultsController.m; path = ../../RBQFetchedResultsController/Source/RBQFetchedResultsController.m; sourceTree = ""; }; A0519B751C56F84800307EB5 /* RBQFetchRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchRequest.h; path = ../../RBQFetchedResultsController/Source/RBQFetchRequest.h; sourceTree = ""; }; A0519B761C56F84800307EB5 /* RBQFetchRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchRequest.m; path = ../../RBQFetchedResultsController/Source/RBQFetchRequest.m; sourceTree = ""; }; A0C5E0A81CD7CE6300CD2892 /* RBQFetchedResultsControllerDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsControllerDelegateTests.m; sourceTree = ""; }; A0C5E0AA1CD7CF3200CD2892 /* RBQFetchedResultsControllerWithSectionsDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsControllerWithSectionsDelegateTests.m; sourceTree = ""; }; AC0520B151033210B939C995 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig"; sourceTree = ""; }; D6701031C0C8992AEA9F7F6E /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample.release.xcconfig"; sourceTree = ""; }; E0112A40CE95A7F755B7DEF2 /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 667F38021A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 5DBE72B3A704D041106459BA /* libPods-RBQFetchedResultsControllerExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381B1A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 21AECE7723EDC5BE1F493DD7 /* libPods-RBQFetchedResultsControllerExampleTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 01C541735D0E0450F5A842E4 /* Frameworks */ = { isa = PBXGroup; children = ( 5E06FD3669B0EDC2C9E99680 /* libPods-RBQFetchedResultsControllerExample.a */, 7EDEDEB02FA7C4B3DDFF2E01 /* libPods-RBQFetchedResultsControllerExampleTests.a */, ); name = Frameworks; sourceTree = ""; }; 148B3E50AC827E8624BB6F6E /* Pods */ = { isa = PBXGroup; children = ( E0112A40CE95A7F755B7DEF2 /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */, D6701031C0C8992AEA9F7F6E /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */, AC0520B151033210B939C995 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */, 69F4B4DCBE4F173C83ACADF0 /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 667F37FC1A5B2682008E3052 = { isa = PBXGroup; children = ( 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F38211A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */, 667F38061A5B2682008E3052 /* Products */, 148B3E50AC827E8624BB6F6E /* Pods */, 01C541735D0E0450F5A842E4 /* Frameworks */, ); sourceTree = ""; }; 667F38061A5B2682008E3052 /* Products */ = { isa = PBXGroup; children = ( 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */, 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */, ); name = Products; sourceTree = ""; }; 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXGroup; children = ( A08908ED1B8F95EB002E87DD /* RBQFetchedResultsController */, 667F380C1A5B2682008E3052 /* AppDelegate.h */, 667F380D1A5B2682008E3052 /* AppDelegate.m */, 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */, 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */, 667F383D1A5B26C5008E3052 /* TestObject.h */, 667F383E1A5B26C5008E3052 /* TestObject.m */, 667F38121A5B2682008E3052 /* Main.storyboard */, 667F38151A5B2682008E3052 /* Images.xcassets */, 667F38171A5B2682008E3052 /* LaunchScreen.xib */, 667F38081A5B2682008E3052 /* Supporting Files */, ); path = RBQFetchedResultsControllerExample; sourceTree = ""; }; 667F38081A5B2682008E3052 /* Supporting Files */ = { isa = PBXGroup; children = ( 667F38091A5B2682008E3052 /* Info.plist */, 667F380A1A5B2682008E3052 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 667F38211A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */ = { isa = PBXGroup; children = ( 4921A5FD1B1A781F00CA32B7 /* RBQTestCase.h */, 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */, 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */, A0C5E0A81CD7CE6300CD2892 /* RBQFetchedResultsControllerDelegateTests.m */, A0C5E0AA1CD7CF3200CD2892 /* RBQFetchedResultsControllerWithSectionsDelegateTests.m */, 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */, 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */, 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */, 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */, 667F38221A5B2682008E3052 /* Supporting Files */, ); path = RBQFetchedResultsControllerExampleTests; sourceTree = ""; }; 667F38221A5B2682008E3052 /* Supporting Files */ = { isa = PBXGroup; children = ( 667F38231A5B2682008E3052 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A0519B6C1C56F84800307EB5 /* CacheObjects */ = { isa = PBXGroup; children = ( A0519B6D1C56F84800307EB5 /* RBQControllerCacheObject.h */, A0519B6E1C56F84800307EB5 /* RBQControllerCacheObject.m */, A0519B6F1C56F84800307EB5 /* RBQObjectCacheObject.h */, A0519B701C56F84800307EB5 /* RBQObjectCacheObject.m */, A0519B711C56F84800307EB5 /* RBQSectionCacheObject.h */, A0519B721C56F84800307EB5 /* RBQSectionCacheObject.m */, ); name = CacheObjects; path = ../../RBQFetchedResultsController/Source/CacheObjects; sourceTree = ""; }; A08908ED1B8F95EB002E87DD /* RBQFetchedResultsController */ = { isa = PBXGroup; children = ( A0519B6C1C56F84800307EB5 /* CacheObjects */, A0519B731C56F84800307EB5 /* RBQFetchedResultsController.h */, A0519B741C56F84800307EB5 /* RBQFetchedResultsController.m */, A0519B751C56F84800307EB5 /* RBQFetchRequest.h */, A0519B761C56F84800307EB5 /* RBQFetchRequest.m */, ); name = RBQFetchedResultsController; path = ../../RBQFetchedResultsController; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXNativeTarget; buildConfigurationList = 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */; buildPhases = ( C3BE296BC60761BAF93E5B11 /* [CP] Check Pods Manifest.lock */, 667F38011A5B2682008E3052 /* Sources */, 667F38021A5B2682008E3052 /* Frameworks */, 667F38031A5B2682008E3052 /* Resources */, 006F9DB7A39428843B940C44 /* [CP] Embed Pods Frameworks */, B0D159D5E35B99EDDF2E4D07 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = RBQFetchedResultsControllerExample; productName = RBQFetchedResultsControllerExample; productReference = 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */; productType = "com.apple.product-type.application"; }; 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */; buildPhases = ( 99BC62BA0EED18E51B5E1107 /* [CP] Check Pods Manifest.lock */, 667F381A1A5B2682008E3052 /* Sources */, 667F381B1A5B2682008E3052 /* Frameworks */, 667F381C1A5B2682008E3052 /* Resources */, 8F020BC11844093311DC7559 /* [CP] Embed Pods Frameworks */, D744C46E9560A4C08EB2C418 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 667F38201A5B2682008E3052 /* PBXTargetDependency */, ); name = RBQFetchedResultsControllerExampleTests; productName = RBQFetchedResultsControllerExampleTests; productReference = 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 667F37FD1A5B2682008E3052 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0810; ORGANIZATIONNAME = Roobiq; TargetAttributes = { 667F38041A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; }; 667F381D1A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; TestTargetID = 667F38041A5B2682008E3052; }; }; }; buildConfigurationList = 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 667F37FC1A5B2682008E3052; productRefGroup = 667F38061A5B2682008E3052 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 667F38031A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38141A5B2682008E3052 /* Main.storyboard in Resources */, 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */, 667F38161A5B2682008E3052 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381C1A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 006F9DB7A39428843B940C44 /* [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-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 8F020BC11844093311DC7559 /* [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-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 99BC62BA0EED18E51B5E1107 /* [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; }; B0D159D5E35B99EDDF2E4D07 /* [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-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; C3BE296BC60761BAF93E5B11 /* [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; }; D744C46E9560A4C08EB2C418 /* [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-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 667F38011A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */, 667F38401A5B26C5008E3052 /* TestObject.m in Sources */, A0519B981C56F84800307EB5 /* RBQControllerCacheObject.m in Sources */, A0519B9C1C56F84800307EB5 /* RBQFetchRequest.m in Sources */, 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */, A0519B991C56F84800307EB5 /* RBQObjectCacheObject.m in Sources */, 667F380B1A5B2682008E3052 /* main.m in Sources */, A0519B9B1C56F84800307EB5 /* RBQFetchedResultsController.m in Sources */, A0519B9A1C56F84800307EB5 /* RBQSectionCacheObject.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381A1A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 660F4C0A1B19413B00492DAE /* RBQFetchRequestInMemoryTests.m in Sources */, A0C5E0AB1CD7CF3200CD2892 /* RBQFetchedResultsControllerWithSectionsDelegateTests.m in Sources */, A0C5E0A91CD7CE6300CD2892 /* RBQFetchedResultsControllerDelegateTests.m in Sources */, 49527C0F1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m in Sources */, 49DF57321B17B09900BA8DDC /* RBQFetchRequestTests.m in Sources */, 49527C091B17F47500C115A3 /* RBQSafeRealmObjectTests.m in Sources */, 4921A5F91B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m in Sources */, 4921A5FF1B1A781F00CA32B7 /* RBQTestCase.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 667F38201A5B2682008E3052 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */; targetProxy = 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 667F38121A5B2682008E3052 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 667F38131A5B2682008E3052 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 667F38171A5B2682008E3052 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( 667F38181A5B2682008E3052 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 667F38261A5B2682008E3052 /* 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; 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.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 667F38271A5B2682008E3052 /* 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 = YES; 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.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 667F38291A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = E0112A40CE95A7F755B7DEF2 /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; HEADER_SEARCH_PATHS = ( "$(inherited)", "\"${PODS_ROOT}/Headers/Public\"", "\"${PODS_ROOT}/Headers/Public/Realm\"", "$(SRCROOT)/../../RBQFetchedResultsController/Source/RBQSafeRealmObject", ); INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 667F382A1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = D6701031C0C8992AEA9F7F6E /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; HEADER_SEARCH_PATHS = ( "$(inherited)", "\"${PODS_ROOT}/Headers/Public\"", "\"${PODS_ROOT}/Headers/Public/Realm\"", "$(SRCROOT)/../../RBQFetchedResultsController/Source/RBQSafeRealmObject", ); INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 667F382C1A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = AC0520B151033210B939C995 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Debug; }; 667F382D1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 69F4B4DCBE4F173C83ACADF0 /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38261A5B2682008E3052 /* Debug */, 667F38271A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38291A5B2682008E3052 /* Debug */, 667F382A1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F382C1A5B2682008E3052 /* Debug */, 667F382D1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 667F37FD1A5B2682008E3052 /* Project object */; } ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchRequestInMemoryTests.m ================================================ // // RBQFetchRequestInMemoryTests.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 5/29/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import #import "RBQFetchRequest.h" #import #import "TestObject.h" @interface RBQFetchRequestInMemoryTests : XCTestCase @property (strong, nonatomic) RLMRealm *inMemoryRealm; @end @implementation RBQFetchRequestInMemoryTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. // Setup the DB (use random strings to create new versions each time) RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.inMemoryRealm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm deleteAllObjects]; for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.inTable = YES; } else { testObject.inTable = NO; } [self.inMemoryRealm addObject:testObject]; } }]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; RLMRealm *realm = self.inMemoryRealm; [realm transactionWithBlock:^{ [realm deleteAllObjects]; }]; } - (void)testVerifyEnityNameObjC { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; XCTAssert([fetchRequest.entityName isEqualToString:@"TestObject"]); } // TODO: testVerifyEntityNameSwift - (void)testFetchObjects { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; id results = [fetchRequest fetchObjects]; TestObject *firstObject = results.firstObject; XCTAssert(results.count == 5); XCTAssert([firstObject.key isEqualToString:@"key0"]); } - (void)testEvaluateObject { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = YES; XCTAssert([fetchRequest evaluateObject:testObject]); } - (void)testEvaluateObjectFailed { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = NO; XCTAssertFalse([fetchRequest evaluateObject:testObject]); } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchRequestTests.m ================================================ // // RBQFetchRequestTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/27. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQFetchRequest.h" #import #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchRequestTests : RBQTestCase @end @implementation RBQFetchRequestTests - (void)testVerifyEnityNameObjC { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; XCTAssert([fetchRequest.entityName isEqualToString:@"TestObject"]); } // TODO: testVerifyEntityNameSwift - (void)testFetchObjects { [self insertDifferentInTableTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; id results = [fetchRequest fetchObjects]; TestObject *firstObject = results.firstObject; XCTAssert(results.count == 5); XCTAssert([firstObject.key isEqualToString:@"key0"]); } - (void)testEvaluateObject { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = YES; XCTAssert([fetchRequest evaluateObject:testObject]); } - (void)testEvaluateObjectFailed { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = NO; XCTAssertFalse([fetchRequest evaluateObject:testObject]); } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsControllerDelegateTests.m ================================================ // // RBQFetchedResultsControllerDelegateTests.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/10/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import #import #import "RBQFetchedResultsController.h" #import "TestObject.h" static char kAssociatedObjectKey; @interface RBQFetchedResultsControllerDelegateTests : XCTestCase @property (strong, nonatomic) XCTestExpectation *controllerWillChangeContentExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeObjectExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeSectionExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeContentExpectation; @property (strong, nonatomic) RLMRealm *inMemoryRealm; @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @property (assign, nonatomic) NSUInteger count; @end @implementation RBQFetchedResultsControllerDelegateTests - (void)setUp { [super setUp]; // Setup the DB (use random strings to create new versions each time) RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.inMemoryRealm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; // Load the DB with data [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [self.inMemoryRealm addObject:object]; } [self.inMemoryRealm commitWriteTransaction]; // Setup the FRC NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:nil cacheName:nil]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; self.controllerWillChangeContentExpectation = nil; self.controllerDidChangeObjectExpectation = nil; self.controllerDidChangeSectionExpectation = nil; self.controllerDidChangeContentExpectation = nil; self.fetchedResultsController = nil; self.count = 0; } - (void)testControllerWillChangeContent { self.controllerWillChangeContentExpectation = [self expectationWithDescription:@"FRC Will Change Content Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeObject { self.controllerWillChangeContentExpectation = [self expectationWithDescription:@"FRC Will Change Content Fired"]; self.controllerDidChangeObjectExpectation = [self expectationWithDescription:@"FRC Did Change Object Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeContent { self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeObjects { dispatch_semaphore_t sem = dispatch_semaphore_create(0); int maxCycles = 100; for (int i = 1; i <= maxCycles; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; TestObject *copiedObject = [object copy]; XCTestExpectation *deleteExpectation = [self expectationWithDescription:@""]; objc_setAssociatedObject(self.fetchedResultsController, &kAssociatedObjectKey, deleteExpectation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm deleteObject:object]; }]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; XCTestExpectation *insertExpectation = [self expectationWithDescription:@""]; objc_setAssociatedObject(self.fetchedResultsController, &kAssociatedObjectKey, insertExpectation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm addObject:copiedObject]; }]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; if (i == maxCycles - 1) { dispatch_semaphore_signal(sem); } } dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); } #pragma - Actions - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteObject:object]; [self.inMemoryRealm commitWriteTransaction]; } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerWillChangeContentExpectation) { [self.controllerWillChangeContentExpectation fulfill]; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); break; } XCTestExpectation *associatedExpectation = objc_getAssociatedObject(controller, &kAssociatedObjectKey); // Fulfilling an expectation prematurely seems to cause problems if (self.controllerDidChangeObjectExpectation && !self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeObjectExpectation fulfill]; } else if (self.controllerDidChangeObjectExpectation && self.controllerDidChangeSectionExpectation) { self.count ++; if (self.count == 10) { [self.controllerDidChangeObjectExpectation fulfill]; } } else if (associatedExpectation) { [associatedExpectation fulfill]; objc_setAssociatedObject(controller, &kAssociatedObjectKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(NSString *)sectionName atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); } if (self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeSectionExpectation fulfill]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerDidChangeContentExpectation) { [self.controllerDidChangeContentExpectation fulfill]; } } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsControllerTests.m ================================================ // // RBQFetchedResultsControllerTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/29. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import #import "RBQFetchedResultsController.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchedResultsControllerTests : RBQTestCase @end @implementation RBQFetchedResultsControllerTests - (void)testPerformFetch { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert([fetchedResultsController numberOfSections] == 2); XCTAssert([fetchedResultsController.sectionNameKeyPath isEqualToString:@"sectionName"]); XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); } - (void)testPeformFetchWithoutSortDescriptor { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert([fetchedResultsController numberOfSections] == 10); XCTAssert([fetchedResultsController.sectionNameKeyPath isEqualToString:@"sectionName"]); XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); } - (void)testDeleteWithCacheName { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *testObject = [fetchedResultsController objectAtIndexPath:indexPath]; XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); XCTAssert([testObject.sectionName isEqualToString:@"section 1"]); XCTAssert(testObject.sortIndex == 0); [RBQFetchedResultsController deleteCacheWithName:@"cache"]; XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); XCTAssertNil([fetchedResultsController objectAtIndexPath:indexPath]); } // TODO: - deleteWithCacheName pass nil - (void)testUpdateFetchRequestSectionNameKeyPathAndPeformFetch { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert(fetchedResultsController.fetchedObjects.count == 10); NSPredicate *anotherPredicate = [NSPredicate predicateWithFormat:@"inTable = NO"]; RBQFetchRequest *anotherFetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate: anotherPredicate]; [fetchedResultsController updateFetchRequest:anotherFetchRequest sectionNameKeyPath:@"sectionName" andPerformFetch:YES]; XCTAssert(fetchedResultsController.fetchedObjects.count == 0); } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsControllerWithSectionsDelegateTests.m ================================================ // // RBQFetchedResultsControllerWithSectionsDelegateTests.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/10/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import #import #import "RBQFetchedResultsController.h" #import "TestObject.h" static char kAssociatedObjectKey; @interface RBQFetchedResultsControllerWithSectionsDelegateTests : XCTestCase @property (strong, nonatomic) XCTestExpectation *controllerWillChangeContentExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeObjectExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeSectionExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeContentExpectation; @property (strong, nonatomic) RLMRealm *inMemoryRealm; @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @property (assign, nonatomic) NSUInteger count; @end @implementation RBQFetchedResultsControllerWithSectionsDelegateTests - (void)setUp { [super setUp]; // Setup the DB (use random strings to create new versions each time) RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.inMemoryRealm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; // Load the DB with data [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [self.inMemoryRealm addObject:object]; } [self.inMemoryRealm commitWriteTransaction]; // Setup the FRC NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:nil]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; self.controllerWillChangeContentExpectation = nil; self.controllerDidChangeObjectExpectation = nil; self.controllerDidChangeSectionExpectation = nil; self.controllerDidChangeContentExpectation = nil; self.fetchedResultsController = nil; self.count = 0; } - (void)testControllerWillChangeContent { self.controllerWillChangeContentExpectation = [self expectationWithDescription:@"FRC Will Change Content Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeObject { self.controllerDidChangeObjectExpectation = [self expectationWithDescription:@"FRC Did Change Object Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeSection { self.controllerDidChangeObjectExpectation = [self expectationWithDescription:@"FRC Did Change Object Fired"]; self.controllerDidChangeSectionExpectation = [self expectationWithDescription:@"FRC Did Change Section Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; // Test deleting a section RLMResults *objectInFirstSection = [TestObject objectsInRealm:self.inMemoryRealm where:@"%K == %@",@"sectionName",@"First Section"]; [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteObjects:objectInFirstSection]; [self.inMemoryRealm commitWriteTransaction]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeContent { self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeObjects { dispatch_semaphore_t sem = dispatch_semaphore_create(0); int maxCycles = 100; for (int i = 1; i <= maxCycles; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; TestObject *copiedObject = [object copy]; XCTestExpectation *deleteExpectation = [self expectationWithDescription:@""]; objc_setAssociatedObject(self.fetchedResultsController, &kAssociatedObjectKey, deleteExpectation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm deleteObject:object]; }]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; XCTestExpectation *insertExpectation = [self expectationWithDescription:@""]; objc_setAssociatedObject(self.fetchedResultsController, &kAssociatedObjectKey, insertExpectation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm addObject:copiedObject]; }]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; if (i == maxCycles - 1) { dispatch_semaphore_signal(sem); } } dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); } #pragma - Actions - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteObject:object]; [self.inMemoryRealm commitWriteTransaction]; } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerWillChangeContentExpectation) { [self.controllerWillChangeContentExpectation fulfill]; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); break; } XCTestExpectation *associatedExpectation = objc_getAssociatedObject(controller, &kAssociatedObjectKey); // Fulfilling an expectation prematurely seems to cause problems if (self.controllerDidChangeObjectExpectation && !self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeObjectExpectation fulfill]; } else if (self.controllerDidChangeObjectExpectation && self.controllerDidChangeSectionExpectation) { self.count ++; if (self.count == 10) { [self.controllerDidChangeObjectExpectation fulfill]; } } else if (associatedExpectation) { [associatedExpectation fulfill]; objc_setAssociatedObject(controller, &kAssociatedObjectKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(NSString *)sectionName atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); } if (self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeSectionExpectation fulfill]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerDidChangeContentExpectation) { [self.controllerDidChangeContentExpectation fulfill]; } } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsSectionInfoTests.m ================================================ // // RBQFetchedResultsSectionInfoTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/28. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQFetchedResultsController.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchedResultsSectionInfoTests : RBQTestCase @end @implementation RBQFetchedResultsSectionInfoTests #pragma mark - Utility - (RBQFetchedResultsSectionInfo *)createFetchedResultsSectionInfo { SEL selector = NSSelectorFromString(@"createSectionWithName:sectionNameKeyPath:fetchRequest:"); NSMethodSignature *signature = [[RBQFetchedResultsSectionInfo class] methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setSelector:selector]; [invocation setTarget:[RBQFetchedResultsSectionInfo class]]; NSString *sectionName = @"section 1"; NSString *sectionNameKeyPath = @"sectionName"; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; [invocation setArgument:§ionName atIndex:2]; [invocation setArgument:§ionNameKeyPath atIndex:3]; [invocation setArgument:&fetchRequest atIndex:4]; [invocation invoke]; RBQFetchedResultsSectionInfo __unsafe_unretained *sectionInfo; [invocation getReturnValue:§ionInfo]; return sectionInfo; } #pragma mark - Test Case - (void)testInitializeFetchedResultsSectionInfo { RBQFetchedResultsSectionInfo *sectionInfo = [self createFetchedResultsSectionInfo]; XCTAssertNotNil(sectionInfo); XCTAssert([sectionInfo isKindOfClass:[RBQFetchedResultsSectionInfo class]]); } - (void)testObjectsProperty { [self insertDifferentSectionNameTestObject]; RBQFetchedResultsSectionInfo *sectionInfo = [self createFetchedResultsSectionInfo]; id results = sectionInfo.objects; XCTAssert(sectionInfo.numberOfObjects == 5); XCTAssert(results.count == 5); for (TestObject *testObject in results) { XCTAssert([testObject.sectionName isEqualToString:@"section 1"]); XCTAssert(testObject.inTable == YES); } } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQSafeRealmObjectTests.m ================================================ // // RBQSafeRealmObjectTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/28. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQSafeRealmObject.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQSafeRealmObjectTests : RBQTestCase @end @implementation RBQSafeRealmObjectTests - (void)testInitializeSafeObject { RBQSafeRealmObject *safeObject = [[RBQSafeRealmObject alloc] initWithClassName:@"TestObject" primaryKeyValue:@"key" primaryKeyType:RLMPropertyTypeString realm:[RLMRealm defaultRealm]]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); } - (void)testSafeObjectFromObjectIfObjectIsPersisted { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); } - (void)testSafeObjectFromObjectIfObjectIsNotPersisted { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssertNil(safeObject.realmConfiguration); } - (void)testThreadSafe { XCTestExpectation *anotherThreadExpectation = [self expectationWithDescription:@"Wait the execution of antoher thread"]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); [anotherThreadExpectation fulfill]; }); [self waitForExpectationsWithTimeout:5 handler:nil]; } - (void)testRLMRealmProperty { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; TestObject *fetchedObject = [TestObject allObjects].firstObject; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.RLMObject isEqualToObject:fetchedObject]); } - (void)testIsEqualToObject { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; TestObject *fetchedObject = [TestObject allObjects].firstObject; RBQSafeRealmObject *safeObject1 = [RBQSafeRealmObject safeObjectFromObject:fetchedObject]; RBQSafeRealmObject *safeObject2 = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject1 isEqualToObject:safeObject2]); } @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQTestCase.h ================================================ // // RBQTestCase.h // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/30. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import @interface RBQTestCase : XCTestCase @property (nonatomic) BOOL inMemory; - (void)insertDifferentSectionNameTestObject; - (void)insertDifferentInTableTestObject; @end ================================================ FILE: Examples/ObjC/RBQFetchedResultsControllerExampleTests/RBQTestCase.m ================================================ // // RBQTestCase.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/30. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import "RBQTestCase.h" #import #import "TestObject.h" static NSString *testRealmFileName = @"test.realm"; @interface RBQTestCase() @property (nonatomic, strong) RLMRealm *realm; @end @implementation RBQTestCase - (void)setUp { [super setUp]; NSArray *writablePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsPath = [writablePaths lastObject]; NSString *testRealmFile = [documentsPath stringByAppendingPathComponent:testRealmFileName]; RLMRealmConfiguration *defaultConfig = [RLMRealmConfiguration defaultConfiguration]; defaultConfig.fileURL = [NSURL fileURLWithPath:testRealmFile]; [RLMRealmConfiguration setDefaultConfiguration:defaultConfig]; if (self.inMemory) { RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.realm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; } else { self.realm = [RLMRealm defaultRealm]; } [self.realm transactionWithBlock:^{ [[RLMRealm defaultRealm] deleteAllObjects]; }]; } - (void)tearDown { [super tearDown]; [self.realm transactionWithBlock:^{ [[RLMRealm defaultRealm] deleteAllObjects]; }]; } #pragma mark - Insert objects in Realm - (void)insertDifferentSectionNameTestObject { [self.realm transactionWithBlock:^{ for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.inTable = YES; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.sectionName = @"section 1"; } else { testObject.sectionName = @"section 2"; } [[RLMRealm defaultRealm] addObject:testObject]; } }]; } - (void)insertDifferentInTableTestObject { [self.realm transactionWithBlock:^{ for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.inTable = YES; } else { testObject.inTable = NO; } [[RLMRealm defaultRealm] addObject:testObject]; } }]; } @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/AppDelegate.h ================================================ // // AppDelegate.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/AppDelegate.m ================================================ // // AppDelegate.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/ExampleTableViewController.h ================================================ // // ExampleTableViewController.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface ExampleTableViewController : UITableViewController @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/ExampleTableViewController.m ================================================ // // ExampleTableViewController.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "ExampleTableViewController.h" #import "TestObject.h" #import #import id NULL_IF_NIL(id x) {return x ? x : NSNull.null;} @interface ExampleTableViewController () @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @end @implementation ExampleTableViewController - (void)viewDidLoad { [super viewDidLoad]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [realm addObject:object]; } [realm commitWriteTransaction]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:realm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"testCache"]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return [self.fetchedResultsController numberOfSections]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.fetchedResultsController numberOfRowsForSectionIndex:section]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.fetchedResultsController titleForHeaderInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"customCell" forIndexPath:indexPath]; // Configure the cell... TestObject *objectForCell = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = objectForCell.title; return cell; } // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source [self deleteObjectAtIndexPath:indexPath]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view [self insertObject]; } } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Beginning updates"); [self.tableView beginUpdates]; } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(RBQFetchedResultsSectionInfo *)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { UITableView *tableView = self.tableView; if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); NSIndexSet *insertedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView insertSections:insertedSection withRowAnimation:UITableViewRowAnimationFade]; } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); NSIndexSet *deletedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView deleteSections:deletedSection withRowAnimation:UITableViewRowAnimationFade]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Ending updates"); NSLog(@"Fetched %ld Items After Change", (unsigned long)self.fetchedResultsController.fetchedObjects.count); @try { [self.tableView endUpdates]; } @catch (NSException *ex) { NSLog(@"RBQFecthResultsTVC caught exception updating table view: %@. Falling back to reload.", ex); [self.fetchedResultsController reset]; [self.tableView reloadData]; } } #pragma mark - UIBarButton Actions - (IBAction)didClickDeleteButton:(UIBarButtonItem *)sender { // Delete the object in the first row // NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; // [self deleteObjectAtIndexPath:firstObjectIndexPath]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NSLog(@"DID BEGIN DELETE"); // Test deleting a section (comment out above to test) RLMResults *objectInFirstSection = [TestObject objectsWhere:@"%K == %@",@"sectionName",@"First Section"]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObjects:objectInFirstSection]; [realm commitWriteTransaction]; NSLog(@"DID END DELETE"); }); } - (IBAction)didClickInsertButton:(UIBarButtonItem *)sender { NSLog(@"DID BEGIN INSERT"); NSLog(@"Fetched %ld Items Before Insert", (unsigned long)self.fetchedResultsController.fetchedObjects.count); [self insertObject]; NSLog(@"DID END INSERT"); } #pragma mark - Private - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; if (!object) { return; } RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObject:object]; [realm commitWriteTransaction]; } - (void)insertObject { RLMRealm *realm = [RLMRealm defaultRealm]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; if (object.sortIndex > 0) { [realm beginWriteTransaction]; NSInteger sortIndex = object.sortIndex - 1; NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)sortIndex]; TestObject *newObject = [TestObject objectInRealm:realm forPrimaryKey:[NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]]; if (!newObject) { newObject = [[TestObject alloc] init]; newObject.title = title; newObject.sortIndex = sortIndex; newObject.sectionName = @"First Section"; newObject.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; newObject.inTable = YES; [realm addObject:newObject]; } else { newObject.inTable = YES; } [realm commitWriteTransaction]; } // Test Moves else { [realm beginWriteTransaction]; NSIndexPath *indexPathFifthRow = [NSIndexPath indexPathForRow:5 inSection:0]; NSIndexPath *indexPathThirdRow = [NSIndexPath indexPathForRow:3 inSection:0]; NSIndexPath *indexPathSixthRow = [NSIndexPath indexPathForRow:6 inSection:0]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *firstObject = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; TestObject *thirdObject = [self.fetchedResultsController objectAtIndexPath:indexPathThirdRow]; TestObject *fifthObject = [self.fetchedResultsController objectAtIndexPath:indexPathFifthRow]; TestObject *sixthObject = [self.fetchedResultsController objectAtIndexPath:indexPathSixthRow]; RLMResults *ninthObject = [TestObject objectsInRealm:realm where:@"%K == %@",@"title",@"Cell 9"]; fifthObject.sortIndex += 1; sixthObject.sortIndex -= 1; firstObject.inTable = NO; thirdObject.title = @"Testing Move And Update"; if (ninthObject.firstObject) { TestObject *object = ninthObject.firstObject; if ([object.sectionName isEqualToString:@"First Section"]) { object.sectionName = @"Second Section"; } else { object.sectionName = @"First Section"; } } //Test an inserted section that's not first // TestObject *extraObjectInSection = [TestObject testObjectWithTitle:@"Test Section" sortIndex:3 inTable:YES]; // extraObjectInSection.sectionName = @"Middle Section"; // [realm addObject:extraObjectInSection]; // // [[RBQRealmNotificationManager defaultManager] didAddObjects:@[extraObjectInSection] // willDeleteObjects:nil // didChangeObjects:@[NULL_IF_NIL(fifthObject), // NULL_IF_NIL(sixthObject), // NULL_IF_NIL(firstObject), // NULL_IF_NIL(thirdObject)]]; [realm commitWriteTransaction]; } } @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/TestObject.h ================================================ // // TestObject.h // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import @interface TestObject : RLMObject @property NSString *title; @property NSInteger sortIndex; @property NSString *sectionName; @property NSString *key; @property BOOL inTable; + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable; @end // This protocol enables typed collections. i.e.: // RLMArray RLM_ARRAY_TYPE(TestObject) ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/TestObject.m ================================================ // // TestObject.m // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "TestObject.h" @implementation TestObject + (NSString *)primaryKey { return @"key"; } // Specify default values for properties //+ (NSDictionary *)defaultPropertyValues //{ // return @{}; //} // Specify properties to ignore (Realm won't persist these) //+ (NSArray *)ignoredProperties //{ // return @[]; //} + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable { TestObject *object = [[TestObject alloc] init]; object.sortIndex = sortIndex; object.title = title; object.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; object.inTable = inTable; return object; } @end ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample/main.m ================================================ // // main.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 667F380B1A5B2682008E3052 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380A1A5B2682008E3052 /* main.m */; }; 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380D1A5B2682008E3052 /* AppDelegate.m */; }; 667F38141A5B2682008E3052 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 667F38121A5B2682008E3052 /* Main.storyboard */; }; 667F38161A5B2682008E3052 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 667F38151A5B2682008E3052 /* Images.xcassets */; }; 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 667F38171A5B2682008E3052 /* LaunchScreen.xib */; }; 667F38401A5B26C5008E3052 /* TestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F383E1A5B26C5008E3052 /* TestObject.m */; }; 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */; }; A0951C3F1C87A5E5006AB5D7 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0951C3E1C87A5E5006AB5D7 /* Realm.framework */; }; A0951C401C87A5E5006AB5D7 /* Realm.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A0951C3E1C87A5E5006AB5D7 /* Realm.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; A0BC27B01C56DA0000306449 /* RBQFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0FBECB01C56D6E3006E5109 /* RBQFetchedResultsController.framework */; }; A0BC27B11C56DA0000306449 /* RBQFetchedResultsController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A0FBECB01C56D6E3006E5109 /* RBQFetchedResultsController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; A0C594D31CCF0D490041A382 /* RBQFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0FBECB01C56D6E3006E5109 /* RBQFetchedResultsController.framework */; }; F9C9CC4A1DF6BE3400A85A48 /* RBQSafeRealmObject.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC441DF6BE1500A85A48 /* RBQSafeRealmObject.framework */; }; F9C9CC4B1DF6BE3400A85A48 /* RBQSafeRealmObject.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC441DF6BE1500A85A48 /* RBQSafeRealmObject.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC4C1DF6BE3400A85A48 /* RealmUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC451DF6BE1500A85A48 /* RealmUtilities.framework */; }; F9C9CC4D1DF6BE3400A85A48 /* RealmUtilities.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC451DF6BE1500A85A48 /* RealmUtilities.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 667F37FD1A5B2682008E3052 /* Project object */; proxyType = 1; remoteGlobalIDString = 667F38041A5B2682008E3052; remoteInfo = RBQFetchedResultsControllerExample; }; A0951C371C87A50B006AB5D7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = A090E5A01C73B17B0046788B; remoteInfo = SwiftFetchedResultsController; }; A0BC27AE1C56D9E400306449 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; A0BC27B21C56DA0000306449 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; A0FBECAF1C56D6E3006E5109 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = 6361D7341C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; A0FBECB11C56D6E3006E5109 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = 6361D73E1C4051A8005CD430; remoteInfo = RBQFetchedResultsControllerTests; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ A092AF9C1C56D79600FD6208 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( F9C9CC4B1DF6BE3400A85A48 /* RBQSafeRealmObject.framework in Embed Frameworks */, F9C9CC4D1DF6BE3400A85A48 /* RealmUtilities.framework in Embed Frameworks */, A0951C401C87A5E5006AB5D7 /* Realm.framework in Embed Frameworks */, A0BC27B11C56DA0000306449 /* RBQFetchedResultsController.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFetchedResultsControllerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 667F38091A5B2682008E3052 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667F380A1A5B2682008E3052 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 667F380C1A5B2682008E3052 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 667F380D1A5B2682008E3052 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 667F38131A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 667F38151A5B2682008E3052 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 667F38181A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFetchedResultsControllerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 667F383D1A5B26C5008E3052 /* TestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObject.h; sourceTree = ""; }; 667F383E1A5B26C5008E3052 /* TestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObject.m; sourceTree = ""; }; 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleTableViewController.h; sourceTree = ""; }; 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleTableViewController.m; sourceTree = ""; }; A0951C3E1C87A5E5006AB5D7 /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = ../../Carthage/Build/iOS/Realm.framework; sourceTree = ""; }; A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RBQFetchedResultsController.xcodeproj; path = ../../RBQFetchedResultsController.xcodeproj; sourceTree = ""; }; F9C9CC441DF6BE1500A85A48 /* RBQSafeRealmObject.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RBQSafeRealmObject.framework; path = ../../Carthage/Build/iOS/RBQSafeRealmObject.framework; sourceTree = ""; }; F9C9CC451DF6BE1500A85A48 /* RealmUtilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmUtilities.framework; path = ../../Carthage/Build/iOS/RealmUtilities.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 667F38021A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F9C9CC4A1DF6BE3400A85A48 /* RBQSafeRealmObject.framework in Frameworks */, F9C9CC4C1DF6BE3400A85A48 /* RealmUtilities.framework in Frameworks */, A0951C3F1C87A5E5006AB5D7 /* Realm.framework in Frameworks */, A0BC27B01C56DA0000306449 /* RBQFetchedResultsController.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381B1A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A0C594D31CCF0D490041A382 /* RBQFetchedResultsController.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 19B744AA72655FFA5B118084 /* Frameworks */ = { isa = PBXGroup; children = ( F9C9CC441DF6BE1500A85A48 /* RBQSafeRealmObject.framework */, F9C9CC451DF6BE1500A85A48 /* RealmUtilities.framework */, A0951C3E1C87A5E5006AB5D7 /* Realm.framework */, A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */, ); name = Frameworks; sourceTree = ""; }; 667F37FC1A5B2682008E3052 = { isa = PBXGroup; children = ( 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F38061A5B2682008E3052 /* Products */, 19B744AA72655FFA5B118084 /* Frameworks */, ); sourceTree = ""; }; 667F38061A5B2682008E3052 /* Products */ = { isa = PBXGroup; children = ( 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */, 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */, ); name = Products; sourceTree = ""; }; 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXGroup; children = ( 667F380C1A5B2682008E3052 /* AppDelegate.h */, 667F380D1A5B2682008E3052 /* AppDelegate.m */, 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */, 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */, 667F383D1A5B26C5008E3052 /* TestObject.h */, 667F383E1A5B26C5008E3052 /* TestObject.m */, 667F38121A5B2682008E3052 /* Main.storyboard */, 667F38151A5B2682008E3052 /* Images.xcassets */, 667F38171A5B2682008E3052 /* LaunchScreen.xib */, 667F38081A5B2682008E3052 /* Supporting Files */, ); path = RBQFetchedResultsControllerExample; sourceTree = ""; }; 667F38081A5B2682008E3052 /* Supporting Files */ = { isa = PBXGroup; children = ( 667F38091A5B2682008E3052 /* Info.plist */, 667F380A1A5B2682008E3052 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; A0FBECAB1C56D6E3006E5109 /* Products */ = { isa = PBXGroup; children = ( A0FBECB01C56D6E3006E5109 /* RBQFetchedResultsController.framework */, A0FBECB21C56D6E3006E5109 /* RBQFetchedResultsController.xctest */, A0951C381C87A50B006AB5D7 /* SwiftFetchedResultsController.framework */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXNativeTarget; buildConfigurationList = 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */; buildPhases = ( 667F38011A5B2682008E3052 /* Sources */, 667F38021A5B2682008E3052 /* Frameworks */, 667F38031A5B2682008E3052 /* Resources */, A092AF9C1C56D79600FD6208 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( A0BC27AF1C56D9E400306449 /* PBXTargetDependency */, A0BC27B31C56DA0000306449 /* PBXTargetDependency */, ); name = RBQFetchedResultsControllerExample; productName = RBQFetchedResultsControllerExample; productReference = 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */; productType = "com.apple.product-type.application"; }; 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */; buildPhases = ( 667F381A1A5B2682008E3052 /* Sources */, 667F381B1A5B2682008E3052 /* Frameworks */, 667F381C1A5B2682008E3052 /* Resources */, ); buildRules = ( ); dependencies = ( 667F38201A5B2682008E3052 /* PBXTargetDependency */, ); name = RBQFetchedResultsControllerExampleTests; productName = RBQFetchedResultsControllerExampleTests; productReference = 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 667F37FD1A5B2682008E3052 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0810; ORGANIZATIONNAME = Roobiq; TargetAttributes = { 667F38041A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; }; 667F381D1A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; TestTargetID = 667F38041A5B2682008E3052; }; }; }; buildConfigurationList = 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 667F37FC1A5B2682008E3052; productRefGroup = 667F38061A5B2682008E3052 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = A0FBECAB1C56D6E3006E5109 /* Products */; ProjectRef = A0FBECAA1C56D6E3006E5109 /* RBQFetchedResultsController.xcodeproj */; }, ); projectRoot = ""; targets = ( 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ A0951C381C87A50B006AB5D7 /* SwiftFetchedResultsController.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = SwiftFetchedResultsController.framework; remoteRef = A0951C371C87A50B006AB5D7 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; A0FBECB01C56D6E3006E5109 /* RBQFetchedResultsController.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = RBQFetchedResultsController.framework; remoteRef = A0FBECAF1C56D6E3006E5109 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; A0FBECB21C56D6E3006E5109 /* RBQFetchedResultsController.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = RBQFetchedResultsController.xctest; remoteRef = A0FBECB11C56D6E3006E5109 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 667F38031A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38141A5B2682008E3052 /* Main.storyboard in Resources */, 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */, 667F38161A5B2682008E3052 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381C1A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 667F38011A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */, 667F38401A5B26C5008E3052 /* TestObject.m in Sources */, 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */, 667F380B1A5B2682008E3052 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381A1A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 667F38201A5B2682008E3052 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */; targetProxy = 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */; }; A0BC27AF1C56D9E400306449 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = RBQFetchedResultsController; targetProxy = A0BC27AE1C56D9E400306449 /* PBXContainerItemProxy */; }; A0BC27B31C56DA0000306449 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = RBQFetchedResultsController; targetProxy = A0BC27B21C56DA0000306449 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 667F38121A5B2682008E3052 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 667F38131A5B2682008E3052 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 667F38171A5B2682008E3052 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( 667F38181A5B2682008E3052 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 667F38261A5B2682008E3052 /* 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; 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.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 667F38271A5B2682008E3052 /* 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 = YES; 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.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 667F38291A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ../../Carthage/Build/iOS/; INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 667F382A1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ../../Carthage/Build/iOS/; INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 667F382C1A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Debug; }; 667F382D1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38261A5B2682008E3052 /* Debug */, 667F38271A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38291A5B2682008E3052 /* Debug */, 667F382A1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F382C1A5B2682008E3052 /* Debug */, 667F382D1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 667F37FD1A5B2682008E3052 /* Project object */; } ================================================ FILE: Examples/ObjC-carthage/RBQFetchedResultsControllerExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/ObjC-cocoapods/Podfile ================================================ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'RBQFetchedResultsControllerExample' do pod 'RBQFetchedResultsController', path: '../../' target 'RBQFetchedResultsControllerExampleTests' do inherit! :search_paths end end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/AppDelegate.h ================================================ // // AppDelegate.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/AppDelegate.m ================================================ // // AppDelegate.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/ExampleTableViewController.h ================================================ // // ExampleTableViewController.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // @import UIKit; @interface ExampleTableViewController : UITableViewController @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/ExampleTableViewController.m ================================================ // // ExampleTableViewController.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "ExampleTableViewController.h" #import "TestObject.h" #import id NULL_IF_NIL(id x) {return x ? x : NSNull.null;} @interface ExampleTableViewController () @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @end @implementation ExampleTableViewController - (void)viewDidLoad { [super viewDidLoad]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [realm addObject:object]; } [realm commitWriteTransaction]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:realm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"testCache"]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return [self.fetchedResultsController numberOfSections]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.fetchedResultsController numberOfRowsForSectionIndex:section]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.fetchedResultsController titleForHeaderInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"customCell" forIndexPath:indexPath]; // Configure the cell... TestObject *objectForCell = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = objectForCell.title; return cell; } // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source [self deleteObjectAtIndexPath:indexPath]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view [self insertObject]; } } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Beginning updates"); [self.tableView beginUpdates]; } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(RBQFetchedResultsSectionInfo *)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { UITableView *tableView = self.tableView; if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); NSIndexSet *insertedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView insertSections:insertedSection withRowAnimation:UITableViewRowAnimationFade]; } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); NSIndexSet *deletedSection = [NSIndexSet indexSetWithIndex:sectionIndex]; [tableView deleteSections:deletedSection withRowAnimation:UITableViewRowAnimationFade]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { NSLog(@"Ending updates"); NSLog(@"Fetched %ld Items After Change", (unsigned long)self.fetchedResultsController.fetchedObjects.count); @try { [self.tableView endUpdates]; } @catch (NSException *ex) { NSLog(@"RBQFecthResultsTVC caught exception updating table view: %@. Falling back to reload.", ex); [self.fetchedResultsController reset]; [self.tableView reloadData]; } } #pragma mark - UIBarButton Actions - (IBAction)didClickDeleteButton:(UIBarButtonItem *)sender { // Delete the object in the first row // NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; // [self deleteObjectAtIndexPath:firstObjectIndexPath]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NSLog(@"DID BEGIN DELETE"); // Test deleting a section (comment out above to test) RLMResults *objectInFirstSection = [TestObject objectsWhere:@"%K == %@",@"sectionName",@"First Section"]; RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObjects:objectInFirstSection]; [realm commitWriteTransaction]; NSLog(@"DID END DELETE"); }); } - (IBAction)didClickInsertButton:(UIBarButtonItem *)sender { NSLog(@"DID BEGIN INSERT"); NSLog(@"Fetched %ld Items Before Insert", (unsigned long)self.fetchedResultsController.fetchedObjects.count); [self insertObject]; NSLog(@"DID END INSERT"); } #pragma mark - Private - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; if (!object) { return; } RLMRealm *realm = [RLMRealm defaultRealm]; [realm beginWriteTransaction]; [realm deleteObject:object]; [realm commitWriteTransaction]; } - (void)insertObject { RLMRealm *realm = [RLMRealm defaultRealm]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; if (object.sortIndex > 0) { [realm beginWriteTransaction]; NSInteger sortIndex = object.sortIndex - 1; NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)sortIndex]; TestObject *newObject = [TestObject objectInRealm:realm forPrimaryKey:[NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]]; if (!newObject) { newObject = [[TestObject alloc] init]; newObject.title = title; newObject.sortIndex = sortIndex; newObject.sectionName = @"First Section"; newObject.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; newObject.inTable = YES; [realm addObject:newObject]; } else { newObject.inTable = YES; } [realm commitWriteTransaction]; } // Test Moves else { [realm beginWriteTransaction]; NSIndexPath *indexPathFifthRow = [NSIndexPath indexPathForRow:5 inSection:0]; NSIndexPath *indexPathThirdRow = [NSIndexPath indexPathForRow:3 inSection:0]; NSIndexPath *indexPathSixthRow = [NSIndexPath indexPathForRow:6 inSection:0]; NSIndexPath *indexPathFirstRow = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *firstObject = [self.fetchedResultsController objectAtIndexPath:indexPathFirstRow]; TestObject *thirdObject = [self.fetchedResultsController objectAtIndexPath:indexPathThirdRow]; TestObject *fifthObject = [self.fetchedResultsController objectAtIndexPath:indexPathFifthRow]; TestObject *sixthObject = [self.fetchedResultsController objectAtIndexPath:indexPathSixthRow]; RLMResults *ninthObject = [TestObject objectsInRealm:realm where:@"%K == %@",@"title",@"Cell 9"]; fifthObject.sortIndex += 1; sixthObject.sortIndex -= 1; firstObject.inTable = NO; thirdObject.title = @"Testing Move And Update"; if (ninthObject.firstObject) { TestObject *object = ninthObject.firstObject; if ([object.sectionName isEqualToString:@"First Section"]) { object.sectionName = @"Second Section"; } else { object.sectionName = @"First Section"; } } //Test an inserted section that's not first // TestObject *extraObjectInSection = [TestObject testObjectWithTitle:@"Test Section" sortIndex:3 inTable:YES]; // extraObjectInSection.sectionName = @"Middle Section"; // [realm addObject:extraObjectInSection]; // // [[RBQRealmNotificationManager defaultManager] didAddObjects:@[extraObjectInSection] // willDeleteObjects:nil // didChangeObjects:@[NULL_IF_NIL(fifthObject), // NULL_IF_NIL(sixthObject), // NULL_IF_NIL(firstObject), // NULL_IF_NIL(thirdObject)]]; [realm commitWriteTransaction]; } } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/TestObject.h ================================================ // // TestObject.h // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import @interface TestObject : RLMObject @property NSString *title; @property NSInteger sortIndex; @property NSString *sectionName; @property NSString *key; @property BOOL inTable; + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable; @end // This protocol enables typed collections. i.e.: // RLMArray RLM_ARRAY_TYPE(TestObject) ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/TestObject.m ================================================ // // TestObject.m // RBQFetchedResultsControllerTest // // Created by Lauren Smith on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "TestObject.h" @implementation TestObject + (NSString *)primaryKey { return @"key"; } // Specify default values for properties //+ (NSDictionary *)defaultPropertyValues //{ // return @{}; //} // Specify properties to ignore (Realm won't persist these) //+ (NSArray *)ignoredProperties //{ // return @[]; //} + (instancetype)testObjectWithTitle:(NSString *)title sortIndex:(NSInteger)sortIndex inTable:(BOOL)inTable { TestObject *object = [[TestObject alloc] init]; object.sortIndex = sortIndex; object.title = title; object.key = [NSString stringWithFormat:@"%@%ld",title, (long)sortIndex]; object.inTable = inTable; return object; } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample/main.m ================================================ // // main.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/5/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 4921A5F91B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */; }; 4921A5FF1B1A781F00CA32B7 /* RBQTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */; }; 49527C091B17F47500C115A3 /* RBQSafeRealmObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */; }; 49527C0F1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */; }; 49527C111B1818CF00C115A3 /* RBQEntityChangesObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49527C101B1818CF00C115A3 /* RBQEntityChangesObjectTests.m */; }; 49DF57321B17B09900BA8DDC /* RBQFetchRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */; }; 49DF57331B17B09900BA8DDC /* RBQRealmChangeLoggerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DF57311B17B09900BA8DDC /* RBQRealmChangeLoggerTests.m */; }; 660F4C0A1B19413B00492DAE /* RBQFetchRequestInMemoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */; }; 662C46951A623B6200A8D145 /* RBQFetchedResultsControllerDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 662C46941A623B6200A8D145 /* RBQFetchedResultsControllerDelegateTests.m */; }; 667F380B1A5B2682008E3052 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380A1A5B2682008E3052 /* main.m */; }; 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F380D1A5B2682008E3052 /* AppDelegate.m */; }; 667F38141A5B2682008E3052 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 667F38121A5B2682008E3052 /* Main.storyboard */; }; 667F38161A5B2682008E3052 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 667F38151A5B2682008E3052 /* Images.xcassets */; }; 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 667F38171A5B2682008E3052 /* LaunchScreen.xib */; }; 667F38401A5B26C5008E3052 /* TestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F383E1A5B26C5008E3052 /* TestObject.m */; }; 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */; }; B7C8573C3830C6731BA361C1 /* libPods-RBQFetchedResultsControllerExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7709CA864C22F985095ED7F8 /* libPods-RBQFetchedResultsControllerExampleTests.a */; }; E1938404D3F347DA2566D140 /* libPods-RBQFetchedResultsControllerExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F2684C1DA2F8DDE9DF59603 /* libPods-RBQFetchedResultsControllerExample.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 667F37FD1A5B2682008E3052 /* Project object */; proxyType = 1; remoteGlobalIDString = 667F38041A5B2682008E3052; remoteInfo = RBQFetchedResultsControllerExample; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsControllerTests.m; sourceTree = ""; }; 4921A5FD1B1A781F00CA32B7 /* RBQTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQTestCase.h; sourceTree = ""; }; 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQTestCase.m; sourceTree = ""; }; 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQSafeRealmObjectTests.m; sourceTree = ""; }; 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsSectionInfoTests.m; sourceTree = ""; }; 49527C101B1818CF00C115A3 /* RBQEntityChangesObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQEntityChangesObjectTests.m; sourceTree = ""; }; 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchRequestTests.m; sourceTree = ""; }; 49DF57311B17B09900BA8DDC /* RBQRealmChangeLoggerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQRealmChangeLoggerTests.m; sourceTree = ""; }; 4E25AEFAD0B0D6D0EA5FCDD3 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig"; sourceTree = ""; }; 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchRequestInMemoryTests.m; sourceTree = ""; }; 662C46941A623B6200A8D145 /* RBQFetchedResultsControllerDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQFetchedResultsControllerDelegateTests.m; sourceTree = ""; }; 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFetchedResultsControllerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 667F38091A5B2682008E3052 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667F380A1A5B2682008E3052 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 667F380C1A5B2682008E3052 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 667F380D1A5B2682008E3052 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 667F38131A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 667F38151A5B2682008E3052 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 667F38181A5B2682008E3052 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFetchedResultsControllerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 667F38231A5B2682008E3052 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 667F383D1A5B26C5008E3052 /* TestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObject.h; sourceTree = ""; }; 667F383E1A5B26C5008E3052 /* TestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObject.m; sourceTree = ""; }; 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleTableViewController.h; sourceTree = ""; }; 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleTableViewController.m; sourceTree = ""; }; 6F2684C1DA2F8DDE9DF59603 /* libPods-RBQFetchedResultsControllerExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RBQFetchedResultsControllerExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7709CA864C22F985095ED7F8 /* libPods-RBQFetchedResultsControllerExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RBQFetchedResultsControllerExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 8CAE229C2AD33311A81574FC /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig"; sourceTree = ""; }; C3BC6C0E1DFD67B590EF054C /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample.debug.xcconfig"; sourceTree = ""; }; F522D106517B0E6B45AF3A92 /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFetchedResultsControllerExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 667F38021A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E1938404D3F347DA2566D140 /* libPods-RBQFetchedResultsControllerExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381B1A5B2682008E3052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( B7C8573C3830C6731BA361C1 /* libPods-RBQFetchedResultsControllerExampleTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 667F37FC1A5B2682008E3052 = { isa = PBXGroup; children = ( 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F38211A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */, 667F38061A5B2682008E3052 /* Products */, F195ADCA5FE615DCF6039F48 /* Pods */, E8F471E218FD6EB79AAD66CB /* Frameworks */, ); sourceTree = ""; }; 667F38061A5B2682008E3052 /* Products */ = { isa = PBXGroup; children = ( 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */, 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */, ); name = Products; sourceTree = ""; }; 667F38071A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXGroup; children = ( 667F380C1A5B2682008E3052 /* AppDelegate.h */, 667F380D1A5B2682008E3052 /* AppDelegate.m */, 667F38411A5B27E4008E3052 /* ExampleTableViewController.h */, 667F38421A5B27E4008E3052 /* ExampleTableViewController.m */, 667F383D1A5B26C5008E3052 /* TestObject.h */, 667F383E1A5B26C5008E3052 /* TestObject.m */, 667F38121A5B2682008E3052 /* Main.storyboard */, 667F38151A5B2682008E3052 /* Images.xcassets */, 667F38171A5B2682008E3052 /* LaunchScreen.xib */, 667F38081A5B2682008E3052 /* Supporting Files */, ); path = RBQFetchedResultsControllerExample; sourceTree = ""; }; 667F38081A5B2682008E3052 /* Supporting Files */ = { isa = PBXGroup; children = ( 667F38091A5B2682008E3052 /* Info.plist */, 667F380A1A5B2682008E3052 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 667F38211A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */ = { isa = PBXGroup; children = ( 4921A5FD1B1A781F00CA32B7 /* RBQTestCase.h */, 4921A5FE1B1A781F00CA32B7 /* RBQTestCase.m */, 4921A5F81B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m */, 662C46941A623B6200A8D145 /* RBQFetchedResultsControllerDelegateTests.m */, 49DF57301B17B09900BA8DDC /* RBQFetchRequestTests.m */, 660F4C091B19413B00492DAE /* RBQFetchRequestInMemoryTests.m */, 49DF57311B17B09900BA8DDC /* RBQRealmChangeLoggerTests.m */, 49527C081B17F47500C115A3 /* RBQSafeRealmObjectTests.m */, 49527C0E1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m */, 49527C101B1818CF00C115A3 /* RBQEntityChangesObjectTests.m */, 667F38221A5B2682008E3052 /* Supporting Files */, ); path = RBQFetchedResultsControllerExampleTests; sourceTree = ""; }; 667F38221A5B2682008E3052 /* Supporting Files */ = { isa = PBXGroup; children = ( 667F38231A5B2682008E3052 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; E8F471E218FD6EB79AAD66CB /* Frameworks */ = { isa = PBXGroup; children = ( 6F2684C1DA2F8DDE9DF59603 /* libPods-RBQFetchedResultsControllerExample.a */, 7709CA864C22F985095ED7F8 /* libPods-RBQFetchedResultsControllerExampleTests.a */, ); name = Frameworks; sourceTree = ""; }; F195ADCA5FE615DCF6039F48 /* Pods */ = { isa = PBXGroup; children = ( C3BC6C0E1DFD67B590EF054C /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */, F522D106517B0E6B45AF3A92 /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */, 4E25AEFAD0B0D6D0EA5FCDD3 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */, 8CAE229C2AD33311A81574FC /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */ = { isa = PBXNativeTarget; buildConfigurationList = 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */; buildPhases = ( B0DA5EE2877FCBCE2F6FD3E4 /* [CP] Check Pods Manifest.lock */, 667F38011A5B2682008E3052 /* Sources */, 667F38021A5B2682008E3052 /* Frameworks */, 667F38031A5B2682008E3052 /* Resources */, 23E874D43B022E36F548D0E4 /* [CP] Embed Pods Frameworks */, F248AEAAEA8558AA9BA0043A /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = RBQFetchedResultsControllerExample; productName = RBQFetchedResultsControllerExample; productReference = 667F38051A5B2682008E3052 /* RBQFetchedResultsControllerExample.app */; productType = "com.apple.product-type.application"; }; 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */; buildPhases = ( 8990FF0F58865A1BF2A78256 /* [CP] Check Pods Manifest.lock */, 667F381A1A5B2682008E3052 /* Sources */, 667F381B1A5B2682008E3052 /* Frameworks */, 667F381C1A5B2682008E3052 /* Resources */, 2BB6C38536FC1B9F4628DF61 /* [CP] Embed Pods Frameworks */, 4119263906E92044B3F7C0D0 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 667F38201A5B2682008E3052 /* PBXTargetDependency */, ); name = RBQFetchedResultsControllerExampleTests; productName = RBQFetchedResultsControllerExampleTests; productReference = 667F381E1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 667F37FD1A5B2682008E3052 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0810; ORGANIZATIONNAME = Roobiq; TargetAttributes = { 667F38041A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; }; 667F381D1A5B2682008E3052 = { CreatedOnToolsVersion = 6.1.1; TestTargetID = 667F38041A5B2682008E3052; }; }; }; buildConfigurationList = 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 667F37FC1A5B2682008E3052; productRefGroup = 667F38061A5B2682008E3052 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */, 667F381D1A5B2682008E3052 /* RBQFetchedResultsControllerExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 667F38031A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38141A5B2682008E3052 /* Main.storyboard in Resources */, 667F38191A5B2682008E3052 /* LaunchScreen.xib in Resources */, 667F38161A5B2682008E3052 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381C1A5B2682008E3052 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 23E874D43B022E36F548D0E4 /* [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-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 2BB6C38536FC1B9F4628DF61 /* [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-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 4119263906E92044B3F7C0D0 /* [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-RBQFetchedResultsControllerExampleTests/Pods-RBQFetchedResultsControllerExampleTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; 8990FF0F58865A1BF2A78256 /* [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; }; B0DA5EE2877FCBCE2F6FD3E4 /* [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; }; F248AEAAEA8558AA9BA0043A /* [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-RBQFetchedResultsControllerExample/Pods-RBQFetchedResultsControllerExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 667F38011A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 667F38431A5B27E4008E3052 /* ExampleTableViewController.m in Sources */, 667F38401A5B26C5008E3052 /* TestObject.m in Sources */, 667F380E1A5B2682008E3052 /* AppDelegate.m in Sources */, 667F380B1A5B2682008E3052 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 667F381A1A5B2682008E3052 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 660F4C0A1B19413B00492DAE /* RBQFetchRequestInMemoryTests.m in Sources */, 49527C0F1B18144C00C115A3 /* RBQFetchedResultsSectionInfoTests.m in Sources */, 49DF57321B17B09900BA8DDC /* RBQFetchRequestTests.m in Sources */, 49DF57331B17B09900BA8DDC /* RBQRealmChangeLoggerTests.m in Sources */, 49527C091B17F47500C115A3 /* RBQSafeRealmObjectTests.m in Sources */, 4921A5F91B1A643500CA32B7 /* RBQFetchedResultsControllerTests.m in Sources */, 662C46951A623B6200A8D145 /* RBQFetchedResultsControllerDelegateTests.m in Sources */, 4921A5FF1B1A781F00CA32B7 /* RBQTestCase.m in Sources */, 49527C111B1818CF00C115A3 /* RBQEntityChangesObjectTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 667F38201A5B2682008E3052 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 667F38041A5B2682008E3052 /* RBQFetchedResultsControllerExample */; targetProxy = 667F381F1A5B2682008E3052 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 667F38121A5B2682008E3052 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 667F38131A5B2682008E3052 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 667F38171A5B2682008E3052 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( 667F38181A5B2682008E3052 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 667F38261A5B2682008E3052 /* 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; 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.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 667F38271A5B2682008E3052 /* 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 = YES; 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.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 667F38291A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = C3BC6C0E1DFD67B590EF054C /* Pods-RBQFetchedResultsControllerExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 667F382A1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F522D106517B0E6B45AF3A92 /* Pods-RBQFetchedResultsControllerExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = RBQFetchedResultsControllerExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 667F382C1A5B2682008E3052 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4E25AEFAD0B0D6D0EA5FCDD3 /* Pods-RBQFetchedResultsControllerExampleTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Debug; }; 667F382D1A5B2682008E3052 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 8CAE229C2AD33311A81574FC /* Pods-RBQFetchedResultsControllerExampleTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFetchedResultsControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Roobiq.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFetchedResultsControllerExample.app/RBQFetchedResultsControllerExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 667F38001A5B2682008E3052 /* Build configuration list for PBXProject "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38261A5B2682008E3052 /* Debug */, 667F38271A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F38281A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F38291A5B2682008E3052 /* Debug */, 667F382A1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 667F382B1A5B2682008E3052 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 667F382C1A5B2682008E3052 /* Debug */, 667F382D1A5B2682008E3052 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 667F37FD1A5B2682008E3052 /* Project object */; } ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQEntityChangesObjectTests.m ================================================ // // RBQEntityChangesObjectTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/28. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQRealmNotificationManager.h" #import "TestObject.h" #import "RBQSafeRealmObject.h" @interface RBQEntityChangesObjectTests : XCTestCase @end @implementation RBQEntityChangesObjectTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } #pragma mark - Utility #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" - (RBQEntityChangesObject *)createEntityChangesObject { SEL selector = NSSelectorFromString(@"createEntityChangeObjectWithClassName:"); RBQEntityChangesObject *entityChangesObject = [[RBQEntityChangesObject class] performSelector:selector withObject:@"TestObject"]; return entityChangesObject; } #pragma mark - Test Case - (void)testInitializeEntityChangesObject { RBQEntityChangesObject *entityChangesObject = [self createEntityChangesObject]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert([entityChangesObject.addedSafeObjects isKindOfClass:[NSSet class]]); XCTAssert([entityChangesObject.deletedSafeObjects isKindOfClass:[NSSet class]]); XCTAssert([entityChangesObject.changedSafeObjects isKindOfClass:[NSSet class]]); } - (void)testDidAddSafeObject { RBQEntityChangesObject *entityChangesObject = [self createEntityChangesObject]; SEL selector = NSSelectorFromString(@"didAddSafeObject:"); RBQSafeRealmObject *safeObject = [[RBQSafeRealmObject alloc] initWithClassName:@"TestObject" primaryKeyValue:@"key" primaryKeyType:RLMPropertyTypeString realm:[RLMRealm defaultRealm]]; XCTAssert(entityChangesObject.addedSafeObjects.count == 0); [entityChangesObject performSelector:selector withObject:safeObject]; XCTAssert(entityChangesObject.addedSafeObjects.count == 1); } - (void)testWillDeleteSafeObject { RBQEntityChangesObject *entityChangesObject = [self createEntityChangesObject]; SEL selector = NSSelectorFromString(@"willDeleteSafeObject:"); RBQSafeRealmObject *safeObject = [[RBQSafeRealmObject alloc] initWithClassName:@"TestObject" primaryKeyValue:@"key" primaryKeyType:RLMPropertyTypeString realm:[RLMRealm defaultRealm]]; XCTAssert(entityChangesObject.deletedSafeObjects.count == 0); [entityChangesObject performSelector:selector withObject:safeObject]; XCTAssert(entityChangesObject.deletedSafeObjects.count == 1); } - (void)testDidChangeSafeObject { RBQEntityChangesObject *entityChangesObject = [self createEntityChangesObject]; SEL selector = NSSelectorFromString(@"didChangeSafeObject:"); RBQSafeRealmObject *safeObject = [[RBQSafeRealmObject alloc] initWithClassName:@"TestObject" primaryKeyValue:@"key" primaryKeyType:RLMPropertyTypeString realm:[RLMRealm defaultRealm]]; XCTAssert(entityChangesObject.changedSafeObjects.count == 0); [entityChangesObject performSelector:selector withObject:safeObject]; XCTAssert(entityChangesObject.changedSafeObjects.count == 1); } #pragma clang diagnostic pop @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQFetchRequestInMemoryTests.m ================================================ // // RBQFetchRequestInMemoryTests.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 5/29/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import #import "RBQFetchRequest.h" #import #import "TestObject.h" @interface RBQFetchRequestInMemoryTests : XCTestCase @property (strong, nonatomic) RLMRealm *inMemoryRealm; @end @implementation RBQFetchRequestInMemoryTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. // Setup the DB (use random strings to create new versions each time) RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.inMemoryRealm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; [self.inMemoryRealm transactionWithBlock:^{ [self.inMemoryRealm deleteAllObjects]; for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.inTable = YES; } else { testObject.inTable = NO; } [self.inMemoryRealm addObject:testObject]; } }]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; RLMRealm *realm = self.inMemoryRealm; [realm transactionWithBlock:^{ [realm deleteAllObjects]; }]; } - (void)testVerifyEnityNameObjC { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; XCTAssert([fetchRequest.entityName isEqualToString:@"TestObject"]); } // TODO: testVerifyEntityNameSwift - (void)testFetchObjects { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; id results = [fetchRequest fetchObjects]; TestObject *firstObject = results.firstObject; XCTAssert(results.count == 5); XCTAssert([firstObject.key isEqualToString:@"key0"]); } - (void)testEvaluateObject { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = YES; XCTAssert([fetchRequest evaluateObject:testObject]); } - (void)testEvaluateObjectFailed { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = NO; XCTAssertFalse([fetchRequest evaluateObject:testObject]); } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQFetchRequestTests.m ================================================ // // RBQFetchRequestTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/27. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQFetchRequest.h" #import #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchRequestTests : RBQTestCase @end @implementation RBQFetchRequestTests - (void)testVerifyEnityNameObjC { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; XCTAssert([fetchRequest.entityName isEqualToString:@"TestObject"]); } // TODO: testVerifyEntityNameSwift - (void)testFetchObjects { [self insertDifferentInTableTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; id results = [fetchRequest fetchObjects]; TestObject *firstObject = results.firstObject; XCTAssert(results.count == 5); XCTAssert([firstObject.key isEqualToString:@"key0"]); } - (void)testEvaluateObject { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = YES; XCTAssert([fetchRequest evaluateObject:testObject]); } - (void)testEvaluateObjectFailed { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.inTable = NO; XCTAssertFalse([fetchRequest evaluateObject:testObject]); } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsControllerDelegateTests.m ================================================ // // RBQFetchedResultsControllerDelegateTests.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/10/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import #import "RBQFetchedResultsController.h" #import "RBQRealmNotificationManager.h" #import "RLMRealm+Notifications.h" #import "TestObject.h" @interface RBQFetchedResultsControllerDelegateTests : XCTestCase @property (strong, nonatomic) XCTestExpectation *controllerWillChangeContentExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeObjectExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeSectionExpectation; @property (strong, nonatomic) XCTestExpectation *controllerDidChangeContentExpectation; @property (strong, nonatomic) RLMRealm *inMemoryRealm; @property (strong, nonatomic) RBQFetchedResultsController *fetchedResultsController; @property (assign, nonatomic) NSUInteger count; @end @implementation RBQFetchedResultsControllerDelegateTests - (void)setUp { [super setUp]; // Setup the DB (use random strings to create new versions each time) RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.inMemoryRealm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; // Load the DB with data [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteAllObjects]; for (NSUInteger i = 0; i < 1000; i++) { NSString *title = [NSString stringWithFormat:@"Cell %lu", (unsigned long)i]; TestObject *object = [TestObject testObjectWithTitle:title sortIndex:i inTable:YES]; if (i < 10) { object.sectionName = @"First Section"; } else { object.sectionName = @"Second Section"; } [self.inMemoryRealm addObject:object]; } [self.inMemoryRealm commitWriteTransaction]; // Setup the FRC NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:self.inMemoryRealm predicate:predicate]; RLMSortDescriptor *sortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sortIndex" ascending:YES]; RLMSortDescriptor *sortDescriptorSection = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptorSection,sortDescriptor]; self.fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:nil]; self.fetchedResultsController.delegate = self; [self.fetchedResultsController performFetch]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; self.controllerWillChangeContentExpectation = nil; self.controllerDidChangeObjectExpectation = nil; self.controllerDidChangeSectionExpectation = nil; self.controllerDidChangeContentExpectation = nil; self.fetchedResultsController = nil; self.count = 0; } - (void)testControllerWillChangeContent { self.controllerWillChangeContentExpectation = [self expectationWithDescription:@"FRC Will Change Content Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeObject { self.controllerDidChangeObjectExpectation = [self expectationWithDescription:@"FRC Did Change Object Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeSection { self.controllerDidChangeObjectExpectation = [self expectationWithDescription:@"FRC Did Change Object Fired"]; self.controllerDidChangeSectionExpectation = [self expectationWithDescription:@"FRC Did Change Section Fired"]; self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; // Test deleting a section RLMResults *objectInFirstSection = [TestObject objectsInRealm:self.inMemoryRealm where:@"%K == %@",@"sectionName",@"First Section"]; [self.inMemoryRealm beginWriteTransaction]; [self.inMemoryRealm deleteObjectsWithNotification:objectInFirstSection]; [self.inMemoryRealm commitWriteTransaction]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } - (void)testControllerDidChangeContent { self.controllerDidChangeContentExpectation = [self expectationWithDescription:@"FRC Did Change Content Fired"]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self deleteObjectAtIndexPath:indexPath]; [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) { XCTAssertNil(error, @"%@", error.localizedDescription); }]; } #pragma - Actions - (void)deleteObjectAtIndexPath:(NSIndexPath *)indexPath { TestObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.inMemoryRealm beginWriteTransaction]; [[RBQRealmChangeLogger loggerForRealm:self.inMemoryRealm] willDeleteObject:object]; [self.inMemoryRealm deleteObject:object]; [self.inMemoryRealm commitWriteTransaction]; } #pragma mark - - (void)controllerWillChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerWillChangeContentExpectation) { [self.controllerWillChangeContentExpectation fulfill]; } } - (void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: { NSLog(@"Inserting at path %@", newIndexPath); break; } case NSFetchedResultsChangeDelete: { NSLog(@"Deleting at path %ld", (long)indexPath.row); break; } case NSFetchedResultsChangeUpdate: NSLog(@"Updating at path %@", indexPath); break; case NSFetchedResultsChangeMove: NSLog(@"Moving from path %@ to %@", indexPath, newIndexPath); break; } // Fulfilling an expectation prematurely seems to cause problems if (self.controllerDidChangeObjectExpectation && !self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeObjectExpectation fulfill]; } else if (self.controllerDidChangeObjectExpectation && self.controllerDidChangeSectionExpectation) { self.count ++; if (self.count == 10) { [self.controllerDidChangeObjectExpectation fulfill]; } } } - (void)controller:(RBQFetchedResultsController *)controller didChangeSection:(NSString *)sectionName atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { if (type == NSFetchedResultsChangeInsert) { NSLog(@"Inserting section at %lu", (unsigned long)sectionIndex); } else if (type == NSFetchedResultsChangeDelete) { NSLog(@"Deleting section at %lu", (unsigned long)sectionIndex); } if (self.controllerDidChangeSectionExpectation) { [self.controllerDidChangeSectionExpectation fulfill]; } } - (void)controllerDidChangeContent:(RBQFetchedResultsController *)controller { if (self.controllerDidChangeContentExpectation) { [self.controllerDidChangeContentExpectation fulfill]; } } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsControllerTests.m ================================================ // // RBQFetchedResultsControllerTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/29. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import #import "RBQFetchedResultsController.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchedResultsControllerTests : RBQTestCase @end @implementation RBQFetchedResultsControllerTests - (void)testPerformFetch { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert([fetchedResultsController numberOfSections] == 2); XCTAssert([fetchedResultsController.sectionNameKeyPath isEqualToString:@"sectionName"]); XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); } - (void)testPeformFetchWithoutSortDescriptor { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert([fetchedResultsController numberOfSections] == 10); XCTAssert([fetchedResultsController.sectionNameKeyPath isEqualToString:@"sectionName"]); XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); } - (void)testDeleteWithCacheName { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; TestObject *testObject = [fetchedResultsController objectAtIndexPath:indexPath]; XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); XCTAssert([testObject.sectionName isEqualToString:@"section 1"]); XCTAssert(testObject.sortIndex == 0); [RBQFetchedResultsController deleteCacheWithName:@"cache"]; XCTAssert([fetchedResultsController.cacheName isEqualToString:@"cache"]); XCTAssert(fetchedResultsController.fetchedObjects.count == 10); XCTAssertNil([fetchedResultsController objectAtIndexPath:indexPath]); } // TODO: - deleteWithCacheName pass nil - (void)testUpdateFetchRequestSectionNameKeyPathAndPeformFetch { [self insertDifferentSectionNameTestObject]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; RLMSortDescriptor *sectionNameSortDescriptor = [RLMSortDescriptor sortDescriptorWithProperty:@"sectionName" ascending:YES]; fetchRequest.sortDescriptors = @[sectionNameSortDescriptor]; RBQFetchedResultsController *fetchedResultsController = [[RBQFetchedResultsController alloc] initWithFetchRequest:fetchRequest sectionNameKeyPath:@"sectionName" cacheName:@"cache"]; [fetchedResultsController performFetch]; XCTAssert(fetchedResultsController.fetchedObjects.count == 10); NSPredicate *anotherPredicate = [NSPredicate predicateWithFormat:@"inTable = NO"]; RBQFetchRequest *anotherFetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate: anotherPredicate]; [fetchedResultsController updateFetchRequest:anotherFetchRequest sectionNameKeyPath:@"sectionName" andPeformFetch:YES]; XCTAssert(fetchedResultsController.fetchedObjects.count == 0); } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQFetchedResultsSectionInfoTests.m ================================================ // // RBQFetchedResultsSectionInfoTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/28. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQFetchedResultsController.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQFetchedResultsSectionInfoTests : RBQTestCase @end @implementation RBQFetchedResultsSectionInfoTests #pragma mark - Utility - (RBQFetchedResultsSectionInfo *)createFetchedResultsSectionInfo { SEL selector = NSSelectorFromString(@"createSectionWithName:sectionNameKeyPath:fetchRequest:"); NSMethodSignature *signature = [[RBQFetchedResultsSectionInfo class] methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setSelector:selector]; [invocation setTarget:[RBQFetchedResultsSectionInfo class]]; NSString *sectionName = @"section 1"; NSString *sectionNameKeyPath = @"sectionName"; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inTable = YES"]; RBQFetchRequest *fetchRequest = [RBQFetchRequest fetchRequestWithEntityName:@"TestObject" inRealm:[RLMRealm defaultRealm] predicate:predicate]; [invocation setArgument:§ionName atIndex:2]; [invocation setArgument:§ionNameKeyPath atIndex:3]; [invocation setArgument:&fetchRequest atIndex:4]; [invocation invoke]; RBQFetchedResultsSectionInfo __unsafe_unretained *sectionInfo; [invocation getReturnValue:§ionInfo]; return sectionInfo; } #pragma mark - Test Case - (void)testInitializeFetchedResultsSectionInfo { RBQFetchedResultsSectionInfo *sectionInfo = [self createFetchedResultsSectionInfo]; XCTAssertNotNil(sectionInfo); XCTAssert([sectionInfo isKindOfClass:[RBQFetchedResultsSectionInfo class]]); } - (void)testObjectsProperty { [self insertDifferentSectionNameTestObject]; RBQFetchedResultsSectionInfo *sectionInfo = [self createFetchedResultsSectionInfo]; id results = sectionInfo.objects; XCTAssert(sectionInfo.numberOfObjects == 5); XCTAssert(results.count == 5); for (TestObject *testObject in results) { XCTAssert([testObject.sectionName isEqualToString:@"section 1"]); XCTAssert(testObject.inTable == YES); } } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQRealmChangeLoggerTests.m ================================================ // // RBQRealmChangeLoggerTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/27. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQRealmNotificationManager.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQRealmChangeLoggerTests : RBQTestCase @end @implementation RBQRealmChangeLoggerTests - (void)testDidAddObject { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger didAddObject:testObject]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 1); XCTAssert(entityChangesObject.deletedSafeObjects.count == 0); XCTAssert(entityChangesObject.changedSafeObjects.count == 0); } - (void)testDidAddObjects { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject1 = [[TestObject alloc] init]; TestObject *testObject2 = [[TestObject alloc] init]; TestObject *testObject3 = [[TestObject alloc] init]; testObject1.key = @"key1"; testObject2.key = @"key2"; testObject3.key = @"key3"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger didAddObjects:@[testObject1, testObject2, testObject3]]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 3); XCTAssert(entityChangesObject.deletedSafeObjects.count == 0); XCTAssert(entityChangesObject.changedSafeObjects.count == 0); } - (void)testWillDeleteObject { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger willDeleteObject:testObject]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 0); XCTAssert(entityChangesObject.deletedSafeObjects.count == 1); XCTAssert(entityChangesObject.changedSafeObjects.count == 0); } - (void)testWillDeleteObjects { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject1 = [[TestObject alloc] init]; TestObject *testObject2 = [[TestObject alloc] init]; TestObject *testObject3 = [[TestObject alloc] init]; testObject1.key = @"key1"; testObject2.key = @"key2"; testObject3.key = @"key3"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger willDeleteObjects:@[testObject1, testObject2, testObject3]]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 0); XCTAssert(entityChangesObject.deletedSafeObjects.count == 3); XCTAssert(entityChangesObject.changedSafeObjects.count == 0); } - (void)testDidChangeObject { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger didChangeObject:testObject]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 0); XCTAssert(entityChangesObject.deletedSafeObjects.count == 0); XCTAssert(entityChangesObject.changedSafeObjects.count == 1); } - (void)testDidChangeObjects { RBQRealmChangeLogger *logger = [RBQRealmChangeLogger defaultLogger]; TestObject *testObject1 = [[TestObject alloc] init]; TestObject *testObject2 = [[TestObject alloc] init]; TestObject *testObject3 = [[TestObject alloc] init]; testObject1.key = @"key1"; testObject2.key = @"key2"; testObject3.key = @"key3"; XCTAssert(logger.entityChanges.allKeys.count == 0); [logger didChangeObjects:@[testObject1, testObject2, testObject3]]; NSDictionary *entityChanges = logger.entityChanges; RBQEntityChangesObject *entityChangesObject = entityChanges[@"TestObject"]; XCTAssert([entityChangesObject.className isEqualToString:@"TestObject"]); XCTAssert(entityChangesObject.addedSafeObjects.count == 0); XCTAssert(entityChangesObject.deletedSafeObjects.count == 0); XCTAssert(entityChangesObject.changedSafeObjects.count == 3); } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQSafeRealmObjectTests.m ================================================ // // RBQSafeRealmObjectTests.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/28. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import #import "RBQSafeRealmObject.h" #import "TestObject.h" #import "RBQTestCase.h" @interface RBQSafeRealmObjectTests : RBQTestCase @end @implementation RBQSafeRealmObjectTests - (void)testInitializeSafeObject { RBQSafeRealmObject *safeObject = [[RBQSafeRealmObject alloc] initWithClassName:@"TestObject" primaryKeyValue:@"key" primaryKeyType:RLMPropertyTypeString realm:[RLMRealm defaultRealm]]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); } - (void)testSafeObjectFromObjectIfObjectIsPersisted { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); } - (void)testSafeObjectFromObjectIfObjectIsNotPersisted { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssertNil(safeObject.realmConfiguration); } - (void)testThreadSafe { XCTestExpectation *anotherThreadExpectation = [self expectationWithDescription:@"Wait the execution of antoher thread"]; TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ XCTAssert([safeObject.className isEqualToString:@"TestObject"]); XCTAssert([safeObject.primaryKeyValue isEqualToString:@"key"]); XCTAssert(safeObject.primaryKeyType == RLMPropertyTypeString); XCTAssert([safeObject.realm isEqual:[RLMRealm defaultRealm]]); [anotherThreadExpectation fulfill]; }); [self waitForExpectationsWithTimeout:5 handler:nil]; } - (void)testRLMRealmProperty { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; TestObject *fetchedObject = [TestObject allObjects].firstObject; RBQSafeRealmObject *safeObject = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject.RLMObject isEqualToObject:fetchedObject]); } - (void)testIsEqualToObject { TestObject *testObject = [[TestObject alloc] init]; testObject.key = @"key"; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = 0; testObject.inTable = YES; RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ [realm addObject:testObject]; }]; TestObject *fetchedObject = [TestObject allObjects].firstObject; RBQSafeRealmObject *safeObject1 = [RBQSafeRealmObject safeObjectFromObject:fetchedObject]; RBQSafeRealmObject *safeObject2 = [RBQSafeRealmObject safeObjectFromObject:testObject]; XCTAssert([safeObject1 isEqualToObject:safeObject2]); } @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQTestCase.h ================================================ // // RBQTestCase.h // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/30. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import @interface RBQTestCase : XCTestCase @property (nonatomic) BOOL inMemory; - (void)insertDifferentSectionNameTestObject; - (void)insertDifferentInTableTestObject; @end ================================================ FILE: Examples/ObjC-cocoapods/RBQFetchedResultsControllerExampleTests/RBQTestCase.m ================================================ // // RBQTestCase.m // RBQFetchedResultsControllerExample // // Created by AsanoYuki on 2015/05/30. // Copyright (c) 2015年 Roobiq. All rights reserved. // #import "RBQTestCase.h" #import #import "TestObject.h" static NSString *testRealmFileName = @"test.realm"; @interface RBQTestCase() @property (nonatomic, strong) RLMRealm *realm; @end @implementation RBQTestCase - (void)setUp { [super setUp]; NSArray *writablePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsPath = [writablePaths lastObject]; NSString *testRealmFile = [documentsPath stringByAppendingPathComponent:testRealmFileName]; RLMRealmConfiguration *defaultConfig = [RLMRealmConfiguration defaultConfiguration]; defaultConfig.path = testRealmFile; [RLMRealmConfiguration setDefaultConfiguration:defaultConfig]; if (self.inMemory) { RLMRealmConfiguration *inMemoryConfig = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfig.inMemoryIdentifier = [[NSProcessInfo processInfo] globallyUniqueString]; self.realm = [RLMRealm realmWithConfiguration:inMemoryConfig error:nil]; } else { self.realm = [RLMRealm defaultRealm]; } [self.realm transactionWithBlock:^{ [[RLMRealm defaultRealm] deleteAllObjects]; }]; } - (void)tearDown { [super tearDown]; [self.realm transactionWithBlock:^{ [[RLMRealm defaultRealm] deleteAllObjects]; }]; } #pragma mark - Insert objects in Realm - (void)insertDifferentSectionNameTestObject { [self.realm transactionWithBlock:^{ for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.inTable = YES; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.sectionName = @"section 1"; } else { testObject.sectionName = @"section 2"; } [[RLMRealm defaultRealm] addObject:testObject]; } }]; } - (void)insertDifferentInTableTestObject { [self.realm transactionWithBlock:^{ for (int i=0; i < 10; i++) { TestObject *testObject = [[TestObject alloc] init]; testObject.key = [NSString stringWithFormat:@"key%d", i]; testObject.sectionName = @"sectionName"; testObject.title = @"title"; testObject.sortIndex = i; if (i % 2 == 0) { testObject.inTable = YES; } else { testObject.inTable = NO; } [[RLMRealm defaultRealm] addObject:testObject]; } }]; } @end ================================================ FILE: Examples/Swift/.swift-version ================================================ 3.0.1 ================================================ FILE: Examples/Swift/Podfile ================================================ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! inhibit_all_warnings! target 'RBQFRCSwiftExample' do pod 'RealmUtilities' pod 'SafeRealmObject' target 'RBQFRCSwiftExampleTests' do inherit! :search_paths end end ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/AppDelegate.swift ================================================ // // AppDelegate.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/MainTableViewController.swift ================================================ // // MainTableViewController.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/31/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import SafeRealmObject import UIKit import Realm import RealmSwift // MARK: - class TestObject: Object { @objc dynamic var title = "" @objc dynamic var sortIndex = 0 @objc dynamic var sectionName = "" @objc dynamic var key = "" @objc dynamic var inTable: Bool = false override class func primaryKey() -> String? { return "key" } class func testObject(_ title: String, sortIndex: Int, inTable: Bool) -> TestObject { let object = TestObject() object.title = title object.sortIndex = sortIndex object.inTable = inTable object.key = "\(title)\(sortIndex)" return object } } // MARK: - class MainTableViewController: UITableViewController { var fetchedResultsController: FetchedResultsController? var realm: Realm? override func viewDidLoad() { super.viewDidLoad() let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "Test")) self.realm = realm realm.beginWrite() realm.deleteAll() for index in 1...1000 { let title = "Cell \(index)" let object = TestObject.testObject(title, sortIndex: index, inTable: true) if (index < 10) { object.sectionName = "First Section" } else { object.sectionName = "Second Section" } realm.add(object, update: false) } try! realm.commitWrite() let predicate = NSPredicate(format: "inTable = YES") let fetchRequest = FetchRequest(realm: realm, predicate: predicate) let sortDescriptor = SortDescriptor(keyPath: "sortIndex", ascending: true) let sortDescriptorSection = SortDescriptor(keyPath: "sectionName", ascending: true) fetchRequest.sortDescriptors = [sortDescriptorSection, sortDescriptor] self.fetchedResultsController = FetchedResultsController(fetchRequest: fetchRequest, sectionNameKeyPath: "sectionName", cacheName: "testCache") self.fetchedResultsController!.delegate = self let _ = self.fetchedResultsController!.performFetch() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return self.fetchedResultsController!.numberOfSections() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.fetchedResultsController!.numberOfRowsForSectionIndex(section) } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return self.fetchedResultsController!.titleForHeaderInSection(section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) // Configure the cell... let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) cell.textLabel?.text = object?.title return cell } // Override to support conditional editing of the table view. override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // Return NO if you do not want the specified item to be editable. return true } // Override to support editing the table view. override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // Delete the row from the data source self.deleteObjectAtIndexPath(indexPath) } else if editingStyle == .insert { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } // MARK: - Button Actions @IBAction func didPressInsertButton(_ sender: UIBarButtonItem) { self.insertObject() } @IBAction func didPressDeleteButton(_ sender: UIBarButtonItem) { let objectsInFirstSection = self.realm!.objects(TestObject.self).filter("%K == %@", "sectionName","First Section") try! self.realm!.write { () -> Void in self.realm!.delete(objectsInFirstSection) } } // MARK: - Private fileprivate func deleteObjectAtIndexPath(_ indexPath: IndexPath) { if let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) { let realm = self.realm! try! realm.write({ () -> Void in realm.delete(object) }) } } fileprivate func insertObject() { let realm = self.realm! let indexPathFirstRow = IndexPath(row: 0, section: 0) let object = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) if (object?.sortIndex)! > 0 { realm.beginWrite() let sortIndex = object!.sortIndex - 1 let title = "Cell \(sortIndex)" var newObject = realm.object(ofType: TestObject.self, forPrimaryKey: "\(title)\(sortIndex)" as AnyObject) if newObject == nil { newObject = TestObject() newObject!.title = title newObject!.sortIndex = sortIndex newObject!.sectionName = "First Section" newObject!.key = "\(title)\(sortIndex)" newObject!.inTable = true realm.add(newObject!, update: false) } else { newObject?.inTable = true } try! realm.commitWrite() } else { // Test Moves realm.beginWrite() let indexPathFifthRow = IndexPath(row: 5, section: 0) let indexPathThirdRow = IndexPath(row: 3, section: 0) let indexPathSixthRow = IndexPath(row: 6, section: 0) let indexPathFirstRow = IndexPath(row: 0, section: 0) let firstObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) let thirdObject = self.fetchedResultsController?.objectAtIndexPath(indexPathThirdRow) let fifthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFifthRow) let sixthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathSixthRow) let ninthObject = realm.objects(TestObject.self).filter("%K == %@", "title","Cell 9") fifthObject?.sortIndex += 1 sixthObject?.sortIndex -= 1 firstObject?.inTable = false thirdObject?.title = "Testing Move And Update" if let testObject = ninthObject.first { if testObject.sectionName == "First Section" { testObject.sectionName = "Second Section" } else { testObject.sectionName = "First Section" } } try! realm.commitWrite() } } } // MARK: - extension MainTableViewController: FetchedResultsControllerDelegate { func controllerWillChangeContent(_ controller: FetchedResultsController) { self.tableView.beginUpdates() } public func controller(_ controller: FetchedResultsController, didChangeObject anObject: SafeObject, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { let tableView = self.tableView switch type { case .insert: tableView?.insertRows(at: [newIndexPath!], with: UITableView.RowAnimation.fade) case .delete: tableView?.deleteRows(at: [indexPath!], with: UITableView.RowAnimation.fade) case .update: tableView?.reloadRows(at: [indexPath!], with: UITableView.RowAnimation.fade) case .move: tableView?.deleteRows(at: [indexPath!], with: UITableView.RowAnimation.fade) tableView?.insertRows(at: [newIndexPath!], with: UITableView.RowAnimation.fade) } } func controllerDidChangeSection(_ controller: FetchedResultsController, section: FetchResultsSectionInfo, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) { let tableView = self.tableView if changeType == NSFetchedResultsChangeType.insert { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.insertSections(indexSet, with: UITableView.RowAnimation.fade) } else if changeType == NSFetchedResultsChangeType.delete { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.deleteSections(indexSet, with: UITableView.RowAnimation.fade) } } func controllerDidChangeContent(_ controller: FetchedResultsController) { self.tableView.endUpdates() } } ================================================ FILE: Examples/Swift/RBQFRCSwiftExample/RBQFRCSwift-BridgingHeader.h ================================================ // // RBQFRCSwift-BridgingHeader.h // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // #import "RBQFetchedResultsController.h" #import "RBQFetchRequest.h" #import #import ================================================ FILE: Examples/Swift/RBQFRCSwiftExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 9EDF1BD2192244E7325F36EC /* Pods_RBQFRCSwiftExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B25B6BB5B4064923A161E8B0 /* Pods_RBQFRCSwiftExampleTests.framework */; }; A0519BB61C56F88C00307EB5 /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0519BB21C56F88C00307EB5 /* FetchedResultsController.swift */; }; A0519BB71C56F88C00307EB5 /* FetchRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0519BB31C56F88C00307EB5 /* FetchRequest.swift */; }; A0519BB81C56F88C00307EB5 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0519BB41C56F88C00307EB5 /* Utilities.swift */; }; A0519BE51C56F89B00307EB5 /* RBQControllerCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519BBB1C56F89B00307EB5 /* RBQControllerCacheObject.m */; }; A0519BE61C56F89B00307EB5 /* RBQObjectCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519BBD1C56F89B00307EB5 /* RBQObjectCacheObject.m */; }; A0519BE71C56F89B00307EB5 /* RBQSectionCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519BBF1C56F89B00307EB5 /* RBQSectionCacheObject.m */; }; A0519BE81C56F89B00307EB5 /* RBQFetchedResultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519BC11C56F89B00307EB5 /* RBQFetchedResultsController.m */; }; A0519BE91C56F89B00307EB5 /* RBQFetchRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519BC31C56F89B00307EB5 /* RBQFetchRequest.m */; }; A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */; }; A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F11B6185AE0000C9B2 /* Main.storyboard */; }; A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F41B6185AE0000C9B2 /* Images.xcassets */; }; A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */; }; A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */; }; A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AB74611B6C389700923940 /* MainTableViewController.swift */; }; C9530DC27BD716194D2D9ED4 /* Pods_RBQFRCSwiftExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00319C4131299318D0CE01CC /* Pods_RBQFRCSwiftExample.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A05FA4E01B6185AE0000C9B2 /* Project object */; proxyType = 1; remoteGlobalIDString = A05FA4E71B6185AE0000C9B2; remoteInfo = RBQFRCSwiftExample; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ A05FA5131B6185F30000C9B2 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 00319C4131299318D0CE01CC /* Pods_RBQFRCSwiftExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RBQFRCSwiftExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 633E6162CF3770E25E232A56 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests.release.xcconfig"; sourceTree = ""; }; A0519BB21C56F88C00307EB5 /* FetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FetchedResultsController.swift; path = ../../RBQFetchedResultsController/Source/Swift/FetchedResultsController.swift; sourceTree = ""; }; A0519BB31C56F88C00307EB5 /* FetchRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FetchRequest.swift; path = ../../RBQFetchedResultsController/Source/Swift/FetchRequest.swift; sourceTree = ""; }; A0519BB41C56F88C00307EB5 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utilities.swift; path = ../../RBQFetchedResultsController/Source/Swift/Utilities.swift; sourceTree = ""; }; A0519BBA1C56F89B00307EB5 /* RBQControllerCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQControllerCacheObject.h; sourceTree = ""; }; A0519BBB1C56F89B00307EB5 /* RBQControllerCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQControllerCacheObject.m; sourceTree = ""; }; A0519BBC1C56F89B00307EB5 /* RBQObjectCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQObjectCacheObject.h; sourceTree = ""; }; A0519BBD1C56F89B00307EB5 /* RBQObjectCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQObjectCacheObject.m; sourceTree = ""; }; A0519BBE1C56F89B00307EB5 /* RBQSectionCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQSectionCacheObject.h; sourceTree = ""; }; A0519BBF1C56F89B00307EB5 /* RBQSectionCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQSectionCacheObject.m; sourceTree = ""; }; A0519BC01C56F89B00307EB5 /* RBQFetchedResultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchedResultsController.h; path = ../../RBQFetchedResultsController/Source/RBQFetchedResultsController.h; sourceTree = ""; }; A0519BC11C56F89B00307EB5 /* RBQFetchedResultsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchedResultsController.m; path = ../../RBQFetchedResultsController/Source/RBQFetchedResultsController.m; sourceTree = ""; }; A0519BC21C56F89B00307EB5 /* RBQFetchRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchRequest.h; path = ../../RBQFetchedResultsController/Source/RBQFetchRequest.h; sourceTree = ""; }; A0519BC31C56F89B00307EB5 /* RBQFetchRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchRequest.m; path = ../../RBQFetchedResultsController/Source/RBQFetchRequest.m; sourceTree = ""; }; A0519BC61C56F89B00307EB5 /* RLMObject+Notifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RLMObject+Notifications.h"; sourceTree = ""; }; A0519BC71C56F89B00307EB5 /* RLMObject+Notifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RLMObject+Notifications.m"; sourceTree = ""; }; A0519BC81C56F89B00307EB5 /* RLMRealm+Notifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RLMRealm+Notifications.h"; sourceTree = ""; }; A0519BC91C56F89B00307EB5 /* RLMRealm+Notifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RLMRealm+Notifications.m"; sourceTree = ""; }; A0519BCA1C56F89B00307EB5 /* RLMResults+Notifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RLMResults+Notifications.h"; sourceTree = ""; }; A0519BCB1C56F89B00307EB5 /* RLMResults+Notifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RLMResults+Notifications.m"; sourceTree = ""; }; A0519BCD1C56F89B00307EB5 /* RBQRealmNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQRealmNotificationManager.h; sourceTree = ""; }; A0519BCE1C56F89B00307EB5 /* RBQRealmNotificationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQRealmNotificationManager.m; sourceTree = ""; }; A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFRCSwiftExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA4EC1B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; A05FA4F21B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; A05FA4F41B6185AE0000C9B2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; A05FA4F71B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFRCSwiftExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA5021B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RBQFRCSwiftExampleTests.swift; sourceTree = ""; }; A08909851B8FB1C1002E87DD /* RBQFRCSwift-BridgingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RBQFRCSwift-BridgingHeader.h"; sourceTree = ""; }; A0AB74611B6C389700923940 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = ""; }; B25B6BB5B4064923A161E8B0 /* Pods_RBQFRCSwiftExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RBQFRCSwiftExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B36C0AF6EC590706E168170A /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests.debug.xcconfig"; sourceTree = ""; }; D7864A603072C1724ABE96A6 /* Pods-RBQFRCSwiftExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample.release.xcconfig"; sourceTree = ""; }; F6B7EBA1353A22336B3D1695 /* Pods-RBQFRCSwiftExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ A05FA4E51B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( C9530DC27BD716194D2D9ED4 /* Pods_RBQFRCSwiftExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FA1B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 9EDF1BD2192244E7325F36EC /* Pods_RBQFRCSwiftExampleTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 39F4E4983D27CC60399A5D24 /* Pods */ = { isa = PBXGroup; children = ( F6B7EBA1353A22336B3D1695 /* Pods-RBQFRCSwiftExample.debug.xcconfig */, D7864A603072C1724ABE96A6 /* Pods-RBQFRCSwiftExample.release.xcconfig */, B36C0AF6EC590706E168170A /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */, 633E6162CF3770E25E232A56 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; A0519BB91C56F89B00307EB5 /* CacheObjects */ = { isa = PBXGroup; children = ( A0519BBA1C56F89B00307EB5 /* RBQControllerCacheObject.h */, A0519BBB1C56F89B00307EB5 /* RBQControllerCacheObject.m */, A0519BBC1C56F89B00307EB5 /* RBQObjectCacheObject.h */, A0519BBD1C56F89B00307EB5 /* RBQObjectCacheObject.m */, A0519BBE1C56F89B00307EB5 /* RBQSectionCacheObject.h */, A0519BBF1C56F89B00307EB5 /* RBQSectionCacheObject.m */, ); name = CacheObjects; path = ../../RBQFetchedResultsController/Source/CacheObjects; sourceTree = ""; }; A0519BC41C56F89B00307EB5 /* RBQRealmNotificationManager */ = { isa = PBXGroup; children = ( A0519BC51C56F89B00307EB5 /* Helpers */, A0519BCD1C56F89B00307EB5 /* RBQRealmNotificationManager.h */, A0519BCE1C56F89B00307EB5 /* RBQRealmNotificationManager.m */, ); name = RBQRealmNotificationManager; path = ../../RBQFetchedResultsController/Source/RBQRealmNotificationManager; sourceTree = ""; }; A0519BC51C56F89B00307EB5 /* Helpers */ = { isa = PBXGroup; children = ( A0519BC61C56F89B00307EB5 /* RLMObject+Notifications.h */, A0519BC71C56F89B00307EB5 /* RLMObject+Notifications.m */, A0519BC81C56F89B00307EB5 /* RLMRealm+Notifications.h */, A0519BC91C56F89B00307EB5 /* RLMRealm+Notifications.m */, A0519BCA1C56F89B00307EB5 /* RLMResults+Notifications.h */, A0519BCB1C56F89B00307EB5 /* RLMResults+Notifications.m */, ); path = Helpers; sourceTree = ""; }; A05FA4DF1B6185AE0000C9B2 = { isa = PBXGroup; children = ( A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, A05FA4E91B6185AE0000C9B2 /* Products */, 39F4E4983D27CC60399A5D24 /* Pods */, E23B252BD5C9A622BFB39D12 /* Frameworks */, ); sourceTree = ""; }; A05FA4E91B6185AE0000C9B2 /* Products */ = { isa = PBXGroup; children = ( A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */, A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */, ); name = Products; sourceTree = ""; }; A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXGroup; children = ( A089093F1B8F9715002E87DD /* RBQFetchedResultsController */, A08909331B8F970A002E87DD /* Swift */, A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */, A08909851B8FB1C1002E87DD /* RBQFRCSwift-BridgingHeader.h */, A0AB74611B6C389700923940 /* MainTableViewController.swift */, A05FA4F11B6185AE0000C9B2 /* Main.storyboard */, A05FA4F41B6185AE0000C9B2 /* Images.xcassets */, A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */, A05FA4EB1B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExample; sourceTree = ""; }; A05FA4EB1B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA4EC1B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXGroup; children = ( A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */, A05FA5011B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExampleTests; sourceTree = ""; }; A05FA5011B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA5021B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A08909331B8F970A002E87DD /* Swift */ = { isa = PBXGroup; children = ( A0519BB21C56F88C00307EB5 /* FetchedResultsController.swift */, A0519BB31C56F88C00307EB5 /* FetchRequest.swift */, A0519BB41C56F88C00307EB5 /* Utilities.swift */, ); name = Swift; path = ../../Swift; sourceTree = ""; }; A089093F1B8F9715002E87DD /* RBQFetchedResultsController */ = { isa = PBXGroup; children = ( A0519BB91C56F89B00307EB5 /* CacheObjects */, A0519BC01C56F89B00307EB5 /* RBQFetchedResultsController.h */, A0519BC11C56F89B00307EB5 /* RBQFetchedResultsController.m */, A0519BC21C56F89B00307EB5 /* RBQFetchRequest.h */, A0519BC31C56F89B00307EB5 /* RBQFetchRequest.m */, A0519BC41C56F89B00307EB5 /* RBQRealmNotificationManager */, ); name = RBQFetchedResultsController; path = ../../RBQFetchedResultsController; sourceTree = ""; }; E23B252BD5C9A622BFB39D12 /* Frameworks */ = { isa = PBXGroup; children = ( 00319C4131299318D0CE01CC /* Pods_RBQFRCSwiftExample.framework */, B25B6BB5B4064923A161E8B0 /* Pods_RBQFRCSwiftExampleTests.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */; buildPhases = ( 5023F0B217EFFA8F645B9BE6 /* [CP] Check Pods Manifest.lock */, A05FA4E41B6185AE0000C9B2 /* Sources */, A05FA4E51B6185AE0000C9B2 /* Frameworks */, A05FA4E61B6185AE0000C9B2 /* Resources */, A05FA5131B6185F30000C9B2 /* Embed Frameworks */, B7699BF9CDBA409BEB9F4504 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = RBQFRCSwiftExample; productName = RBQFRCSwiftExample; productReference = A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */; productType = "com.apple.product-type.application"; }; A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */; buildPhases = ( 31865C1B5BE568D46F99B0EC /* [CP] Check Pods Manifest.lock */, A05FA4F91B6185AE0000C9B2 /* Sources */, A05FA4FA1B6185AE0000C9B2 /* Frameworks */, A05FA4FB1B6185AE0000C9B2 /* Resources */, ); buildRules = ( ); dependencies = ( A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */, ); name = RBQFRCSwiftExampleTests; productName = RBQFRCSwiftExampleTests; productReference = A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ A05FA4E01B6185AE0000C9B2 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Adam Fish"; TargetAttributes = { A05FA4E71B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 1010; }; A05FA4FC1B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 1010; TestTargetID = A05FA4E71B6185AE0000C9B2; }; }; }; buildConfigurationList = A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = A05FA4DF1B6185AE0000C9B2; productRefGroup = A05FA4E91B6185AE0000C9B2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ A05FA4E61B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */, A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */, A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FB1B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 31865C1B5BE568D46F99B0EC /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-RBQFRCSwiftExampleTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 5023F0B217EFFA8F645B9BE6 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-RBQFRCSwiftExample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; B7699BF9CDBA409BEB9F4504 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample-frameworks.sh", "${BUILT_PRODUCTS_DIR}/RBQSafeRealmObject/RBQSafeRealmObject.framework", "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework", "${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework", "${BUILT_PRODUCTS_DIR}/RealmUtilities/RealmUtilities.framework", "${BUILT_PRODUCTS_DIR}/SafeRealmObject/SafeRealmObject.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RBQSafeRealmObject.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmSwift.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SafeRealmObject.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ A05FA4E41B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0519BE61C56F89B00307EB5 /* RBQObjectCacheObject.m in Sources */, A0519BB71C56F88C00307EB5 /* FetchRequest.swift in Sources */, A0519BE51C56F89B00307EB5 /* RBQControllerCacheObject.m in Sources */, A0519BB61C56F88C00307EB5 /* FetchedResultsController.swift in Sources */, A0519BE81C56F89B00307EB5 /* RBQFetchedResultsController.m in Sources */, A0519BB81C56F88C00307EB5 /* Utilities.swift in Sources */, A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */, A0519BE71C56F89B00307EB5 /* RBQSectionCacheObject.m in Sources */, A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */, A0519BE91C56F89B00307EB5 /* RBQFetchRequest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4F91B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */; targetProxy = A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ A05FA4F11B6185AE0000C9B2 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( A05FA4F21B6185AE0000C9B2 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( A05FA4F71B6185AE0000C9B2 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ A05FA5051B6185AE0000C9B2 /* 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_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; 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_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.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; A05FA5061B6185AE0000C9B2 /* 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_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; 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 = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; A05FA5081B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F6B7EBA1353A22336B3D1695 /* Pods-RBQFRCSwiftExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/RBQFRCSwiftExample", ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/RBQFRCSwiftExample/RBQFRCSwift-BridgingHeader.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; A05FA5091B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = D7864A603072C1724ABE96A6 /* Pods-RBQFRCSwiftExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/RBQFRCSwiftExample", ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/RBQFRCSwiftExample/RBQFRCSwift-BridgingHeader.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; A05FA50B1B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B36C0AF6EC590706E168170A /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Debug; }; A05FA50C1B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 633E6162CF3770E25E232A56 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5051B6185AE0000C9B2 /* Debug */, A05FA5061B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5081B6185AE0000C9B2 /* Debug */, A05FA5091B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA50B1B6185AE0000C9B2 /* Debug */, A05FA50C1B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = A05FA4E01B6185AE0000C9B2 /* Project object */; } ================================================ FILE: Examples/Swift/RBQFRCSwiftExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/Swift/RBQFRCSwiftExampleTests/RBQFRCSwiftExampleTests.swift ================================================ // // RBQFRCSwiftExampleTests.swift // RBQFRCSwiftExampleTests // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit import XCTest class RBQFRCSwiftExampleTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. self.measure() { // Put the code you want to measure the time of here. } } } ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/AppDelegate.swift ================================================ // // AppDelegate.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample/MainTableViewController.swift ================================================ // // MainTableViewController.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/31/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit import Realm import RealmSwift import SafeRealmObject import SwiftFetchedResultsController // MARK: - class TestObject: Object { dynamic var title = "" dynamic var sortIndex = 0 dynamic var sectionName = "" dynamic var key = "" dynamic var inTable: Bool = false override class func primaryKey() -> String? { return "key" } class func testObject(_ title: String, sortIndex: Int, inTable: Bool) -> TestObject { let object = TestObject() object.title = title object.sortIndex = sortIndex object.inTable = inTable object.key = "\(title)\(sortIndex)" return object } } // MARK: - class MainTableViewController: UITableViewController { var fetchedResultsController: FetchedResultsController? var realm: Realm? override func viewDidLoad() { super.viewDidLoad() let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "Test")) self.realm = realm realm.beginWrite() realm.deleteAll() for index in 1...1000 { let title = "Cell \(index)" let object = TestObject.testObject(title, sortIndex: index, inTable: true) if (index < 10) { object.sectionName = "First Section" } else { object.sectionName = "Second Section" } realm.add(object, update: false) } try! realm.commitWrite() let predicate = NSPredicate(format: "inTable = YES") let fetchRequest = FetchRequest(realm: realm, predicate: predicate) let sortDescriptor = SortDescriptor(property: "sortIndex", ascending: true) let sortDescriptorSection = SortDescriptor(property: "sectionName", ascending: true) fetchRequest.sortDescriptors = [sortDescriptorSection, sortDescriptor] self.fetchedResultsController = FetchedResultsController(fetchRequest: fetchRequest, sectionNameKeyPath: "sectionName", cacheName: "testCache") self.fetchedResultsController!.delegate = self let _ = self.fetchedResultsController!.performFetch() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return self.fetchedResultsController!.numberOfSections() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.fetchedResultsController!.numberOfRowsForSectionIndex(section) } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return self.fetchedResultsController!.titleForHeaderInSection(section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) // Configure the cell... let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) cell.textLabel?.text = object?.title return cell } // Override to support conditional editing of the table view. override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // Return NO if you do not want the specified item to be editable. return true } // Override to support editing the table view. override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // Delete the row from the data source self.deleteObjectAtIndexPath(indexPath) } else if editingStyle == .insert { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } // MARK: - Button Actions @IBAction func didPressInsertButton(_ sender: UIBarButtonItem) { self.insertObject() } @IBAction func didPressDeleteButton(_ sender: UIBarButtonItem) { let objectsInFirstSection = self.realm!.objects(TestObject.self).filter("%K == %@", "sectionName","First Section") try! self.realm!.write { () -> Void in self.realm!.delete(objectsInFirstSection) } } // MARK: - Private fileprivate func deleteObjectAtIndexPath(_ indexPath: IndexPath) { if let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) { let realm = self.realm! try! realm.write({ () -> Void in realm.delete(object) }) } } fileprivate func insertObject() { let realm = self.realm! let indexPathFirstRow = IndexPath(row: 0, section: 0) let object = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) if (object?.sortIndex)! > 0 { realm.beginWrite() let sortIndex = object!.sortIndex - 1 let title = "Cell \(sortIndex)" var newObject = realm.object(ofType: TestObject.self, forPrimaryKey: "\(title)\(sortIndex)" as AnyObject) if newObject == nil { newObject = TestObject() newObject!.title = title newObject!.sortIndex = sortIndex newObject!.sectionName = "First Section" newObject!.key = "\(title)\(sortIndex)" newObject!.inTable = true realm.add(newObject!, update: false) } else { newObject?.inTable = true } try! realm.commitWrite() } else { // Test Moves realm.beginWrite() let indexPathFifthRow = IndexPath(row: 5, section: 0) let indexPathThirdRow = IndexPath(row: 3, section: 0) let indexPathSixthRow = IndexPath(row: 6, section: 0) let indexPathFirstRow = IndexPath(row: 0, section: 0) let firstObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) let thirdObject = self.fetchedResultsController?.objectAtIndexPath(indexPathThirdRow) let fifthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFifthRow) let sixthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathSixthRow) let ninthObject = realm.objects(TestObject.self).filter("%K == %@", "title","Cell 9") fifthObject?.sortIndex += 1 sixthObject?.sortIndex -= 1 firstObject?.inTable = false thirdObject?.title = "Testing Move And Update" if let testObject = ninthObject.first { if testObject.sectionName == "First Section" { testObject.sectionName = "Second Section" } else { testObject.sectionName = "First Section" } } try! realm.commitWrite() } } } // MARK: - extension MainTableViewController: FetchedResultsControllerDelegate { func controllerWillChangeContent(_ controller: FetchedResultsController) { self.tableView.beginUpdates() } public func controller(_ controller: FetchedResultsController, didChangeObject anObject: SafeObject, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { let tableView = self.tableView switch type { case .insert: tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade) case .delete: tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade) case .update: tableView?.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.fade) case .move: tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade) tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade) } } func controllerDidChangeSection(_ controller: FetchedResultsController, section: FetchResultsSectionInfo, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) { let tableView = self.tableView if changeType == NSFetchedResultsChangeType.insert { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.insertSections(indexSet, with: UITableViewRowAnimation.fade) } else if changeType == NSFetchedResultsChangeType.delete { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.deleteSections(indexSet, with: UITableViewRowAnimation.fade) } } func controllerDidChangeContent(_ controller: FetchedResultsController) { self.tableView.endUpdates() } } ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */; }; A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F11B6185AE0000C9B2 /* Main.storyboard */; }; A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F41B6185AE0000C9B2 /* Images.xcassets */; }; A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */; }; A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */; }; A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AB74611B6C389700923940 /* MainTableViewController.swift */; }; A0BC27C21C56DA8D00306449 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27C01C56DA8D00306449 /* Realm.framework */; }; A0BC27C31C56DA8D00306449 /* Realm.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27C01C56DA8D00306449 /* Realm.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; A0BC27C41C56DA8D00306449 /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27C11C56DA8D00306449 /* RealmSwift.framework */; }; A0BC27C51C56DA8D00306449 /* RealmSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27C11C56DA8D00306449 /* RealmSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC501DF6BE8B00A85A48 /* RBQFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27BA1C56DA7500306449 /* RBQFetchedResultsController.framework */; }; F9C9CC511DF6BE8B00A85A48 /* RBQFetchedResultsController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A0BC27BA1C56DA7500306449 /* RBQFetchedResultsController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC541DF6BE8B00A85A48 /* SwiftFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A090E5D41C73B3B60046788B /* SwiftFetchedResultsController.framework */; }; F9C9CC551DF6BE8B00A85A48 /* SwiftFetchedResultsController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A090E5D41C73B3B60046788B /* SwiftFetchedResultsController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC5C1DF6BEB300A85A48 /* RBQSafeRealmObject.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC581DF6BEAC00A85A48 /* RBQSafeRealmObject.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC601DF6BEB300A85A48 /* SafeRealmObject.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC5A1DF6BEAC00A85A48 /* SafeRealmObject.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F9C9CC661DF71C1500A85A48 /* RealmUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC591DF6BEAC00A85A48 /* RealmUtilities.framework */; }; F9C9CC671DF71C1500A85A48 /* RealmUtilities.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC591DF6BEAC00A85A48 /* RealmUtilities.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A05FA4E01B6185AE0000C9B2 /* Project object */; proxyType = 1; remoteGlobalIDString = A05FA4E71B6185AE0000C9B2; remoteInfo = RBQFRCSwiftExample; }; A090E5CF1C73B3B50046788B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = A090E59F1C73B17B0046788B; remoteInfo = SwiftFetchedResultsController; }; A090E5D31C73B3B60046788B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = A090E5A01C73B17B0046788B; remoteInfo = SwiftFetchedResultsController; }; A0BC27B91C56DA7500306449 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = 6361D7341C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; A0BC27BB1C56DA7500306449 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 2; remoteGlobalIDString = 6361D73E1C4051A8005CD430; remoteInfo = RBQFetchedResultsControllerTests; }; A0BC27BD1C56DA7C00306449 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; F9C9CC521DF6BE8B00A85A48 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; F9C9CC561DF6BE8B00A85A48 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; proxyType = 1; remoteGlobalIDString = A090E59F1C73B17B0046788B; remoteInfo = SwiftFetchedResultsController; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ A05FA5131B6185F30000C9B2 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( F9C9CC5C1DF6BEB300A85A48 /* RBQSafeRealmObject.framework in Embed Frameworks */, A0BC27C51C56DA8D00306449 /* RealmSwift.framework in Embed Frameworks */, F9C9CC551DF6BE8B00A85A48 /* SwiftFetchedResultsController.framework in Embed Frameworks */, F9C9CC671DF71C1500A85A48 /* RealmUtilities.framework in Embed Frameworks */, F9C9CC601DF6BEB300A85A48 /* SafeRealmObject.framework in Embed Frameworks */, F9C9CC511DF6BE8B00A85A48 /* RBQFetchedResultsController.framework in Embed Frameworks */, A0BC27C31C56DA8D00306449 /* Realm.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFRCSwiftExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA4EC1B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; A05FA4F21B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; A05FA4F41B6185AE0000C9B2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; A05FA4F71B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFRCSwiftExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA5021B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RBQFRCSwiftExampleTests.swift; sourceTree = ""; }; A0AB74611B6C389700923940 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = ""; }; A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RBQFetchedResultsController.xcodeproj; path = ../../RBQFetchedResultsController.xcodeproj; sourceTree = ""; }; A0BC27C01C56DA8D00306449 /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = ../../Carthage/Build/iOS/Realm.framework; sourceTree = ""; }; A0BC27C11C56DA8D00306449 /* RealmSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmSwift.framework; path = ../../Carthage/Build/iOS/RealmSwift.framework; sourceTree = ""; }; F9C9CC581DF6BEAC00A85A48 /* RBQSafeRealmObject.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RBQSafeRealmObject.framework; path = ../../Carthage/Build/iOS/RBQSafeRealmObject.framework; sourceTree = ""; }; F9C9CC591DF6BEAC00A85A48 /* RealmUtilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmUtilities.framework; path = ../../Carthage/Build/iOS/RealmUtilities.framework; sourceTree = ""; }; F9C9CC5A1DF6BEAC00A85A48 /* SafeRealmObject.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafeRealmObject.framework; path = ../../Carthage/Build/iOS/SafeRealmObject.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ A05FA4E51B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A0BC27C21C56DA8D00306449 /* Realm.framework in Frameworks */, F9C9CC661DF71C1500A85A48 /* RealmUtilities.framework in Frameworks */, F9C9CC541DF6BE8B00A85A48 /* SwiftFetchedResultsController.framework in Frameworks */, F9C9CC501DF6BE8B00A85A48 /* RBQFetchedResultsController.framework in Frameworks */, A0BC27C41C56DA8D00306449 /* RealmSwift.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FA1B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 8BEDE2E49A674D438DD0CE47 /* Frameworks */ = { isa = PBXGroup; children = ( F9C9CC581DF6BEAC00A85A48 /* RBQSafeRealmObject.framework */, F9C9CC591DF6BEAC00A85A48 /* RealmUtilities.framework */, F9C9CC5A1DF6BEAC00A85A48 /* SafeRealmObject.framework */, A0BC27C01C56DA8D00306449 /* Realm.framework */, A0BC27C11C56DA8D00306449 /* RealmSwift.framework */, A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */, ); name = Frameworks; sourceTree = ""; }; A05FA4DF1B6185AE0000C9B2 = { isa = PBXGroup; children = ( A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, A05FA4E91B6185AE0000C9B2 /* Products */, 8BEDE2E49A674D438DD0CE47 /* Frameworks */, ); sourceTree = ""; }; A05FA4E91B6185AE0000C9B2 /* Products */ = { isa = PBXGroup; children = ( A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */, A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */, ); name = Products; sourceTree = ""; }; A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXGroup; children = ( A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */, A0AB74611B6C389700923940 /* MainTableViewController.swift */, A05FA4F11B6185AE0000C9B2 /* Main.storyboard */, A05FA4F41B6185AE0000C9B2 /* Images.xcassets */, A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */, A05FA4EB1B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExample; sourceTree = ""; }; A05FA4EB1B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA4EC1B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXGroup; children = ( A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */, A05FA5011B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExampleTests; sourceTree = ""; }; A05FA5011B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA5021B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A0BC27B51C56DA7500306449 /* Products */ = { isa = PBXGroup; children = ( A0BC27BA1C56DA7500306449 /* RBQFetchedResultsController.framework */, A0BC27BC1C56DA7500306449 /* RBQFetchedResultsController.xctest */, A090E5D41C73B3B60046788B /* SwiftFetchedResultsController.framework */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */; buildPhases = ( A05FA4E41B6185AE0000C9B2 /* Sources */, A05FA4E51B6185AE0000C9B2 /* Frameworks */, A05FA4E61B6185AE0000C9B2 /* Resources */, A05FA5131B6185F30000C9B2 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( A090E5D01C73B3B50046788B /* PBXTargetDependency */, A0BC27BE1C56DA7C00306449 /* PBXTargetDependency */, F9C9CC531DF6BE8B00A85A48 /* PBXTargetDependency */, F9C9CC571DF6BE8B00A85A48 /* PBXTargetDependency */, ); name = RBQFRCSwiftExample; productName = RBQFRCSwiftExample; productReference = A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */; productType = "com.apple.product-type.application"; }; A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */; buildPhases = ( 0BAC064F8923B4D07295C7EB /* Check Pods Manifest.lock */, A05FA4F91B6185AE0000C9B2 /* Sources */, A05FA4FA1B6185AE0000C9B2 /* Frameworks */, A05FA4FB1B6185AE0000C9B2 /* Resources */, 3CFF26782BB12C184090942C /* Embed Pods Frameworks */, 8D7C6A3CCEEAE266BF7667B9 /* Copy Pods Resources */, ); buildRules = ( ); dependencies = ( A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */, ); name = RBQFRCSwiftExampleTests; productName = RBQFRCSwiftExampleTests; productReference = A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ A05FA4E01B6185AE0000C9B2 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Adam Fish"; TargetAttributes = { A05FA4E71B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; }; A05FA4FC1B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 0810; TestTargetID = A05FA4E71B6185AE0000C9B2; }; }; }; buildConfigurationList = A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = A05FA4DF1B6185AE0000C9B2; productRefGroup = A05FA4E91B6185AE0000C9B2 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = A0BC27B51C56DA7500306449 /* Products */; ProjectRef = A0BC27B41C56DA7500306449 /* RBQFetchedResultsController.xcodeproj */; }, ); projectRoot = ""; targets = ( A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ A090E5D41C73B3B60046788B /* SwiftFetchedResultsController.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = SwiftFetchedResultsController.framework; remoteRef = A090E5D31C73B3B60046788B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; A0BC27BA1C56DA7500306449 /* RBQFetchedResultsController.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = RBQFetchedResultsController.framework; remoteRef = A0BC27B91C56DA7500306449 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; A0BC27BC1C56DA7500306449 /* RBQFetchedResultsController.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = RBQFetchedResultsController.xctest; remoteRef = A0BC27BB1C56DA7500306449 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ A05FA4E61B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */, A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */, A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FB1B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 0BAC064F8923B4D07295C7EB /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "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 cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 3CFF26782BB12C184090942C /* Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 8D7C6A3CCEEAE266BF7667B9 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ A05FA4E41B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */, A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4F91B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */; targetProxy = A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */; }; A090E5D01C73B3B50046788B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftFetchedResultsController; targetProxy = A090E5CF1C73B3B50046788B /* PBXContainerItemProxy */; }; A0BC27BE1C56DA7C00306449 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = RBQFetchedResultsController; targetProxy = A0BC27BD1C56DA7C00306449 /* PBXContainerItemProxy */; }; F9C9CC531DF6BE8B00A85A48 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = RBQFetchedResultsController; targetProxy = F9C9CC521DF6BE8B00A85A48 /* PBXContainerItemProxy */; }; F9C9CC571DF6BE8B00A85A48 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftFetchedResultsController; targetProxy = F9C9CC561DF6BE8B00A85A48 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ A05FA4F11B6185AE0000C9B2 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( A05FA4F21B6185AE0000C9B2 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( A05FA4F71B6185AE0000C9B2 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ A05FA5051B6185AE0000C9B2 /* 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-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.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; A05FA5061B6185AE0000C9B2 /* 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 = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; A05FA5081B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", ../../Carthage/Build/iOS/, ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Debug; }; A05FA5091B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", ../../Carthage/Build/iOS/, ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Release; }; A05FA50B1B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Debug; }; A05FA50C1B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5051B6185AE0000C9B2 /* Debug */, A05FA5061B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5081B6185AE0000C9B2 /* Debug */, A05FA5091B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA50B1B6185AE0000C9B2 /* Debug */, A05FA50C1B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = A05FA4E01B6185AE0000C9B2 /* Project object */; } ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/Swift-carthage/RBQFRCSwiftExampleTests/RBQFRCSwiftExampleTests.swift ================================================ // // RBQFRCSwiftExampleTests.swift // RBQFRCSwiftExampleTests // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit import XCTest class RBQFRCSwiftExampleTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. self.measure() { // Put the code you want to measure the time of here. } } } ================================================ FILE: Examples/Swift-cocoapods/.swift-version ================================================ 3.0.1 ================================================ FILE: Examples/Swift-cocoapods/Podfile ================================================ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! target 'RBQFRCSwiftExample' do pod 'RBQFetchedResultsController', path: '../../' pod 'SwiftFetchedResultsController', path: '../../' target 'RBQFRCSwiftExampleTests' do inherit! :search_paths end end ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/AppDelegate.swift ================================================ // // AppDelegate.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/MainTableViewController.swift ================================================ // // MainTableViewController.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/31/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import Realm import RealmSwift import SafeRealmObject import SwiftFetchedResultsController import UIKit // MARK: - class TestObject: Object { dynamic var title = "" dynamic var sortIndex = 0 dynamic var sectionName = "" dynamic var key = "" dynamic var inTable: Bool = false override class func primaryKey() -> String? { return "key" } class func testObject(_ title: String, sortIndex: Int, inTable: Bool) -> TestObject { let object = TestObject() object.title = title object.sortIndex = sortIndex object.inTable = inTable object.key = "\(title)\(sortIndex)" return object } } // MARK: - class MainTableViewController: UITableViewController { var fetchedResultsController: FetchedResultsController? var realm: Realm? override func viewDidLoad() { super.viewDidLoad() let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "Test")) self.realm = realm realm.beginWrite() realm.deleteAll() for index in 1...1000 { let title = "Cell \(index)" let object = TestObject.testObject(title, sortIndex: index, inTable: true) if (index < 10) { object.sectionName = "First Section" } else { object.sectionName = "Second Section" } realm.add(object, update: false) } try! realm.commitWrite() let predicate = NSPredicate(format: "inTable = YES") let fetchRequest = FetchRequest(realm: realm, predicate: predicate) let sortDescriptor = SortDescriptor(property: "sortIndex", ascending: true) let sortDescriptorSection = SortDescriptor(property: "sectionName", ascending: true) fetchRequest.sortDescriptors = [sortDescriptorSection, sortDescriptor] self.fetchedResultsController = FetchedResultsController(fetchRequest: fetchRequest, sectionNameKeyPath: "sectionName", cacheName: "testCache") self.fetchedResultsController!.delegate = self let _ = self.fetchedResultsController!.performFetch() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return self.fetchedResultsController!.numberOfSections() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.fetchedResultsController!.numberOfRowsForSectionIndex(section) } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return self.fetchedResultsController!.titleForHeaderInSection(section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) // Configure the cell... let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) cell.textLabel?.text = object?.title return cell } // Override to support conditional editing of the table view. override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // Return NO if you do not want the specified item to be editable. return true } // Override to support editing the table view. override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // Delete the row from the data source self.deleteObjectAtIndexPath(indexPath) } else if editingStyle == .insert { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } // MARK: - Button Actions @IBAction func didPressInsertButton(_ sender: UIBarButtonItem) { self.insertObject() } @IBAction func didPressDeleteButton(_ sender: UIBarButtonItem) { let objectsInFirstSection = self.realm!.objects(TestObject.self).filter("%K == %@", "sectionName","First Section") try! self.realm!.write { () -> Void in self.realm!.delete(objectsInFirstSection) } } // MARK: - Private fileprivate func deleteObjectAtIndexPath(_ indexPath: IndexPath) { if let object = self.fetchedResultsController?.objectAtIndexPath(indexPath) { let realm = self.realm! try! realm.write({ () -> Void in realm.delete(object) }) } } fileprivate func insertObject() { let realm = self.realm! let indexPathFirstRow = IndexPath(row: 0, section: 0) let object = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) if (object?.sortIndex)! > 0 { realm.beginWrite() let sortIndex = object!.sortIndex - 1 let title = "Cell \(sortIndex)" var newObject = realm.object(ofType: TestObject.self, forPrimaryKey: "\(title)\(sortIndex)" as AnyObject) if newObject == nil { newObject = TestObject() newObject!.title = title newObject!.sortIndex = sortIndex newObject!.sectionName = "First Section" newObject!.key = "\(title)\(sortIndex)" newObject!.inTable = true realm.add(newObject!, update: false) } else { newObject?.inTable = true } try! realm.commitWrite() } else { // Test Moves realm.beginWrite() let indexPathFifthRow = IndexPath(row: 5, section: 0) let indexPathThirdRow = IndexPath(row: 3, section: 0) let indexPathSixthRow = IndexPath(row: 6, section: 0) let indexPathFirstRow = IndexPath(row: 0, section: 0) let firstObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFirstRow) let thirdObject = self.fetchedResultsController?.objectAtIndexPath(indexPathThirdRow) let fifthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathFifthRow) let sixthObject = self.fetchedResultsController?.objectAtIndexPath(indexPathSixthRow) let ninthObject = realm.objects(TestObject.self).filter("%K == %@", "title","Cell 9") fifthObject?.sortIndex += 1 sixthObject?.sortIndex -= 1 firstObject?.inTable = false thirdObject?.title = "Testing Move And Update" if let testObject = ninthObject.first { if testObject.sectionName == "First Section" { testObject.sectionName = "Second Section" } else { testObject.sectionName = "First Section" } } try! realm.commitWrite() } } } // MARK: - extension MainTableViewController: FetchedResultsControllerDelegate { func controllerWillChangeContent(_ controller: FetchedResultsController) { self.tableView.beginUpdates() } public func controller(_ controller: FetchedResultsController, didChangeObject anObject: SafeObject, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { let tableView = self.tableView switch type { case .insert: tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade) case .delete: tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade) case .update: tableView?.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.fade) case .move: tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade) tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade) } } func controllerDidChangeSection(_ controller: FetchedResultsController, section: FetchResultsSectionInfo, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) { let tableView = self.tableView if changeType == NSFetchedResultsChangeType.insert { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.insertSections(indexSet, with: UITableViewRowAnimation.fade) } else if changeType == NSFetchedResultsChangeType.delete { let indexSet = IndexSet(integer: Int(sectionIndex)) tableView?.deleteSections(indexSet, with: UITableViewRowAnimation.fade) } } func controllerDidChangeContent(_ controller: FetchedResultsController) { self.tableView.endUpdates() } } ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample/RBQFRCSwift-BridgingHeader.h ================================================ // // RBQFRCSwift-BridgingHeader.h // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // #import "RBQFetchedResultsController.h" #import "RBQFetchRequest.h" #import "RBQSafeRealmObject.h" #import "RBQRealmNotificationManager.h" #import "RLMObjectBase+Utilities.h" ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 18F44CFF107A2EE1082DC0AA /* Pods_RBQFRCSwiftExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 562846FB89DF75BB0D5CA170 /* Pods_RBQFRCSwiftExampleTests.framework */; }; 7548BB4B03843909EDE10894 /* Pods_RBQFRCSwiftExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18BC486F316E6B828A15ECBB /* Pods_RBQFRCSwiftExample.framework */; }; A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */; }; A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F11B6185AE0000C9B2 /* Main.storyboard */; }; A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F41B6185AE0000C9B2 /* Images.xcassets */; }; A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */; }; A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */; }; A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AB74611B6C389700923940 /* MainTableViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A05FA4E01B6185AE0000C9B2 /* Project object */; proxyType = 1; remoteGlobalIDString = A05FA4E71B6185AE0000C9B2; remoteInfo = RBQFRCSwiftExample; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ A05FA5131B6185F30000C9B2 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 18BC486F316E6B828A15ECBB /* Pods_RBQFRCSwiftExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RBQFRCSwiftExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4E1FCB9E207C119C0AE0ED70 /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests.debug.xcconfig"; sourceTree = ""; }; 562846FB89DF75BB0D5CA170 /* Pods_RBQFRCSwiftExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RBQFRCSwiftExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8DA8E0C988E77F16403017FF /* Pods-RBQFRCSwiftExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample.debug.xcconfig"; sourceTree = ""; }; A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBQFRCSwiftExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA4EC1B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; A05FA4F21B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; A05FA4F41B6185AE0000C9B2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; A05FA4F71B6185AE0000C9B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFRCSwiftExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A05FA5021B6185AE0000C9B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RBQFRCSwiftExampleTests.swift; sourceTree = ""; }; A0AB74611B6C389700923940 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = ""; }; A9AE666DAD240A473FD1FCE6 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests.release.xcconfig"; sourceTree = ""; }; E3A3DB9B3608D864C439B8F3 /* Pods-RBQFRCSwiftExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RBQFRCSwiftExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ A05FA4E51B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 7548BB4B03843909EDE10894 /* Pods_RBQFRCSwiftExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FA1B6185AE0000C9B2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 18F44CFF107A2EE1082DC0AA /* Pods_RBQFRCSwiftExampleTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ A05FA4DF1B6185AE0000C9B2 = { isa = PBXGroup; children = ( A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, A05FA4E91B6185AE0000C9B2 /* Products */, E2093C6F1F033BAA11FDF6E3 /* Pods */, EE8DED9C032A84D2CE496A23 /* Frameworks */, ); sourceTree = ""; }; A05FA4E91B6185AE0000C9B2 /* Products */ = { isa = PBXGroup; children = ( A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */, A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */, ); name = Products; sourceTree = ""; }; A05FA4EA1B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXGroup; children = ( A05FA4ED1B6185AE0000C9B2 /* AppDelegate.swift */, A0AB74611B6C389700923940 /* MainTableViewController.swift */, A05FA4F11B6185AE0000C9B2 /* Main.storyboard */, A05FA4F41B6185AE0000C9B2 /* Images.xcassets */, A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */, A05FA4EB1B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExample; sourceTree = ""; }; A05FA4EB1B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA4EC1B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; A05FA5001B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXGroup; children = ( A05FA5031B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift */, A05FA5011B6185AE0000C9B2 /* Supporting Files */, ); path = RBQFRCSwiftExampleTests; sourceTree = ""; }; A05FA5011B6185AE0000C9B2 /* Supporting Files */ = { isa = PBXGroup; children = ( A05FA5021B6185AE0000C9B2 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; E2093C6F1F033BAA11FDF6E3 /* Pods */ = { isa = PBXGroup; children = ( 8DA8E0C988E77F16403017FF /* Pods-RBQFRCSwiftExample.debug.xcconfig */, E3A3DB9B3608D864C439B8F3 /* Pods-RBQFRCSwiftExample.release.xcconfig */, 4E1FCB9E207C119C0AE0ED70 /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */, A9AE666DAD240A473FD1FCE6 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; EE8DED9C032A84D2CE496A23 /* Frameworks */ = { isa = PBXGroup; children = ( 18BC486F316E6B828A15ECBB /* Pods_RBQFRCSwiftExample.framework */, 562846FB89DF75BB0D5CA170 /* Pods_RBQFRCSwiftExampleTests.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */; buildPhases = ( F5EB15E6E676C45D569CB3A1 /* [CP] Check Pods Manifest.lock */, A05FA4E41B6185AE0000C9B2 /* Sources */, A05FA4E51B6185AE0000C9B2 /* Frameworks */, A05FA4E61B6185AE0000C9B2 /* Resources */, A05FA5131B6185F30000C9B2 /* Embed Frameworks */, 1272F9283761A1492F58E766 /* [CP] Embed Pods Frameworks */, A3258959C79BC2C3258342EF /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = RBQFRCSwiftExample; productName = RBQFRCSwiftExample; productReference = A05FA4E81B6185AE0000C9B2 /* RBQFRCSwiftExample.app */; productType = "com.apple.product-type.application"; }; A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */ = { isa = PBXNativeTarget; buildConfigurationList = A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */; buildPhases = ( A648BFA2463310F5310D64AA /* [CP] Check Pods Manifest.lock */, A05FA4F91B6185AE0000C9B2 /* Sources */, A05FA4FA1B6185AE0000C9B2 /* Frameworks */, A05FA4FB1B6185AE0000C9B2 /* Resources */, DFBEAACD9C329C1192D7B0CC /* [CP] Embed Pods Frameworks */, 1D8579019880ED5696A66886 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */, ); name = RBQFRCSwiftExampleTests; productName = RBQFRCSwiftExampleTests; productReference = A05FA4FD1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ A05FA4E01B6185AE0000C9B2 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Adam Fish"; TargetAttributes = { A05FA4E71B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 0810; }; A05FA4FC1B6185AE0000C9B2 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 0810; TestTargetID = A05FA4E71B6185AE0000C9B2; }; }; }; buildConfigurationList = A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = A05FA4DF1B6185AE0000C9B2; productRefGroup = A05FA4E91B6185AE0000C9B2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */, A05FA4FC1B6185AE0000C9B2 /* RBQFRCSwiftExampleTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ A05FA4E61B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA4F31B6185AE0000C9B2 /* Main.storyboard in Resources */, A05FA4F81B6185AE0000C9B2 /* LaunchScreen.xib in Resources */, A05FA4F51B6185AE0000C9B2 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4FB1B6185AE0000C9B2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 1272F9283761A1492F58E766 /* [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-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 1D8579019880ED5696A66886 /* [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-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; A3258959C79BC2C3258342EF /* [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-RBQFRCSwiftExample/Pods-RBQFRCSwiftExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; A648BFA2463310F5310D64AA /* [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; }; DFBEAACD9C329C1192D7B0CC /* [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-RBQFRCSwiftExampleTests/Pods-RBQFRCSwiftExampleTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; F5EB15E6E676C45D569CB3A1 /* [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 */ A05FA4E41B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0AB74621B6C389700923940 /* MainTableViewController.swift in Sources */, A05FA4EE1B6185AE0000C9B2 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A05FA4F91B6185AE0000C9B2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A05FA5041B6185AE0000C9B2 /* RBQFRCSwiftExampleTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ A05FA4FF1B6185AE0000C9B2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A05FA4E71B6185AE0000C9B2 /* RBQFRCSwiftExample */; targetProxy = A05FA4FE1B6185AE0000C9B2 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ A05FA4F11B6185AE0000C9B2 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( A05FA4F21B6185AE0000C9B2 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; A05FA4F61B6185AE0000C9B2 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( A05FA4F71B6185AE0000C9B2 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ A05FA5051B6185AE0000C9B2 /* 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-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.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; A05FA5061B6185AE0000C9B2 /* 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 = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; A05FA5081B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 8DA8E0C988E77F16403017FF /* Pods-RBQFRCSwiftExample.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/RBQFRCSwiftExample", ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Debug; }; A05FA5091B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E3A3DB9B3608D864C439B8F3 /* Pods-RBQFRCSwiftExample.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/RBQFRCSwiftExample", ); INFOPLIST_FILE = RBQFRCSwiftExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; }; name = Release; }; A05FA50B1B6185AE0000C9B2 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4E1FCB9E207C119C0AE0ED70 /* Pods-RBQFRCSwiftExampleTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Debug; }; A05FA50C1B6185AE0000C9B2 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = A9AE666DAD240A473FD1FCE6 /* Pods-RBQFRCSwiftExampleTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = RBQFRCSwiftExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.Realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RBQFRCSwiftExample.app/RBQFRCSwiftExample"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ A05FA4E31B6185AE0000C9B2 /* Build configuration list for PBXProject "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5051B6185AE0000C9B2 /* Debug */, A05FA5061B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA5071B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExample" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA5081B6185AE0000C9B2 /* Debug */, A05FA5091B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A05FA50A1B6185AE0000C9B2 /* Build configuration list for PBXNativeTarget "RBQFRCSwiftExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( A05FA50B1B6185AE0000C9B2 /* Debug */, A05FA50C1B6185AE0000C9B2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = A05FA4E01B6185AE0000C9B2 /* Project object */; } ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExampleTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/Swift-cocoapods/RBQFRCSwiftExampleTests/RBQFRCSwiftExampleTests.swift ================================================ // // RBQFRCSwiftExampleTests.swift // RBQFRCSwiftExampleTests // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import UIKit import XCTest class RBQFRCSwiftExampleTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. self.measure() { // Put the code you want to measure the time of here. } } } ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Roobiq Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: RBQFetchedResultsController/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass ================================================ FILE: RBQFetchedResultsController/ModuleMapFile ================================================ framework module RBQFetchedResultsController { umbrella header "RBQFRC.h" export * module * { export * } } ================================================ FILE: RBQFetchedResultsController/RBQFRC.h ================================================ // // RBQFRC.h // RBQFetchedResultsController // // Created by Atai Barkai on 1/8/16. // Copyright © 2016 Atai Barkai. All rights reserved. // #import //! Project version number for RBQFetchedResultsControllerFramework. FOUNDATION_EXPORT double RBQFetchedResultsControllerFrameworkVersionNumber; //! Project version string for RBQFetchedResultsControllerFramework. FOUNDATION_EXPORT const unsigned char RBQFetchedResultsControllerFrameworkVersionString[]; // RBQFetchedResultsController #import "RBQFetchedResultsController.h" #import "RBQFetchRequest.h" ================================================ FILE: RBQFetchedResultsController/RBQFetchedResultsControllerTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQControllerCacheObject.h ================================================ // // RBQControllerCacheObject.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import "RBQSectionCacheObject.h" /** Represents the current state of the FRC cache */ typedef NS_ENUM(NSUInteger, RBQControllerCacheState){ /** Cache is ready */ RBQControllerCacheStateReady, /** Cache is processing (if the app is forced closed in this state, the cache will be rebuilt) */ RBQControllerCacheStateProcessing }; RLM_ARRAY_TYPE(RBQSectionCacheObject) /** * Internal cache object used by RBQFetchedResultsController. * * @warning This class is not to be used external the RBQFetchedResultsController */ @interface RBQControllerCacheObject : RLMObject /** * Name for the cache */ @property NSString *name; /** * Hash for RBQFetchRequest to monitor if cache needs rebuilt */ @property NSInteger fetchRequestHash; /** * Used to track if the cache was processing while app is terminated * * @warning If cache is not ready, when requested, it will be rebuilt (this can occur if the app is forced closed while the cache is processing. */ @property NSInteger state DEPRECATED_MSG_ATTRIBUTE("Do not use."); /** * Used to track the current section name key path if any for the cache */ @property NSString *sectionNameKeyPath; /** * RBQSectionCacheObjects within cache */ @property RLMArray *sections; /** * All RBQFetchedResultsCacheObjects in cache */ @property RLMArray *objects; /** * Create RBQFetchedResultsControllerCacheObject with a name and RBQFetchRequest hash (both used for identification) * * @param name The name of the cache * @param hash A RBQFetchRequest hash used to identify the cache * * @return A new instance of RBQFetchedResultsControllerCacheObject */ + (instancetype)cacheWithName:(NSString *)name fetchRequestHash:(NSInteger)hash; @end // This protocol enables typed collections. i.e.: // RLMArray RLM_ARRAY_TYPE(RBQControllerCacheObject) ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQControllerCacheObject.m ================================================ // // RBQControllerCacheObject.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQControllerCacheObject.h" @implementation RBQControllerCacheObject + (instancetype)cacheWithName:(NSString *)name fetchRequestHash:(NSInteger)hash { RBQControllerCacheObject *cache = [[RBQControllerCacheObject alloc] init]; cache.name = name; cache.fetchRequestHash = hash; return cache; } + (NSString *)primaryKey { return @"name"; } + (NSDictionary *)defaultPropertyValues { return @{@"sectionNameKeyPath" : @"", @"state" : @(RBQControllerCacheStateReady)}; } @end ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQObjectCacheObject.h ================================================ // // RBQObjectCacheObject.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import @class RBQSectionCacheObject; /** * Internal object used by RBQFetchedResultsController. * * RBQObjectCacheObject represents the original RLMObject within the FRC cache. * * @warning This class is not to be used external the RBQFetchedResultsController */ @interface RBQObjectCacheObject : RLMObject /** * Original RLMObject class name */ @property NSString *className; /** * Primary key value represented as a string */ @property NSString *primaryKeyStringValue; /** * Primary key type (use to convert the string value if necessary) * * @warning Only supports RLMPropertyTypeInt and RLMPropertyTypeString, which are the only * supported Realm primary key types as of v0.90.5. */ @property NSInteger primaryKeyType; /** * Value for the section (i.e. the section name) */ @property NSString *sectionKeyPathValue; /** * Section for the cache object */ @property RBQSectionCacheObject *section; /** * Create RBQFetchedResultsCacheObject from RLMObject * * @param object RLMObject being represented in the cache * @param sectionValue The section key path value for this object * * @return A new instance of RBQFetchedResultsCacheObject */ + (instancetype)createCacheObjectWithObject:(RLMObjectBase *)object sectionKeyPathValue:(NSString *)sectionValue; /** * Create RBQFetchedResultsCacheObject from RBQSafeObject * * @param safeObject RBQSafeRealmObject being represented in the cache * @param sectionValue The section key path value for this object * * @return A new instance of RBQFetchedResultsCacheObject */ + (instancetype)createCacheObjectWithSafeObject:(RBQSafeRealmObject *)safeObject sectionKeyPathValue:(NSString *)sectionValue; /** * Retrieve RBQFetchedResultsCacheObject from a Realm instance from RLMObject * * @param realm The RLMRealm in which the cache object is persisted * @param object The RLMObject that is represented by the cache object * * @return A instance of RBQFetchedResultsCacheObject */ + (instancetype)cacheObjectInRealm:(RLMRealm *)realm forObject:(RLMObjectBase *)object; /** * Retrieve RLMObject in given Realm instance for RBQFetchedResultsCacheObject * * @param realm The RLMRealm in which the cache object is persisted * @param cacheObject The RBQObjectCacheObject representing the RLMObject * * @return A instance of RLMObject */ + (RLMObject *)objectInRealm:(RLMRealm *)realm forCacheObject:(RBQObjectCacheObject *)cacheObject; /** * Retrieve the primary key value from the primary key string value * * @return Instance of the original RLMObject's primary key value */ - (id)primaryKeyValue; @end // This protocol enables typed collections. i.e.: // RLMArray ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQObjectCacheObject.m ================================================ // // RBQObjectCacheObject.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQObjectCacheObject.h" #import "RBQSectionCacheObject.h" #import #import #import #import @implementation RBQObjectCacheObject #pragma mark - Public Class + (instancetype)createCacheObjectWithObject:(RLMObjectBase *)object sectionKeyPathValue:(NSString *)sectionValue { RBQObjectCacheObject *cacheObject = [[RBQObjectCacheObject alloc] init]; RLMObjectSchema *objectSchema = RLMObjectBaseObjectSchema(object); cacheObject.primaryKeyType = objectSchema.primaryKeyProperty.type; cacheObject.sectionKeyPathValue = sectionValue; cacheObject.className = [[object class] className]; id primaryKeyValue = [RLMObjectBase primaryKeyValueForObject:object]; if (cacheObject.primaryKeyType == RLMPropertyTypeString) { cacheObject.primaryKeyStringValue = (NSString *)primaryKeyValue; } else if (cacheObject.primaryKeyType == RLMPropertyTypeInt) { cacheObject.primaryKeyStringValue = ((NSNumber *)primaryKeyValue).stringValue; } else { @throw([self unsupportedPrimaryKeyTypeException]); } return cacheObject; } + (instancetype)createCacheObjectWithSafeObject:(RBQSafeRealmObject *)safeObject sectionKeyPathValue:(NSString *)sectionValue { RBQObjectCacheObject *cacheObject = [[RBQObjectCacheObject alloc] init]; cacheObject.primaryKeyType = safeObject.primaryKeyType; cacheObject.sectionKeyPathValue = sectionValue; cacheObject.className = safeObject.className; if (cacheObject.primaryKeyType == RLMPropertyTypeString) { cacheObject.primaryKeyStringValue = (NSString *)safeObject.primaryKeyValue; } else if (cacheObject.primaryKeyType == RLMPropertyTypeInt) { cacheObject.primaryKeyStringValue = ((NSNumber *)safeObject.primaryKeyValue).stringValue; } else { @throw([self unsupportedPrimaryKeyTypeException]); } return cacheObject; } + (instancetype)cacheObjectInRealm:(RLMRealm *)realm forObject:(RLMObjectBase *)object { if (object) { id primaryKeyValue = [RLMObject primaryKeyValueForObject:object]; RLMObjectSchema *objectSchema = RLMObjectBaseObjectSchema(object); RLMPropertyType primaryKeyType = objectSchema.primaryKeyProperty.type; if (primaryKeyType == RLMPropertyTypeString) { return [RBQObjectCacheObject objectInRealm:realm forPrimaryKey:primaryKeyValue]; } else if (primaryKeyType == RLMPropertyTypeInt) { NSString *primaryKeyStringValue = ((NSNumber *)primaryKeyValue).stringValue; return [RBQObjectCacheObject objectInRealm:realm forPrimaryKey:primaryKeyStringValue]; } else { @throw([self unsupportedPrimaryKeyTypeException]); } } return nil; } + (RLMObject *)objectInRealm:(RLMRealm *)realm forCacheObject:(RBQObjectCacheObject *)cacheObject { if (cacheObject.primaryKeyType == RLMPropertyTypeString) { return [realm objectWithClassName:cacheObject.className forPrimaryKey:cacheObject.primaryKeyStringValue]; } else if (cacheObject.primaryKeyType == RLMPropertyTypeInt) { NSNumber *numberFromString = @(cacheObject.primaryKeyStringValue.longLongValue); return [realm objectWithClassName:cacheObject.className forPrimaryKey:numberFromString]; } else { @throw ([self unsupportedPrimaryKeyTypeException]); } } #pragma mark - RLMObject Class + (NSString *)primaryKey { return @"primaryKeyStringValue"; } + (NSDictionary *)defaultPropertyValues { return @{@"className": @"", @"primaryKeyStringValue" : @"", @"primaryKeyType" : @(NSIntegerMin), @"sectionKeyPathValue" : @"" }; } #pragma mark - Public Instance - (id)primaryKeyValue { if (self.primaryKeyType == RLMPropertyTypeInt) { NSNumber *numberFromString = @(self.primaryKeyStringValue.integerValue); return numberFromString; } return self.primaryKeyStringValue; } #pragma mark - Equality - (BOOL)isEqualToObject:(RBQObjectCacheObject *)object { if (self.primaryKeyType == RLMPropertyTypeString && object.primaryKeyType == RLMPropertyTypeString) { return [self.primaryKeyStringValue isEqualToString:object.primaryKeyStringValue]; } else if (self.primaryKeyType == RLMPropertyTypeInt && object.primaryKeyType == RLMPropertyTypeInt) { return self.primaryKeyStringValue.integerValue == object.primaryKeyStringValue.integerValue; } else { return [super isEqual:object]; } } - (BOOL)isEqual:(id)object { return [self isEqualToObject:object]; } #pragma mark - - (id)copyWithZone:(NSZone *)zone { RBQObjectCacheObject *objectCache = [[RBQObjectCacheObject allocWithZone:zone] init]; objectCache.className = _className; objectCache.primaryKeyStringValue = _primaryKeyStringValue; objectCache.primaryKeyType = _primaryKeyType; objectCache.sectionKeyPathValue = _sectionKeyPathValue; objectCache.section = _section; return objectCache; } #pragma mark - Helper exception + (NSException *)unsupportedPrimaryKeyTypeException { return [NSException exceptionWithName:@"Unsupported primary key type" reason:@"RBQFetchedResultsController only supports NSString or int/NSInteger primary keys" userInfo:nil]; } @end ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQSectionCacheObject.h ================================================ // // RBQSectionCacheObject.h // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import "RBQObjectCacheObject.h" RLM_ARRAY_TYPE(RBQObjectCacheObject) /** * Internal object used by RBQFetchedResultsController cache. Object represents a section within the FRC cache. * * @warning This class is not to be used external the RBQFetchedResultsController */ @interface RBQSectionCacheObject : RLMObject /** * Section name */ @property NSString *name; /** * Index of the first object contained within the section */ @property NSInteger firstObjectIndex; /** * Index of the first object contained within the section */ @property NSInteger lastObjectIndex; /** * Sorted RBQFetchedResultsCacheObjects in section */ @property RLMArray *objects; /** * Create RBQSectionCacheObject with a given section name * * @param name The name of the section * * @return A new instance of RBQSectionCacheObject */ + (instancetype)cacheWithName:(NSString *)name; @end // This protocol enables typed collections. i.e.: // RLMArray ================================================ FILE: RBQFetchedResultsController/Source/CacheObjects/RBQSectionCacheObject.m ================================================ // // RBQSectionCacheObject.m // RBQFetchedResultsControllerExample // // Created by Adam Fish on 1/6/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQSectionCacheObject.h" @implementation RBQSectionCacheObject + (instancetype)cacheWithName:(NSString *)name { RBQSectionCacheObject *section = [[RBQSectionCacheObject alloc] init]; section.name = name; return section; } + (NSString *)primaryKey { return @"name"; } + (NSDictionary *)defaultPropertyValues { return @{@"firstObjectIndex" : @(NSIntegerMin), @"lastObjectIndex" : @(NSIntegerMin), @"name" : @"" }; } #pragma mark - Equality - (BOOL)isEqualToObject:(RBQSectionCacheObject *)object { return [self.name isEqualToString:object.name]; } - (BOOL)isEqual:(id)object { return [self isEqualToObject:object]; } @end ================================================ FILE: RBQFetchedResultsController/Source/RBQFetchRequest.h ================================================ // // RBQFetchRequest.h // RBQFetchedResultsControllerTest // // Created by Adam Fish on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import #import @class RBQFetchRequest, RLMRealm, RLMObject, RLMRealmConfiguration, RLMArray, RLMSortDescriptor; #pragma mark - RBQFetchRequest /** * This class is used by the RBQFetchedResultsController to represent the properties of the fetch. The RBQFetchRequest is specific to one RLMObject and uses an NSPredicate and array of RLMSortDescriptors to define the query. */ @interface RBQFetchRequest : NSObject /** * RLMObject class name for the fetch request */ @property (nonatomic, readonly, nonnull) NSString *entityName; /** * The Realm in which the entity for the fetch request is persisted. */ @property (nonatomic, readonly, nonnull) RLMRealm *realm; /** * The configuration object used to create an instance of RLMRealm for the fetch request */ @property (nonatomic, readonly, nonnull) RLMRealmConfiguration *realmConfiguration; /** * Predicate supported by Realm * * http://realm.io/docs/cocoa/0.89.2/#querying-with-predicates */ @property (nonatomic, strong, nullable) NSPredicate *predicate; /** * Array of RLMSortDescriptors * * http://realm.io/docs/cocoa/0.89.2/#ordering-results */ @property(nonatomic, strong, nullable) NSArray *sortDescriptors; /** * Constructor method to create a fetch request for a given entity name in a specific Realm. * * @param entityName Class name for the RLMObject * @param realm RLMRealm in which the RLMObject is persisted (if passing in-memory Realm, make sure to keep a strong reference elsewhere since fetch request only stores the path) * @param predicate NSPredicate that represents the search query * * @return A new instance of RBQFetchRequest */ + (nonnull instancetype)fetchRequestWithEntityName:(nonnull NSString *)entityName inRealm:(nonnull RLMRealm *)realm predicate:(nullable NSPredicate *)predicate; /** * Retrieve all the RLMObjects for this fetch request in its realm. * * @return RLMResults or RLMArray for all the objects in the fetch request (not thread-safe). */ - (nonnull id)fetchObjects; /** * Should this object be in our fetch results? * * Intended to be used by the RBQFetchedResultsController to evaluate incremental changes. For * simple fetch requests this just evaluates the NSPredicate, but subclasses may have a more * complicated implementaiton. * * @param object Realm object of appropriate type * * @return YES if performing fetch would include this object */ - (BOOL)evaluateObject:(nonnull RLMObject *)object; /** * Create RBQFetchRequest in RLMRealm instance with an entity name * * @param entityName Class name for the RLMObject * @param realm RLMRealm in which the RLMObject is persisted * * @return A new instance of RBQFetchRequest */ - (nonnull instancetype)initWithEntityName:(nonnull NSString *)entityName inRealm:(nonnull RLMRealm *)realm; @end ================================================ FILE: RBQFetchedResultsController/Source/RBQFetchRequest.m ================================================ // // RBQFetchRequest.m // RBQFetchedResultsControllerTest // // Created by Adam Fish on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQFetchRequest.h" #import #import #import #import @interface RBQFetchRequest () @property (strong, nonatomic) RLMRealm *realmForMainThread; // Improves scroll performance @end @implementation RBQFetchRequest @synthesize entityName = _entityName, realmConfiguration = _realmConfiguration; #pragma mark - Public Class + (instancetype)fetchRequestWithEntityName:(NSString *)entityName inRealm:(RLMRealm *)realm predicate:(NSPredicate *)predicate { RBQFetchRequest *fetchRequest = [[self alloc] initWithEntityName:entityName inRealm:realm]; fetchRequest.predicate = predicate; return fetchRequest; } #pragma mark - Public Instance - (instancetype)initWithEntityName:(NSString *)entityName inRealm:(RLMRealm *)realm { self = [super init]; if (self) { // Returns the appropriate class name for Obj-C or Swift _entityName = entityName; _realmConfiguration = realm.configuration; } return self; } - (id)fetchObjects { RLMResults *fetchResults = [self.realm allObjects:self.entityName]; // If we have a predicate use it if (self.predicate) { fetchResults = [fetchResults objectsWithPredicate:self.predicate]; } // If we have sort descriptors then use them if (self.sortDescriptors.count > 0) { fetchResults = [fetchResults sortedResultsUsingDescriptors:self.sortDescriptors]; } return fetchResults; } - (BOOL)evaluateObject:(RLMObject *)object { // If we have a predicate, use it if (self.predicate) { return [self.predicate evaluateWithObject:object]; } // Verify the class name of object match the entity name of fetch request NSString *className = [[object class] className]; BOOL sameEntity = [className isEqualToString:self.entityName]; return sameEntity; } #pragma mark - Getter - (RLMRealm *)realm { if ([NSThread isMainThread] && !self.realmForMainThread) { self.realmForMainThread = [RLMRealm realmWithConfiguration:self.realmConfiguration error:nil]; } if ([NSThread isMainThread]) { return self.realmForMainThread; } return [RLMRealm realmWithConfiguration:self.realmConfiguration error:nil]; } #pragma mark - Hash - (NSUInteger)hash { if (self.predicate && self.sortDescriptors) { NSUInteger sortHash = 1; for (RLMSortDescriptor *sortDescriptor in self.sortDescriptors) { sortHash = sortHash ^ sortDescriptor.hash; } return self.predicate.hash ^ sortHash ^ self.entityName.hash; } else if (self.predicate && self.entityName) { return self.predicate.hash ^ self.entityName.hash; } else { return [super hash]; } } @end ================================================ FILE: RBQFetchedResultsController/Source/RBQFetchedResultsController.h ================================================ // // RBQFetchedResultsController.h // RBQFetchedResultsControllerTest // // Created by Adam Fish on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQFetchRequest.h" #import #import @import CoreData; @class RBQFetchedResultsController; #pragma mark - RBQFetchedResultsSectionInfo /** * This class is used by the RBQFetchedResultsController to pass along section info. */ @interface RBQFetchedResultsSectionInfo : NSObject /** * The number of objects in the section. */ @property (nonatomic, readonly) NSUInteger numberOfObjects; /** * The objects in the section (generated on-demand and not thread-safe). */ @property (nonatomic, readonly, nonnull) id objects; /** * The name of the section. */ @property (nonatomic, readonly, nonnull) NSString *name; @end #pragma mark - RBQFetchedResultsControllerDelegate /** * Delegate to pass along the changes identified by the RBQFetchedResultsController. */ @protocol RBQFetchedResultsControllerDelegate /** * Indicates that the controller has started identifying changes. * * @param controller controller instance that noticed the change on its fetched objects */ - (void)controllerWillChangeContent:(nonnull RBQFetchedResultsController *)controller; /** * Notifies the delegate that a fetched object has been changed due to an add, remove, move, or update. Enables RBQFetchedResultsController change tracking. * * Changes are reported with the following heuristics: * * On add and remove operations, only the added/removed object is reported. It’s assumed that all objects that come after the affected object are also moved, but these moves are not reported. * * A move is reported when the changed attribute on the object is one of the sort descriptors used in the fetch request. An update of the object is assumed in this case, but no separate update message is sent to the delegate. * * An update is reported when an object’s state changes, but the changed attributes aren’t part of the sort keys. * * @param controller controller instance that noticed the change on its fetched objects * @param anObject changed object represented as a RBQSafeRealmObject for thread safety * @param indexPath indexPath of changed object (nil for inserts) * @param type indicates if the change was an insert, delete, move, or update * @param newIndexPath the destination path for inserted or moved objects, nil otherwise */ - (void)controller:(nonnull RBQFetchedResultsController *)controller didChangeObject:(nonnull RBQSafeRealmObject *)anObject atIndexPath:(nullable NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(nullable NSIndexPath *)newIndexPath; /** * The fetched results controller reports changes to its section before changes to the fetched result objects. * * @param controller controller controller instance that noticed the change on its fetched objects * @param section changed section represented as a RBQFetchedResultsSectionInfo object * @param sectionIndex the section index of the changed section * @param type indicates if the change was an insert or delete */ - (void)controller:(nonnull RBQFetchedResultsController *)controller didChangeSection:(nonnull RBQFetchedResultsSectionInfo *)section atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type; /** * This method is called at the end of processing changes by the controller * * @param controller controller instance that noticed the change on its fetched objects */ - (void)controllerDidChangeContent:(nonnull RBQFetchedResultsController *)controller; @optional /** * This method is called before the controller performs the fetch. * * @param controller controller instance that will perform the fetch */ - (void)controllerWillPerformFetch:(nonnull RBQFetchedResultsController *)controller; /** * This method is called after the controller successfully fetches objects. It will not be called if the fetchRequest is nil. * * @param controller controller instance that performed the fetch */ - (void)controllerDidPerformFetch:(nonnull RBQFetchedResultsController *)controller; @end #pragma mark - RBQFetchedResultsController /** * The class is used to monitor changes from a RBQRealmNotificationManager to convert these changes into specific index path or section index changes. Typically this is used to back a UITableView and support animations when items are inserted, deleted, or changed. */ @interface RBQFetchedResultsController : NSObject @property (nonatomic) bool logging; /** * The fetch request for the controller */ @property (nonatomic, readonly, nonnull) RBQFetchRequest *fetchRequest; /** * The section name key path used to create the sections. Can be nil if no sections. */ @property (nonatomic, readonly, nullable) NSString *sectionNameKeyPath; /** * The delegate to pass the index path and section changes to. */ @property (nonatomic, weak, nullable) id delegate; /** * The name of the cache used internally to represent the tableview structure. */ @property (nonatomic, readonly, nullable) NSString *cacheName; /** * All the objects that match the fetch request. */ @property (nonatomic, readonly, nonnull) id fetchedObjects; /** * Returns all the section titles if using a section name key path */ @property(nonatomic, readonly, nullable) NSArray *sectionIndexTitles; /** * Deletes the cached section information with the given name * * If name is not nil, then the cache will be cleaned, but not deleted from disk. * * If name is nil, then all caches will be deleted by removing the files from disk. * * @warning If clearing all caches (name is nil), it is recommended to do this in didFinishLaunchingWithOptions: in AppDelegate because RLMRealm files cannot be deleted from disk safely, if there are strong references to them. * * @param name The name of the cache file to delete. If name is nil, deletes all cache files. */ + (void)deleteCacheWithName:(nullable NSString *)name; /** * Retrieves all the paths for the Realm files being used as FRC caches on disk. * * The typical use case for this method is to use the paths to perform migrations in AppDelegate. The FRC cache files need to be migrated along with your other Realm files because by default Realm includes all of the properties defined in your model in all Realm files. Thus the FRC cache files will throw an exception if they are not migrated. Call setSchemaVersion:forRealmAtPath:withMigrationBlock: for each path returned in the array. * * @return NSArray of NSStrings representing the paths on disk for all FRC cache Realm files */ + (nonnull NSArray *)allCacheRealmPaths; /** * Constructor method to initialize the controller * * @warning Specify a cache name if deletion of the cache later on is necessary * * @param fetchRequest the RBQFetchRequest for the controller * @param sectionNameKeyPath A key path on result objects that returns the section name. Pass nil to indicate that the controller should generate a single section. If this key path is not the same as that specified by the first sort descriptor in fetchRequest, they must generate the same relative orderings. * @param name the cache name (if nil, cache will not be persisted and built using an in-memory Realm) * * @return A new instance of RBQFetchedResultsController */ - (nonnull id)initWithFetchRequest:(nonnull RBQFetchRequest *)fetchRequest sectionNameKeyPath:(nullable NSString *)sectionNameKeyPath cacheName:(nullable NSString *)name; /** * Method to tell the controller to perform the fetch * * @return Indicates if the fetch was successful */ - (BOOL)performFetch; /** * Call this method to force the cache to be rebuilt. * * A potential use case would be to call this in a @catch after trying to call endUpdates for the table view. If an exception is thrown, then the cache will be rebuilt and you can call reloadData on the table view. */ - (void)reset; /** * Method to retrieve the number of rows for a given section index * * @param index section index * * @return number of rows in the section */ - (NSInteger)numberOfRowsForSectionIndex:(NSInteger)index; /** * Method to retrieve the number of sections represented by the fetch request * * @return number of sections */ - (NSInteger)numberOfSections; /** * Method to retrieve the title for a given section index * * @param section section index * * @return The title of the section */ - (nonnull NSString *)titleForHeaderInSection:(NSInteger)section; /** * Method to retrieve the section index given a section name * * @warning Returns NSNotFound if there is not a section with the given name * * @param sectionName the name of the section * * @return the index of the section (returns NSNotFound if no section with the given name) */ - (NSUInteger)sectionIndexForSectionName:(nonnull NSString *)sectionName; /** * Retrieve the RBQSafeRealmObject for a given index path * * @param indexPath the index path of the object * * @return RBQSafeRealmObject */ - (nullable RBQSafeRealmObject *)safeObjectAtIndexPath:(nonnull NSIndexPath *)indexPath; /** * Retrieve the RLMObject for a given index path * * @warning Returned object is not thread-safe. * * @param indexPath the index path of the object * * @return RLMObject */ - (nullable id)objectAtIndexPath:(nonnull NSIndexPath *)indexPath; /** * Retrieve the index path for a safe object in the fetch request * * @param safeObject RBQSafeRealmObject * * @return index path of the object */ - (nullable NSIndexPath *)indexPathForSafeObject:(nonnull RBQSafeRealmObject *)safeObject; /** * Retrieve the index path for a RLMObject in the fetch request * * @param object RLMObject * * @return index path of the object */ - (nullable NSIndexPath *)indexPathForObject:(nonnull RLMObjectBase *)object; /** * Convenience method to safely update the fetch request for an existing RBQFetchResultsController * * @param fetchRequest a new instance of RBQFetchRequest * @param sectionNameKeyPath the section name key path for this fetch request (if nil, no sections will be shown) * @param performFetch indicates whether you want to immediately performFetch using the new fetch request to rebuild the cache */ - (void)updateFetchRequest:(nonnull RBQFetchRequest *)fetchRequest sectionNameKeyPath:(nullable NSString *)sectionNameKeyPath andPerformFetch:(BOOL)performFetch; @end ================================================ FILE: RBQFetchedResultsController/Source/RBQFetchedResultsController.m ================================================ // // RBQFetchedResultsController.m // RBQFetchedResultsControllerTest // // Created by Adam Fish on 1/2/15. // Copyright (c) 2015 Roobiq. All rights reserved. // #import "RBQFetchedResultsController.h" #import "RBQControllerCacheObject.h" #import "RBQSectionCacheObject.h" #import #import @import UIKit; #pragma mark - Constants static void * RBQArrayFetchRequestContext = &RBQArrayFetchRequestContext; #pragma mark - RBQFetchedResultsController @interface RBQFetchedResultsController () @property (nonatomic, strong) RLMNotificationToken *notificationToken; @property (nonatomic, strong) id notificationCollection; @property (nonatomic, strong) NSRunLoop *notificationRunLoop; @property (strong, nonatomic) RLMRealm *inMemoryRealm; @property (strong, nonatomic) RLMRealm *realmForMainThread; // Improves scroll performance @end #pragma mark - RBQFetchedResultsSectionInfo @interface RBQFetchedResultsSectionInfo () // RBQFetchRequest to support retrieving section objects @property (strong, nonatomic) RBQFetchRequest *fetchRequest; // Section name key path to support retrieving section objects @property (strong, nonatomic) NSString *sectionNameKeyPath; // Create a RBQFetchedResultsSectionInfo + (instancetype)createSectionWithName:(NSString *)sectionName sectionNameKeyPath:(NSString *)sectionNameKeyPath fetchRequest:(RBQFetchRequest *)fetchRequest; @end @implementation RBQFetchedResultsSectionInfo @synthesize name = _name; + (instancetype)createSectionWithName:(NSString *)sectionName sectionNameKeyPath:(NSString *)sectionNameKeyPath fetchRequest:(RBQFetchRequest *)fetchRequest { RBQFetchedResultsSectionInfo *sectionInfo = [[RBQFetchedResultsSectionInfo alloc] init]; sectionInfo->_name = sectionName; sectionInfo.sectionNameKeyPath = sectionNameKeyPath; sectionInfo.fetchRequest = fetchRequest; return sectionInfo; } - (id)objects { if (self.fetchRequest && self.sectionNameKeyPath) { id fetchResults = [self.fetchRequest fetchObjects]; return [fetchResults objectsWhere:@"%K == %@", self.sectionNameKeyPath, self.name]; } else if (self.fetchRequest) { return [self.fetchRequest fetchObjects]; } return nil; } - (NSUInteger)numberOfObjects { return [self objects].count; } @end #pragma mark - RBQStateObject @interface RBQStateObject : NSObject @property (strong, nonatomic) RLMRealm *realm; @property (strong, nonatomic) RLMRealm *cacheRealm; @property (strong, nonatomic) id fetchResults; @property (strong, nonatomic) RBQControllerCacheObject *cache; @end @implementation RBQStateObject @end #pragma mark - RBQChangeSetsObject @interface RBQChangeSetsObject : NSObject @property (strong, nonatomic) NSOrderedSet *cacheObjectsChangeSet; @property (strong, nonatomic) NSOrderedSet *cacheSectionsChangeSet; @property (strong, nonatomic) NSMapTable *cacheObjectToSafeObject; @end @implementation RBQChangeSetsObject @end #pragma mark - RBQSectionChangesObject @interface RBQSectionChangesObject : NSObject @property (strong, nonatomic) NSOrderedSet *oldCacheSections; @property (strong, nonatomic) NSOrderedSet *sortedNewCacheSections; @property (strong, nonatomic) NSOrderedSet *deletedCacheSections; @property (strong, nonatomic) NSOrderedSet *insertedCacheSections; @end @implementation RBQSectionChangesObject @end #pragma mark - RBQSectionChangeObject @interface RBQSectionChangeObject : NSObject @property (strong, nonatomic) NSNumber *previousIndex; @property (strong, nonatomic) NSNumber *updatedIndex; @property (strong, nonatomic) RBQSectionCacheObject *section; @property (assign, nonatomic) NSFetchedResultsChangeType changeType; @end @implementation RBQSectionChangeObject @end #pragma mark - RBQObjectChangeObject @interface RBQObjectChangeObject : NSObject @property (strong, nonatomic) NSIndexPath *previousIndexPath; @property (strong, nonatomic) NSIndexPath *updatedIndexpath; @property (assign, nonatomic) NSFetchedResultsChangeType changeType; @property (strong, nonatomic) RBQSafeRealmObject *object; @property (strong, nonatomic) RBQObjectCacheObject *previousCacheObject; @property (strong, nonatomic) RBQObjectCacheObject *updatedCacheObject; @end @implementation RBQObjectChangeObject @end #pragma mark - RBQDerivedChangesObject @interface RBQDerivedChangesObject : NSObject @property (nonatomic, strong) NSOrderedSet *deletedSectionChanges; @property (nonatomic, strong) NSOrderedSet *insertedSectionChanges; @property (nonatomic, strong) NSOrderedSet *deletedObjectChanges; @property (nonatomic, strong) NSOrderedSet *insertedObjectChanges; @property (nonatomic, strong) NSOrderedSet *movedObjectChanges; @end @implementation RBQDerivedChangesObject @end #pragma mark - RBQFetchedResultsController @implementation RBQFetchedResultsController @synthesize cacheName = _cacheName; #pragma mark - Public Class + (void)deleteCacheWithName:(NSString *)name { if (name) { RLMRealm *cacheRealm = [RBQFetchedResultsController realmForCacheName:name]; [cacheRealm beginWriteTransaction]; [cacheRealm deleteAllObjects]; [cacheRealm commitWriteTransaction]; } // No name, so lets clear all caches else { NSError *error; if (![[NSFileManager defaultManager] removeItemAtPath:[RBQFetchedResultsController basePathForCaches] error:&error]) { #ifdef DEBUG NSLog(@"%@",error.localizedDescription); #endif } } } + (NSArray *)allCacheRealmPaths { NSString *basePath = [RBQFetchedResultsController basePathForCaches]; NSURL *baseURL = [[NSURL alloc] initFileURLWithPath:basePath isDirectory:YES]; NSError *error = nil; NSArray *urlsInSyncCache = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:baseURL includingPropertiesForKeys:@[NSURLIsDirectoryKey, NSURLNameKey] options:0 error:&error]; if (error) { NSLog(@"Error retrieving sync cache directories: %@", error.localizedDescription); } NSMutableArray *cachePaths = [NSMutableArray array]; for (NSURL *url in urlsInSyncCache) { NSNumber *isDirectory = nil; NSError *error = nil; if (![url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) { NSLog(@"Error retrieving resource value: %@", error.localizedDescription); } if (isDirectory.boolValue) { NSString *name = nil; if (![url getResourceValue:&name forKey:NSURLNameKey error:&error]) { NSLog(@"Error retrieving resource value: %@", error.localizedDescription); } else { // Directory name is filename with extension stripped NSString *cachePath = [RBQFetchedResultsController cachePathWithName:name]; [cachePaths addObject:cachePath]; } } } return cachePaths.copy; } #pragma mark - Private Class // Create Realm instance for cache name + (RLMRealm *)realmForCacheName:(NSString *)cacheName { NSURL *url = [NSURL fileURLWithPath:[RBQFetchedResultsController cachePathWithName:cacheName]]; RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; config.fileURL = url; config.encryptionKey = nil; config.objectClasses = @[RBQControllerCacheObject.class, RBQObjectCacheObject.class, RBQSectionCacheObject.class]; return [RLMRealm realmWithConfiguration:config error:nil];; } // Create a file path for Realm cache with a given name + (NSString *)cachePathWithName:(NSString *)name { NSString *basePath = [RBQFetchedResultsController basePathForCaches]; BOOL isDir = NO; NSError *error = nil; //Create a unique directory for each cache NSString *uniqueDirectory = [NSString stringWithFormat:@"/%@/",name]; NSString *cachePath = [basePath stringByAppendingPathComponent:uniqueDirectory]; if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) { [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:@{NSFileProtectionKey:NSFileProtectionNone} error:&error]; if (error) { #ifdef DEBUG NSLog(@"FRC Cache Directory Creation Error: %@",error.localizedDescription); #endif } } NSString *fileName = [NSString stringWithFormat:@"%@.realm",name]; cachePath = [cachePath stringByAppendingPathComponent:fileName]; return cachePath; } + (NSString *)basePathForCaches { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPath = [paths objectAtIndex:0]; BOOL isDir = NO; NSError *error = nil; //Base path for all caches NSString *basePath = [documentPath stringByAppendingPathComponent:@"/RBQFetchedResultsControllerCache"]; if (![[NSFileManager defaultManager] fileExistsAtPath:basePath isDirectory:&isDir] && isDir == NO) { [[NSFileManager defaultManager] createDirectoryAtPath:basePath withIntermediateDirectories:NO attributes:@{NSFileProtectionKey:NSFileProtectionNone} error:&error]; if (error) { #ifdef DEBUG NSLog(@"FRC Cache Directory Creation Error: %@",error.localizedDescription); #endif } } return basePath; } + (NSString *)basePathForCacheWithName:(NSString *)name { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPath = [paths objectAtIndex:0]; BOOL isDir = NO; NSError *error = nil; //Unique directory for the cache NSString *uniqueDirectory = [NSString stringWithFormat:@"/RBQFetchedResultsControllerCache/%@",name]; NSString *cachePath = [documentPath stringByAppendingPathComponent:uniqueDirectory]; if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) { [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:@{NSFileProtectionKey:NSFileProtectionNone} error:&error]; if (error) { #ifdef DEBUG NSLog(@"FRC Cache Directory Creation Error: %@",error.localizedDescription); #endif } } return cachePath; } #pragma mark - Public Instance - (id)initWithFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)name { self = [super init]; if (self) { _cacheName = name; _fetchRequest = fetchRequest; _sectionNameKeyPath = sectionNameKeyPath; #ifdef DEBUG _logging = true; #endif } return self; } - (BOOL)performFetch { if ([self.delegate respondsToSelector:@selector(controllerWillPerformFetch:)]) { [self.delegate controllerWillPerformFetch:self]; } if (self.fetchRequest) { if (self.cacheName) { [self createCacheWithRealm:[self cacheRealm] cacheName:self.cacheName forFetchRequest:self.fetchRequest sectionNameKeyPath:self.sectionNameKeyPath]; } else { [self createCacheWithRealm:[self cacheRealm] cacheName:[self nameForFetchRequest:self.fetchRequest] forFetchRequest:self.fetchRequest sectionNameKeyPath:self.sectionNameKeyPath]; } // Only register for changes after the cache was created! [self registerChangeNotifications]; if ([self.delegate respondsToSelector:@selector(controllerDidPerformFetch:)]) { [self.delegate controllerDidPerformFetch:self]; } return YES; } @throw [NSException exceptionWithName:@"RBQException" reason:@"Unable to perform fetch; fetchRequest must be set." userInfo:nil]; return NO; } - (void)reset { RLMRealm *cacheRealm = [self cacheRealm]; [self unregisterChangeNotifications]; [cacheRealm beginWriteTransaction]; [cacheRealm deleteAllObjects]; [cacheRealm commitWriteTransaction]; [self performFetch]; [self registerChangeNotifications]; } - (RBQSafeRealmObject *)safeObjectAtIndexPath:(NSIndexPath *)indexPath { RBQControllerCacheObject *cache = [self cache]; if (indexPath.section < cache.sections.count) { RBQSectionCacheObject *section = cache.sections[indexPath.section]; if (indexPath.row < section.objects.count) { RBQObjectCacheObject *cacheObject = section.objects[indexPath.row]; RLMRealm *realm = self.fetchRequest.realm; // Call refresh to guarantee latest results [realm refresh]; RLMObject *object = [RBQObjectCacheObject objectInRealm:realm forCacheObject:cacheObject]; return [RBQSafeRealmObject safeObjectFromObject:object]; } } return nil; } - (id)objectAtIndexPath:(NSIndexPath *)indexPath { RBQControllerCacheObject *cache = [self cache]; if (indexPath.section < cache.sections.count) { RBQSectionCacheObject *section = cache.sections[indexPath.section]; if (indexPath.row < section.objects.count) { RBQObjectCacheObject *cacheObject = section.objects[indexPath.row]; RLMRealm *realm = self.fetchRequest.realm; // Call refresh to guarantee latest results [realm refresh]; return [RBQObjectCacheObject objectInRealm:realm forCacheObject:cacheObject]; } } return nil; } - (NSIndexPath *)indexPathForSafeObject:(RBQSafeRealmObject *)safeObject { RBQControllerCacheObject *cache = [self cache]; if (cache) { RLMRealm *cacheRealm = cache.realm; // Get the string value of the primaryKeyValue NSString *primaryKeyStringValue = [NSString stringWithFormat:@"%@",safeObject.primaryKeyValue]; RBQObjectCacheObject *cacheObject = [RBQObjectCacheObject objectInRealm:cacheRealm forPrimaryKey:primaryKeyStringValue]; NSInteger sectionIndex = [cache.sections indexOfObject:cacheObject.section]; NSInteger rowIndex = [cacheObject.section.objects indexOfObject:cacheObject]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]; return indexPath; } return nil; } - (NSIndexPath *)indexPathForObject:(RLMObjectBase *)object { RBQControllerCacheObject *cache = [self cache]; if (cache) { RLMRealm *cacheRealm = cache.realm; RBQObjectCacheObject *cacheObject = [RBQObjectCacheObject cacheObjectInRealm:cacheRealm forObject:object]; NSInteger sectionIndex = [cache.sections indexOfObject:cacheObject.section]; NSInteger rowIndex = [cacheObject.section.objects indexOfObject:cacheObject]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]; return indexPath; } return nil; } - (NSInteger)numberOfRowsForSectionIndex:(NSInteger)index { RBQControllerCacheObject *cache = [self cache]; if (index < cache.sections.count) { RBQSectionCacheObject *section = cache.sections[index]; return section.objects.count; } return 0; } - (NSInteger)numberOfSections { RBQControllerCacheObject *cache = [self cache]; if (cache) { return cache.sections.count; } return 0; } - (NSString *)titleForHeaderInSection:(NSInteger)section { RBQControllerCacheObject *cache = [self cache]; if (cache) { if (section < cache.sections.count) { RBQSectionCacheObject *sectionInfo = cache.sections[section]; return sectionInfo.name; } } return @""; } - (NSUInteger)sectionIndexForSectionName:(NSString *)sectionName { RBQControllerCacheObject *cache = [self cache]; if (cache) { RLMResults *sectionWithName = [cache.sections objectsWhere:@"name == %@",sectionName]; RBQSectionCacheObject *section = sectionWithName.firstObject; if (section) { return [cache.sections indexOfObject:section]; } } return NSNotFound; } - (void)updateFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath andPerformFetch:(BOOL)performFetch { @synchronized(self) { // Turn off change notifications since we are replacing fetch request // Change notifications will be re-registered if performFetch is called [self unregisterChangeNotifications]; // Updating the fetch request will force rebuild of cache automatically _sectionNameKeyPath = sectionNameKeyPath; _fetchRequest = fetchRequest; if (performFetch) { // Only performFetch if the change processing is finished [self performFetch]; } } } #pragma mark - Getters - (id)fetchedObjects { if (self.fetchRequest) { return [self.fetchRequest fetchObjects]; } return nil; } - (NSArray *)sectionIndexTitles { RBQControllerCacheObject *cache = [self cache]; if (cache) { NSArray *titles = [cache.sections valueForKey:@"name"]; return titles; } return nil; } #pragma mark - Private - (void)dealloc { // Remove the notifications [self unregisterChangeNotifications]; } - (NSSet *)safeObjectsFromChanges:(NSArray *)changes withCollection:(id)collection isInsertion:(BOOL)isInsertion { NSMutableSet *set = [NSMutableSet setWithCapacity:changes.count]; RLMRealm *cacheRealm = [self cacheRealm]; for (NSNumber *index in changes) { RBQSafeRealmObject *safeObject = nil; if (isInsertion) { RLMObject *object = [collection objectAtIndex:index.unsignedIntegerValue]; safeObject = [RBQSafeRealmObject safeObjectFromObject:object]; } else { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstObjectIndex <= %@ AND lastObjectIndex >= %@", index, index]; RLMResults *sections = [RBQSectionCacheObject objectsInRealm:cacheRealm withPredicate:predicate]; RBQSectionCacheObject *section = sections.firstObject; NSUInteger row = index.unsignedIntegerValue - section.firstObjectIndex; RBQObjectCacheObject *objectCache = [section.objects objectAtIndex:row]; safeObject = [[RBQSafeRealmObject alloc] initWithClassName:objectCache.className primaryKeyValue:objectCache.primaryKeyValue primaryKeyType:(RLMPropertyType)objectCache.primaryKeyType realm:collection.realm]; } [set addObject:safeObject]; } return set.copy; } // Register the change notification from RBQRealmNotificationManager // Is no-op if the change notifications are already registered - (void)registerChangeNotifications { typeof(self) __weak weakSelf = self; // Setup run loop if (!self.notificationRunLoop) { dispatch_semaphore_t sem = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, ^{ weakSelf.notificationRunLoop = [NSRunLoop currentRunLoop]; dispatch_semaphore_signal(sem); }); CFRunLoopRun(); }); dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); } CFRunLoopPerformBlock(self.notificationRunLoop.getCFRunLoop, kCFRunLoopDefaultMode, ^{ if (weakSelf.notificationToken) { [weakSelf.notificationToken invalidate]; weakSelf.notificationToken = nil; weakSelf.notificationCollection = nil; } weakSelf.notificationCollection = weakSelf.fetchRequest.fetchObjects; weakSelf.notificationToken = [weakSelf.notificationCollection addNotificationBlock:^(id _Nullable collection, RLMCollectionChange * _Nullable change, NSError * _Nullable error) { if (!error && change) { // Create the change sets NSSet *addedSafeObjects = [weakSelf safeObjectsFromChanges:change.insertions withCollection:collection isInsertion:YES]; NSSet *deletedSafeObjects = [weakSelf safeObjectsFromChanges:change.deletions withCollection:collection isInsertion:NO]; NSSet *changedSafeObjects = [weakSelf safeObjectsFromChanges:change.modifications withCollection:collection isInsertion:NO]; [weakSelf calculateChangesWithAddedSafeObjects:addedSafeObjects deletedSafeObjects:deletedSafeObjects changedSafeObjects:changedSafeObjects realm:collection.realm]; } }]; }); CFRunLoopWakeUp(self.notificationRunLoop.getCFRunLoop); } - (void)unregisterChangeNotifications { // Remove the notifications if (self.notificationToken) { [self.notificationToken invalidate]; self.notificationToken = nil; } // Stop the run loop if (self.notificationRunLoop) { CFRunLoopStop(self.notificationRunLoop.getCFRunLoop); self.notificationRunLoop = nil; } } #pragma mark - Change Calculations - (void)calculateChangesWithAddedSafeObjects:(NSSet *)addedSafeObjects deletedSafeObjects:(NSSet *)deletedSafeObjects changedSafeObjects:(NSSet *)changedSafeObjects realm:(RLMRealm *)realm { @synchronized(self) { #ifdef DEBUG NSAssert(addedSafeObjects, @"Added safe objects can't be nil"); NSAssert(deletedSafeObjects, @"Deleted safe objects can't be nil"); NSAssert(changedSafeObjects, @"Changed safe objects can't be nil"); NSAssert(realm, @"Realm can't be nil"); #endif /** * If we are not on the main thread then use a semaphore * to prevent condition where subsequent processing runs * before the async delegate calls complete on main thread */ BOOL useSem = NO; dispatch_semaphore_t sem = dispatch_semaphore_create(0); if (![NSThread isMainThread]) { useSem = YES; } typeof(self) __weak weakSelf = self; /** * Refresh both the cache and main Realm. * * NOTE: must use helper refresh method, so that * we prevent acting on the duplicate notification * triggered by the refresh. * * This is a requirement for any refresh called * synchronously from a RLMRealmDidChangeNotification. */ RLMRealm *cacheRealm = [self cacheRealm]; RBQControllerCacheObject *cache = [self cacheInRealm:cacheRealm]; #ifdef DEBUG NSAssert(cache, @"Cache can't be nil!"); #endif RBQStateObject *state = [self createStateObjectWithFetchRequest:self.fetchRequest realm:realm cache:cache cacheRealm:cacheRealm]; RBQChangeSetsObject *changeSets = [self createChangeSetsWithAddedSafeObjects:addedSafeObjects deletedSafeObjects:deletedSafeObjects changedSafeObjects:changedSafeObjects state:state]; // Make sure we actually identified changes // (changes might not match entity name) if (!changeSets) { #ifdef DEBUG NSLog(@"No change objects or section changes found!"); #endif return; } RBQSectionChangesObject *sectionChanges = [self createSectionChangesWithChangeSets:changeSets state:state]; if ([self.delegate respondsToSelector:@selector(controllerWillChangeContent:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controllerWillChangeContent:weakSelf]; }]; } [state.cacheRealm beginWriteTransaction]; // Create Object To Gather Up Derived Changes RBQDerivedChangesObject *derivedChanges = [self deriveChangesWithChangeSets:changeSets sectionChanges:sectionChanges state:state]; if(self.logging) { NSLog(@"%lu Derived Inserted Sections",(unsigned long)derivedChanges.insertedSectionChanges.count); NSLog(@"%lu Derived Deleted Sections",(unsigned long)derivedChanges.deletedSectionChanges.count); NSLog(@"%lu Derived Added Objects",(unsigned long)derivedChanges.insertedObjectChanges.count); NSLog(@"%lu Derived Deleted Objects",(unsigned long)derivedChanges.deletedObjectChanges.count); NSLog(@"%lu Derived Moved Objects",(unsigned long)derivedChanges.movedObjectChanges.count); } // Apply Derived Changes To Cache [self applyDerivedChangesToCache:derivedChanges state:state]; [state.cacheRealm commitWriteTransaction]; [self runOnMainThread:^(){ if ([weakSelf.delegate respondsToSelector:@selector(controllerDidChangeContent:)]) { [weakSelf.delegate controllerDidChangeContent:weakSelf]; } if (useSem) { dispatch_semaphore_signal(sem); } }]; if (useSem) { dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); } } } - (void)applyDerivedChangesToCache:(RBQDerivedChangesObject *)derivedChanges state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(derivedChanges, @"Derived changes can't be nil!"); NSAssert(state, @"State can't be nil!"); #endif // Apply Section Changes To Cache (deletes in reverse order, then inserts) for (NSOrderedSet *sectionChanges in @[derivedChanges.deletedSectionChanges, derivedChanges.insertedSectionChanges]) { for (RBQSectionChangeObject *sectionChange in sectionChanges) { if (sectionChange.changeType == NSFetchedResultsChangeDelete) { #ifdef DEBUG NSAssert(sectionChange.previousIndex.unsignedIntegerValue < state.cache.sections.count, @"Attemting to delete index that is already gone!"); #endif // Remove the section from Realm cache [state.cache.realm deleteObject:sectionChange.section]; } else if (sectionChange.changeType == NSFetchedResultsChangeInsert) { #ifdef DEBUG NSAssert(sectionChange.updatedIndex.unsignedIntegerValue <= state.cache.sections.count, @"Attemting to insert at index beyond bounds!"); #endif // Add the section to the cache [state.cache.sections insertObject:sectionChange.section atIndex:sectionChange.updatedIndex.unsignedIntegerValue]; } } } // Apply Object Changes To Cache (Must apply in correct order!) for (NSOrderedSet *objectChanges in @[derivedChanges.deletedObjectChanges, derivedChanges.insertedObjectChanges, derivedChanges.movedObjectChanges]) { for (RBQObjectChangeObject *objectChange in objectChanges) { if (objectChange.changeType == NSFetchedResultsChangeDelete) { // Remove the object from the section RBQSectionCacheObject *section = objectChange.previousCacheObject.section; [section.objects removeObjectAtIndex:objectChange.previousIndexPath.row]; // Remove the object [state.cacheRealm deleteObject:objectChange.previousCacheObject]; } else if (objectChange.changeType == NSFetchedResultsChangeInsert) { // Insert the object [state.cacheRealm addObject:objectChange.updatedCacheObject]; // Add the object to the objects array and not just to the Realm! [state.cache.objects addObject:objectChange.updatedCacheObject]; // Get the section and add it to it RBQSectionCacheObject *section = [RBQSectionCacheObject objectInRealm:state.cacheRealm forPrimaryKey:objectChange.updatedCacheObject.sectionKeyPathValue]; #ifdef DEBUG NSAssert(objectChange.updatedIndexpath.row <= section.objects.count, @"Attemting to insert at index beyond bounds!"); #endif [section.objects insertObject:objectChange.updatedCacheObject atIndex:objectChange.updatedIndexpath.row]; objectChange.updatedCacheObject.section = section; } else if (objectChange.changeType == NSFetchedResultsChangeMove) { // Delete to remove it from previous section [state.cacheRealm deleteObject:objectChange.previousCacheObject]; // Add it back in [state.cacheRealm addObject:objectChange.updatedCacheObject]; // Add the object to the objects array and not just to the Realm! [state.cache.objects addObject:objectChange.updatedCacheObject]; // Get the section and add it to it RBQSectionCacheObject *section = [RBQSectionCacheObject objectInRealm:state.cacheRealm forPrimaryKey:objectChange.updatedCacheObject.sectionKeyPathValue]; #ifdef DEBUG NSAssert(objectChange.updatedIndexpath.row <= section.objects.count, @"Attemting to insert at index beyond bounds!"); #endif [section.objects insertObject:objectChange.updatedCacheObject atIndex:objectChange.updatedIndexpath.row]; objectChange.updatedCacheObject.section = section; } } } } #pragma mark - Internal Cache // Create the internal cache for a fetch request - (void)createCacheWithRealm:(RLMRealm *)cacheRealm cacheName:(NSString *)cacheName forFetchRequest:(RBQFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath { id fetchResults = [fetchRequest fetchObjects]; // Check if we have a cache already RBQControllerCacheObject *controllerCache = [RBQControllerCacheObject objectInRealm:cacheRealm forPrimaryKey:cacheName]; [cacheRealm beginWriteTransaction]; /** * Reset the cache if the fetchRequest hash doesn't match * The count in the cache is off from the fetch results * The state was left in processing * The section name key path has changed */ if (controllerCache.fetchRequestHash != fetchRequest.hash || controllerCache.objects.count != fetchResults.count || ![controllerCache.sectionNameKeyPath isEqualToString:sectionNameKeyPath]) { [cacheRealm deleteAllObjects]; controllerCache = nil; } if (!controllerCache) { controllerCache = [RBQControllerCacheObject cacheWithName:cacheName fetchRequestHash:fetchRequest.hash]; RBQSectionCacheObject *section = nil; // Iterate over the results to create the section information NSString *currentSectionTitle = nil; //No sections being used, so create default section if (!sectionNameKeyPath) { currentSectionTitle = @""; section = [RBQSectionCacheObject cacheWithName:currentSectionTitle]; section.firstObjectIndex = 0; } NSUInteger count = 0; for (RLMObject *object in fetchResults) { if (sectionNameKeyPath) { // Check your sectionNameKeyPath if a crash occurs... NSString *sectionTitle = [object valueForKeyPath:sectionNameKeyPath]; // New Section Found --> Process It if (![sectionTitle isEqualToString:currentSectionTitle]) { // If we already gathered up the section objects, then save them if (section.objects.count > 0) { section.lastObjectIndex = count - 1; // We advanced already so we need to save previous index // Add the section to Realm [cacheRealm addOrUpdateObject:section]; // Add the section to the controller cache [controllerCache.sections addObject:section]; } // Keep track of the section title so we create one section cache per value currentSectionTitle = sectionTitle; // Reset the section object array section = [RBQSectionCacheObject cacheWithName:currentSectionTitle]; section.firstObjectIndex = count; } } // Save the final section (or if not using sections, the only section) if (count == fetchResults.count - 1) { section.lastObjectIndex = count; // Set the last object index // Add the section to Realm [cacheRealm addOrUpdateObject:section]; [controllerCache.sections addObject:section]; } // Create the cache object RBQObjectCacheObject *cacheObject = [RBQObjectCacheObject createCacheObjectWithObject:object sectionKeyPathValue:currentSectionTitle]; cacheObject.section = section; if (section) { [section.objects addObject:cacheObject]; } [controllerCache.objects addObject:cacheObject]; // Keep track of the count count ++; } // Set the section name key path, if available if (sectionNameKeyPath) { controllerCache.sectionNameKeyPath = sectionNameKeyPath; } // Add cache to Realm [cacheRealm addOrUpdateObject:controllerCache]; } [cacheRealm commitWriteTransaction]; } #pragma mark - RBQStateObject - (RBQStateObject *)createStateObjectWithFetchRequest:(RBQFetchRequest *)fetchRequest realm:(RLMRealm *)realm cache:(RBQControllerCacheObject *)cache cacheRealm:(RLMRealm *)cacheRealm { #ifdef DEBUG NSAssert(fetchRequest, @"Fetch request can't be nil"); NSAssert(realm, @"Realm can't be nil"); NSAssert(cache, @"Cache can't be nil"); NSAssert(cacheRealm, @"Cache Realm can't be nil"); #endif // Setup the state object RBQStateObject *stateObject = [[RBQStateObject alloc] init]; stateObject.realm = realm; // Get the new list of safe fetch objects stateObject.fetchResults = [fetchRequest fetchObjects]; stateObject.cache = cache; stateObject.cacheRealm = cacheRealm; return stateObject; } #pragma mark - RBQChangeSetsObject - (RBQChangeSetsObject *)createChangeSetsWithAddedSafeObjects:(NSSet *)addedSafeObjects deletedSafeObjects:(NSSet *)deletedSafeObjects changedSafeObjects:(NSSet *)changedSafeObjects state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(addedSafeObjects, @"Added safe objects request can't be nil"); NSAssert(deletedSafeObjects, @"Deleted safe objects can't be nil"); NSAssert(changedSafeObjects, @"Changed safe objects can't be nil"); NSAssert(state, @"State object can't be nil"); #endif // Get Sections In Change Set NSMutableOrderedSet *cacheSectionsInChangeSet = [[NSMutableOrderedSet alloc] init]; NSMutableOrderedSet *cacheObjectsChangeSet = [[NSMutableOrderedSet alloc] init]; NSMapTable *cacheObjectToSafeObject = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsStrongMemory]; for (NSSet *changedObjects in @[addedSafeObjects, deletedSafeObjects, changedSafeObjects]) { for (RBQSafeRealmObject *safeObject in changedObjects) { // Get the section titles in change set // Attempt to get the object from non-cache Realm RLMObject *object = [RBQSafeRealmObject objectfromSafeObject:safeObject]; // Get the string value of the primaryKeyValue NSString *primaryKeyStringValue = [NSString stringWithFormat:@"%@",safeObject.primaryKeyValue]; // If the changed object doesn't match the predicate and // was not already in the cache, then skip it if (![self.fetchRequest evaluateObject:object] && ![RBQObjectCacheObject objectInRealm:state.cacheRealm forPrimaryKey:primaryKeyStringValue]) { continue; } NSString *sectionTitle = nil; if (object && self.sectionNameKeyPath) { sectionTitle = [object valueForKeyPath:self.sectionNameKeyPath]; } else if (self.sectionNameKeyPath) { RBQObjectCacheObject *oldCacheObject = [RBQObjectCacheObject objectInRealm:state.cacheRealm forPrimaryKey:primaryKeyStringValue]; sectionTitle = oldCacheObject.section.name; } // We aren't using sections so create a dummy one with no text else { sectionTitle = @""; } if (sectionTitle) { RBQSectionCacheObject *section = [RBQSectionCacheObject objectInRealm:state.cacheRealm forPrimaryKey:sectionTitle]; if (!section) { section = [RBQSectionCacheObject cacheWithName:sectionTitle]; } [cacheSectionsInChangeSet addObject:section]; } // Get the cache object RBQObjectCacheObject *cacheObject = [RBQObjectCacheObject createCacheObjectWithSafeObject:safeObject sectionKeyPathValue:sectionTitle]; [cacheObjectsChangeSet addObject:cacheObject]; // Set the map to quickly retrieve safe objects later on [cacheObjectToSafeObject setObject:safeObject forKey:cacheObject]; } } if (cacheSectionsInChangeSet.count > 0 || cacheObjectsChangeSet.count > 0) { RBQChangeSetsObject *changeSets = [[RBQChangeSetsObject alloc] init]; changeSets.cacheSectionsChangeSet = cacheSectionsInChangeSet.copy; changeSets.cacheObjectsChangeSet = cacheObjectsChangeSet.copy; changeSets.cacheObjectToSafeObject = cacheObjectToSafeObject; return changeSets; } return nil; } #pragma mark - RBQSectionChangesObject - (RBQSectionChangesObject *)createSectionChangesWithChangeSets:(RBQChangeSetsObject *)changeSets state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(changeSets, @"Change sets can't be nil"); NSAssert(state, @"State can't be nil"); #endif // Get Old Sections NSMutableOrderedSet *oldSections = [[NSMutableOrderedSet alloc] init]; for (RBQSectionCacheObject *section in state.cache.sections) { [oldSections addObject:section]; } // Combine Old With Change Set (without dupes!) NSMutableOrderedSet *oldAndChange = [NSMutableOrderedSet orderedSetWithOrderedSet:oldSections]; for (RBQSectionCacheObject *section in changeSets.cacheSectionsChangeSet) { if (![oldAndChange containsObject:section]) { [oldAndChange addObject:section]; } } NSMutableOrderedSet *newSections = [[NSMutableOrderedSet alloc] init]; NSMutableOrderedSet *deletedSections = [[NSMutableOrderedSet alloc] init]; // Loop through to identify the new sections in fetchResults for (RBQSectionCacheObject *section in oldAndChange) { id sectionResults = nil; if (self.sectionNameKeyPath) { sectionResults = [state.fetchResults objectsWhere:@"%K == %@", self.sectionNameKeyPath, section.name]; } // We aren't using sections, so just use all results else { sectionResults = state.fetchResults; } if (sectionResults.count > 0) { RLMObject *firstObject = [sectionResults firstObject]; RLMObject *lastObject = [sectionResults lastObject]; NSInteger firstObjectIndex = [state.fetchResults indexOfObject:firstObject]; NSInteger lastObjectIndex = [state.fetchResults indexOfObject:lastObject]; // Write change to object index to cache Realm [state.cacheRealm beginWriteTransaction]; section.firstObjectIndex = firstObjectIndex; section.lastObjectIndex = lastObjectIndex; [state.cacheRealm commitWriteTransaction]; // Get the entire list of all sections after the change [newSections addObject:section]; } // Add to deleted only if this section was already in cache // Possible to add a section that has no data (so we don't want to insert or delete it) else { if ([state.cache.sections indexOfObject:section] != NSNotFound) { [deletedSections addObject:section]; } } } // Now sort the sections (sort inserts to be ascending) NSSortDescriptor *sortByFirstIndex = [NSSortDescriptor sortDescriptorWithKey:@"firstObjectIndex" ascending:YES]; [newSections sortUsingDescriptors:@[sortByFirstIndex]]; // Sort the deleted sections NSSortDescriptor *descendingDeleteSort = [NSSortDescriptor sortDescriptorWithKey:@"firstObjectIndex" ascending:NO]; [deletedSections sortUsingDescriptors:@[descendingDeleteSort]]; // Find inserted sections NSMutableOrderedSet *insertedSections = [NSMutableOrderedSet orderedSetWithOrderedSet:newSections]; // Remove the old sections to identify only the inserted [insertedSections removeObjectsInArray:oldSections.array]; RBQSectionChangesObject *sectionChanges = [[RBQSectionChangesObject alloc] init]; // Save the section collections sectionChanges.oldCacheSections = oldSections.copy; sectionChanges.deletedCacheSections = deletedSections.copy; sectionChanges.insertedCacheSections = insertedSections.copy; sectionChanges.sortedNewCacheSections = newSections.copy; return sectionChanges; } #pragma mark - RBQObjectChangeObject - (RBQObjectChangeObject *)objectChangeWithCacheObject:(RBQObjectCacheObject *)cacheObject changeSets:(RBQChangeSetsObject *)changeSets sectionChanges:(RBQSectionChangesObject *)sectionChanges state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(cacheObject, @"Cache object can't be nil"); NSAssert(changeSets, @"Change sets can't be nil"); NSAssert(sectionChanges, @"Change sets can't be nil"); NSAssert(state, @"State can't be nil"); #endif RBQObjectChangeObject *objectChange = [[RBQObjectChangeObject alloc] init]; objectChange.previousCacheObject = [RBQObjectCacheObject objectInRealm:state.cacheRealm forPrimaryKey:cacheObject.primaryKeyStringValue]; RBQSectionCacheObject *oldSectionForObject = objectChange.previousCacheObject.section; // Get old indexPath if we can if (oldSectionForObject && objectChange.previousCacheObject) { NSInteger oldSectionIndex = [sectionChanges.oldCacheSections indexOfObject:oldSectionForObject]; NSInteger oldRowIndex = [oldSectionForObject.objects indexOfObject:objectChange.previousCacheObject]; objectChange.previousIndexPath = [NSIndexPath indexPathForRow:oldRowIndex inSection:oldSectionIndex]; } // Get new indexPath if we can // No need to refresh on the non-cache Realm, since this causes recursion // (refresh sends RLMRealmDidChangeNotification causing FRC processing to start anew) RLMObject *updatedObject = [RBQObjectCacheObject objectInRealm:state.realm forCacheObject:cacheObject]; if (updatedObject) { NSInteger newAllObjectIndex = [state.fetchResults indexOfObject:updatedObject]; if (newAllObjectIndex != NSNotFound) { RBQSectionCacheObject *newSection = nil; NSInteger newSectionIndex = 0; for (RBQSectionCacheObject *section in sectionChanges.sortedNewCacheSections) { if (newAllObjectIndex >= section.firstObjectIndex && newAllObjectIndex <= section.lastObjectIndex) { newSection = section; break; } newSectionIndex ++; } NSInteger newRowIndex = newAllObjectIndex - newSection.firstObjectIndex; objectChange.updatedCacheObject = cacheObject; objectChange.updatedIndexpath = [NSIndexPath indexPathForRow:newRowIndex inSection:newSectionIndex]; } } if (objectChange.previousIndexPath || objectChange.updatedIndexpath) { return objectChange; } return nil; } #pragma mark - RBQDerivedChangesObject - (RBQDerivedChangesObject *)deriveChangesWithChangeSets:(RBQChangeSetsObject *)changeSets sectionChanges:(RBQSectionChangesObject *)sectionChanges state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(changeSets, @"Change sets can't be nil!"); NSAssert(sectionChanges, @"Section changes can't be nil!"); NSAssert(state, @"State can't be nil!"); #endif RBQDerivedChangesObject *derivedChanges = [[RBQDerivedChangesObject alloc] init]; // --------------- // Section Changes // --------------- [self updateDerivedChangesWithSectionChanges:derivedChanges changeSets:changeSets sectionChanges:sectionChanges]; #ifdef DEBUG NSAssert(derivedChanges.deletedSectionChanges, @"Deleted sections changes array can't be nil!"); NSAssert(derivedChanges.insertedSectionChanges, @"Inserted sections changes array can't be nil!"); #endif // --------------- // Object Changes // --------------- [self updateDerivedChangesWithObjectChanges:derivedChanges changeSets:changeSets sectionChanges:sectionChanges state:state]; #ifdef DEBUG NSAssert(derivedChanges.deletedObjectChanges, @"Deleted objects array can't be nil!"); NSAssert(derivedChanges.insertedObjectChanges, @"Inserted objects array can't be nil!"); NSAssert(derivedChanges.movedObjectChanges, @"Moved objects array can't be nil!"); #endif return derivedChanges; } - (void)updateDerivedChangesWithSectionChanges:(RBQDerivedChangesObject *)derivedChanges changeSets:(RBQChangeSetsObject *)changeSets sectionChanges:(RBQSectionChangesObject *)sectionChanges { #ifdef DEBUG NSAssert(changeSets, @"Change sets can't be nil!"); NSAssert(sectionChanges, @"Section changes can't be nil!"); NSAssert(self.fetchRequest, @"Fetch request can't be nil!"); #endif NSMutableOrderedSet *deletedSectionChanges = [[NSMutableOrderedSet alloc] initWithCapacity:sectionChanges.deletedCacheSections.count]; NSMutableOrderedSet *insertedSectionChanges = [[NSMutableOrderedSet alloc] initWithCapacity:sectionChanges.insertedCacheSections.count]; typeof(self) __weak weakSelf = self; // Deleted Sections for (RBQSectionCacheObject *section in sectionChanges.deletedCacheSections) { NSInteger oldSectionIndex = [sectionChanges.oldCacheSections indexOfObject:section]; RBQFetchedResultsSectionInfo *sectionInfo = [RBQFetchedResultsSectionInfo createSectionWithName:section.name sectionNameKeyPath:self.sectionNameKeyPath fetchRequest:self.fetchRequest]; if ([self.delegate respondsToSelector:@selector(controller:didChangeSection:atIndex:forChangeType:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeSection:sectionInfo atIndex:oldSectionIndex forChangeType:NSFetchedResultsChangeDelete]; }]; } // Create the section change object RBQSectionChangeObject *sectionChange = [[RBQSectionChangeObject alloc] init]; sectionChange.previousIndex = @(oldSectionIndex); sectionChange.section = section; sectionChange.changeType = NSFetchedResultsChangeDelete; [deletedSectionChanges addObject:sectionChange]; } // Inserted Sections for (RBQSectionCacheObject *section in sectionChanges.insertedCacheSections) { NSInteger newSectionIndex = [sectionChanges.sortedNewCacheSections indexOfObject:section]; RBQFetchedResultsSectionInfo *sectionInfo = [RBQFetchedResultsSectionInfo createSectionWithName:section.name sectionNameKeyPath:self.sectionNameKeyPath fetchRequest:self.fetchRequest]; if ([self.delegate respondsToSelector:@selector(controller:didChangeSection:atIndex:forChangeType:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeSection:sectionInfo atIndex:newSectionIndex forChangeType:NSFetchedResultsChangeInsert]; }]; } // Create the section change object RBQSectionChangeObject *sectionChange = [[RBQSectionChangeObject alloc] init]; sectionChange.updatedIndex = @(newSectionIndex); sectionChange.section = section; sectionChange.changeType = NSFetchedResultsChangeInsert; [insertedSectionChanges addObject:sectionChange]; } // Sort the changes (Deleted is reverse sort) [deletedSectionChanges sortUsingComparator:^NSComparisonResult(RBQSectionChangeObject *sec1, RBQSectionChangeObject *sec2) { // Compare the index (reverse sort) return [sec2.previousIndex compare:sec1.previousIndex]; }]; [insertedSectionChanges sortUsingComparator:^NSComparisonResult(RBQSectionChangeObject *sec1, RBQSectionChangeObject *sec2) { // Compare the index return [sec1.updatedIndex compare:sec2.updatedIndex]; }]; derivedChanges.deletedSectionChanges = deletedSectionChanges.copy; derivedChanges.insertedSectionChanges = insertedSectionChanges.copy; } - (void)updateDerivedChangesWithObjectChanges:(RBQDerivedChangesObject *)derivedChanges changeSets:(RBQChangeSetsObject *)changeSets sectionChanges:(RBQSectionChangesObject *)sectionChanges state:(RBQStateObject *)state { #ifdef DEBUG NSAssert(derivedChanges, @"Derived changes can't be nil!"); NSAssert(changeSets, @"Change sets can't be nil!"); NSAssert(sectionChanges, @"Section changes can't be nil!"); NSAssert(state, @"State can't be nil!"); #endif typeof(self) __weak weakSelf = self; // We will first process to find inserts/deletes NSMutableOrderedSet *deletedObjectChanges = [[NSMutableOrderedSet alloc] init]; NSMutableOrderedSet *insertedObjectChanges = [[NSMutableOrderedSet alloc] init]; NSMutableDictionary *deletedObjectChangesBySection = [[NSMutableDictionary alloc] init]; NSMutableDictionary *insertedObjectChangesBySection = [[NSMutableDictionary alloc] init]; /** * We will collect any cache objects that aren't inserts/deletes to * process them in a second batch to find moves/updates */ NSMutableSet *moveOrUpdateObjectChanges = [[NSMutableSet alloc] init]; for (RBQObjectCacheObject *cacheObject in changeSets.cacheObjectsChangeSet) { RBQObjectChangeObject *objectChange = [self objectChangeWithCacheObject:cacheObject changeSets:changeSets sectionChanges:sectionChanges state:state]; // If we didn't get an object change then skip if (!objectChange) { continue; } // Deleted Objects if (!objectChange.updatedIndexpath && objectChange.previousIndexPath) { RBQSafeRealmObject *safeObject = [changeSets.cacheObjectToSafeObject objectForKey:objectChange.previousCacheObject]; #ifdef DEBUG NSAssert(safeObject, @"Safe object can't be nil!"); #endif if ([self.delegate respondsToSelector: @selector(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeObject:safeObject atIndexPath:objectChange.previousIndexPath forChangeType:NSFetchedResultsChangeDelete newIndexPath:nil]; }]; } objectChange.changeType = NSFetchedResultsChangeDelete; [deletedObjectChanges addObject:objectChange]; NSMutableOrderedSet *deletedChangesInSection = [deletedObjectChangesBySection objectForKey:@(objectChange.previousIndexPath.section)]; if (!deletedChangesInSection) { deletedChangesInSection = [[NSMutableOrderedSet alloc] init]; [deletedObjectChangesBySection setObject:deletedChangesInSection forKey:@(objectChange.previousIndexPath.section)]; } [deletedChangesInSection addObject:objectChange]; } // Inserted Objects else if (objectChange.updatedIndexpath && !objectChange.previousIndexPath) { RBQSafeRealmObject *safeObject = [changeSets.cacheObjectToSafeObject objectForKey:objectChange.updatedCacheObject]; #ifdef DEBUG NSAssert(safeObject, @"Safe object can't be nil!"); #endif if ([self.delegate respondsToSelector: @selector(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeObject:safeObject atIndexPath:nil forChangeType:NSFetchedResultsChangeInsert newIndexPath:objectChange.updatedIndexpath]; }]; } objectChange.changeType = NSFetchedResultsChangeInsert; [insertedObjectChanges addObject:objectChange]; NSMutableOrderedSet *insertedChangesInSection = [insertedObjectChangesBySection objectForKey:@(objectChange.updatedIndexpath.section)]; if (!insertedChangesInSection) { insertedChangesInSection = [[NSMutableOrderedSet alloc] init]; [insertedObjectChangesBySection setObject:insertedChangesInSection forKey:@(objectChange.updatedIndexpath.section)]; } [insertedChangesInSection addObject:objectChange]; } // For all objectChanges that are not inserts/deletes, store them to process next else { [moveOrUpdateObjectChanges addObject:objectChange]; } } // Sort the collections (deleted reverse sort) [deletedObjectChanges sortUsingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths (reverse sort) return [obj2.previousIndexPath compare:obj1.previousIndexPath]; }]; for (NSNumber *key in deletedObjectChangesBySection) { NSMutableOrderedSet *deletedChangesInSection = deletedObjectChangesBySection[key]; [deletedChangesInSection sortUsingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths (reverse sort) return [obj2.previousIndexPath compare:obj1.previousIndexPath]; }]; } [insertedObjectChanges sortUsingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths return [obj1.updatedIndexpath compare:obj2.updatedIndexpath]; }]; for (NSNumber *key in insertedObjectChangesBySection) { NSMutableOrderedSet *insertedChangesInSection = insertedObjectChangesBySection[key]; [insertedChangesInSection sortUsingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths return [obj1.updatedIndexpath compare:obj2.updatedIndexpath]; }]; } NSMutableOrderedSet *movedObjectChanges = [[NSMutableOrderedSet alloc] init]; /** * Now we will process the remaining items to identify moves/updates * * To accurately find moves, we need to calculate the absolute change to the section and row * * To identify absolute changes, we need to figure out the relative changes to sections and rows * * Initially, relative section changes were calculated, but in practice UITableview just wants * section changes reported as moves. However, there is a unique situation where the indexPath * doesn't change on an object, but the section was deleted and inserted on itself, so we use * the section changes to catch this scenario. */ /** * First we will create two collections: the inserted section indexes and deleted section indexes * * Both of these will be used for any relative section change checking * * Note: this might not need to be sorted as a potential performance improvement (legacy * from calculating relative section changes, but leaving aside for now). */ NSMutableOrderedSet *insertedSectionIndexes = [[NSMutableOrderedSet alloc] initWithCapacity:sectionChanges.insertedCacheSections.count]; for (RBQSectionCacheObject *sectionCache in sectionChanges.insertedCacheSections) { NSNumber *index = @([sectionChanges.sortedNewCacheSections indexOfObject:sectionCache]); [insertedSectionIndexes addObject:index]; } // Sort the indexes [insertedSectionIndexes sortUsingComparator:^NSComparisonResult(NSNumber *num1, NSNumber *num2) { // Compare the NSNumbers return [num1 compare:num2]; }]; NSMutableOrderedSet *deletedSectionIndexes = [[NSMutableOrderedSet alloc] initWithCapacity:sectionChanges.deletedCacheSections.count]; for (RBQSectionCacheObject *sectionCache in sectionChanges.deletedCacheSections) { NSNumber *index = @([sectionChanges.oldCacheSections indexOfObject:sectionCache]); [deletedSectionIndexes addObject:index]; } // Sort the indexes [deletedSectionIndexes sortUsingComparator:^NSComparisonResult(NSNumber *num1, NSNumber *num2) { // Compare the NSNumbers return [num1 compare:num2]; }]; /** * Now that we have the inserted/deleted section index collections and * the inserted/deleted objectChange collections, we can process the remaining * objectChanges to accurately identify moves */ for (RBQObjectChangeObject *objectChange in moveOrUpdateObjectChanges) { /** * Since we didn't find a section change, now we have to get * the relative row changes for the section */ NSOrderedSet *insertedObjectChangesForSection = [insertedObjectChangesBySection objectForKey:@(objectChange.updatedIndexpath.section)]; NSUInteger rowInserts = 0; if (insertedObjectChangesForSection) { /** * Get the number of row inserts that occurred * before the updated indexPath * * We calculate this by asking for the index if * we were to insert object into the insert collection */ NSRange sortRangeRowInserts = NSMakeRange(0, insertedObjectChanges.count); rowInserts = [insertedObjectChanges indexOfObject:objectChange inSortedRange:sortRangeRowInserts options:NSBinarySearchingInsertionIndex usingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths return [obj1.updatedIndexpath compare:obj2.updatedIndexpath]; }]; } NSOrderedSet *deletedObjectChangesForSection = [deletedObjectChangesBySection objectForKey:@(objectChange.previousIndexPath.section)]; NSUInteger rowDeletes = 0; if (deletedObjectChangesForSection) { /** * Get the number of row deletes that occurred * before the updated indexPath * * We calculate this by asking for the index if * we were to insert object into the delete collection */ NSRange sortRangeRowDeletes = NSMakeRange(0, deletedObjectChanges.count); rowDeletes = [deletedObjectChanges indexOfObject:objectChange inSortedRange:sortRangeRowDeletes options:NSBinarySearchingInsertionIndex usingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths return [obj1.previousIndexPath compare:obj2.previousIndexPath]; }]; } NSInteger relativeRowChange = rowInserts - rowDeletes; /** * If an object is moving from one section to another, * but that section index stays the same this needs to be * reported as a move and not an update (the indexPath's are * the same, but UITableView wants a move reported). */ BOOL objectSectionReplacedItself = NO; if ([objectChange.updatedIndexpath compare:objectChange.previousIndexPath] == NSOrderedSame && ([insertedSectionIndexes containsObject:@(objectChange.updatedIndexpath.section)] || [deletedSectionIndexes containsObject:@(objectChange.updatedIndexpath.section)])) { objectSectionReplacedItself = YES; } /** * Now that we have the relative row change, we can identify if there * was an absolute change and report the move. * Also report move if the section change replaced itself * (i.e. indexPath is the same, but we deleted and inserted * a section at the same index) * * Report a move if the object changes section (even if relative) */ if (([objectChange.updatedIndexpath compare:objectChange.previousIndexPath] != NSOrderedSame && (objectChange.updatedIndexpath.row - objectChange.previousIndexPath.row) != relativeRowChange) || objectChange.updatedIndexpath.section != objectChange.previousIndexPath.section || objectSectionReplacedItself) { RBQSafeRealmObject *safeObject = [changeSets.cacheObjectToSafeObject objectForKey:objectChange.previousCacheObject]; #ifdef DEBUG NSAssert(safeObject, @"Safe object can't be nil!"); #endif if ([self.delegate respondsToSelector: @selector(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeObject:safeObject atIndexPath:objectChange.previousIndexPath forChangeType:NSFetchedResultsChangeMove newIndexPath:objectChange.updatedIndexpath]; }]; } objectChange.changeType = NSFetchedResultsChangeMove; [movedObjectChanges addObject:objectChange]; } /** * Finally, if the objectChange wasn't an absolute section change or an * absolute row change, we just report it as an update */ else { RBQSafeRealmObject *safeObject = [changeSets.cacheObjectToSafeObject objectForKey:objectChange.previousCacheObject]; #ifdef DEBUG NSAssert(safeObject, @"Safe object can't be nil!"); #endif if ([self.delegate respondsToSelector: @selector(controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:)]) { [self runOnMainThread:^(){ [weakSelf.delegate controller:weakSelf didChangeObject:safeObject atIndexPath:objectChange.previousIndexPath forChangeType:NSFetchedResultsChangeUpdate newIndexPath:objectChange.updatedIndexpath]; }]; } } } // Sort the moved object changes by updated indexPath [movedObjectChanges sortUsingComparator:^NSComparisonResult(RBQObjectChangeObject *obj1, RBQObjectChangeObject *obj2) { // Compare the indexPaths return [obj1.updatedIndexpath compare:obj2.updatedIndexpath]; }]; derivedChanges.deletedObjectChanges = deletedObjectChanges.copy; derivedChanges.insertedObjectChanges = insertedObjectChanges.copy; derivedChanges.movedObjectChanges = movedObjectChanges.copy; } #pragma mark - Helpers // Create instance of Realm for internal cache - (RLMRealm *)cacheRealm { if (self.cacheName) { if ([NSThread isMainThread] && self.realmForMainThread) { return self.realmForMainThread; } RLMRealm *realm = [RBQFetchedResultsController realmForCacheName:self.cacheName]; if ([NSThread isMainThread]) { self.realmForMainThread = realm; } return realm; } else { RLMRealmConfiguration *inMemoryConfiguration = [RLMRealmConfiguration defaultConfiguration]; inMemoryConfiguration.inMemoryIdentifier = [self nameForFetchRequest:self.fetchRequest]; inMemoryConfiguration.encryptionKey = nil; inMemoryConfiguration.objectClasses = @[RBQControllerCacheObject.class, RBQObjectCacheObject.class, RBQSectionCacheObject.class]; RLMRealm *realm = [RLMRealm realmWithConfiguration:inMemoryConfiguration error:nil]; // Hold onto a strong reference so inMemory realm cache doesn't get deallocated // We don't use the cache since this is deprecated // If the realm path changed (new fetch request then hold onto the new one) if (!self.inMemoryRealm || ![realm.configuration.fileURL.path.lastPathComponent isEqualToString:self.inMemoryRealm.configuration.fileURL.path.lastPathComponent]) { self.inMemoryRealm = realm; } return realm; } return nil; } // Retrieve internal cache - (RBQControllerCacheObject *)cache { RLMRealm *cacheRealm = [self cacheRealm]; [cacheRealm refresh]; RBQControllerCacheObject *cache = [self cacheInRealm:cacheRealm]; return cache; } - (RBQControllerCacheObject *)cacheInRealm:(RLMRealm *)realm { if (self.cacheName) { return [RBQControllerCacheObject objectInRealm:realm forPrimaryKey:self.cacheName]; } else { return [RBQControllerCacheObject objectInRealm:realm forPrimaryKey:[self nameForFetchRequest:self.fetchRequest]]; } return nil; } // Create a computed name for a fetch request - (NSString *)nameForFetchRequest:(RBQFetchRequest *)fetchRequest { return [NSString stringWithFormat:@"%lu-cache",(unsigned long)fetchRequest.hash]; } /** Apparently iOS 7+ NSIndexPath's can sometimes be UIMutableIndexPaths: http://stackoverflow.com/questions/18919459/ios-7-beginupdates-endupdates-inconsistent/18920573#18920573 This foils using them as dictionary keys since isEqual: fails between an equivalent NSIndexPath and UIMutableIndexPath. */ - (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath { if ([indexPath class] == [NSIndexPath class]) { return indexPath; } return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]; } - (void)runOnMainThread:(void (^)(void))mainThreadBlock { if ([NSThread isMainThread]) { mainThreadBlock(); } else { dispatch_async(dispatch_get_main_queue(), mainThreadBlock); } } @end ================================================ FILE: RBQFetchedResultsController/Source/Swift/FetchRequest.swift ================================================ // // FetchRequest.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import Realm import RealmSwift /** This class is used by the FetchedResultsController to represent the properties of the fetch. The FetchRequest is specific to one Object and uses an NSPredicate and array of SortDescriptors to define the query. */ open class FetchRequest { // MARK: Initializers /** Constructor method to create a fetch request for a given entity name in a specific Realm. :param: realm Realm in which the Object is persisted (if passing in-memory Realm, make sure to keep a strong reference elsewhere since fetch request only stores the path) :param predicate NSPredicate that represents the search query or nil if all objects should be included :returns: A new instance of FetchRequest */ public init(realm: Realm, predicate: NSPredicate?) { let entityName = T.className() self.realmConfiguration = realm.configuration let rlmConfiguration: RLMRealmConfiguration = ObjectiveCSupport.convert(object: realm.configuration) let rlmRealm = try! RLMRealm(configuration: rlmConfiguration) self.rbqFetchRequest = RBQFetchRequest(entityName: entityName, in: rlmRealm, predicate: predicate) } // MARK: Properties /// Object class name for the fetch request open var entityName: String { return self.rbqFetchRequest.entityName } /// The Realm in which the entity for the fetch request is persisted. open var realm: Realm { return try! Realm(configuration: self.realmConfiguration) } /// The configuration object used to create an instance of Realm for the fetch request public let realmConfiguration: Realm.Configuration /// Predicate supported by Realm /// /// http://realm.io/docs/cocoa/0.89.2/#querying-with-predicates open var predicate: NSPredicate? { get { return self.rbqFetchRequest.predicate } set { self.rbqFetchRequest.predicate = predicate } } /// Array of SortDescriptors /// /// http://realm.io/docs/cocoa/0.89.2/#ordering-results open var sortDescriptors: [RealmSwift.SortDescriptor] { get { var sortDescriptors: [RealmSwift.SortDescriptor] = [] if let rbqSortDescriptors = self.rbqFetchRequest.sortDescriptors { for rlmSortDesc in rbqSortDescriptors { sortDescriptors.append(SortDescriptor(keyPath: rlmSortDesc.keyPath, ascending: rlmSortDesc.ascending)) } } return sortDescriptors } set { var rbqSortDescriptors = [RLMSortDescriptor]() for sortDesc in newValue { let rlmSortDesc = RLMSortDescriptor(keyPath: sortDesc.keyPath, ascending: sortDesc.ascending) rbqSortDescriptors.append(rlmSortDesc) } self.rbqFetchRequest.sortDescriptors = rbqSortDescriptors } } // MARK: Functions /** Retrieve all the Objects for this fetch request in its realm. @return Results for all the objects in the fetch request (not thread-safe). */ open func fetchObjects() -> Results { // var fetchResults = self.realm.objects(T) var fetchResults = self.realm.objects(T.self) // If we have a predicate use it if let predicate = self.predicate { fetchResults = fetchResults.filter(predicate) } // If we have sort descriptors then use them if (self.sortDescriptors.count > 0) { fetchResults = fetchResults.sorted(by: self.sortDescriptors) } return fetchResults } /** Should this object be in our fetch results? Intended to be used by the FetchedResultsController to evaluate incremental changes. For simple fetch requests this just evaluates the NSPredicate, but subclasses may have a more complicated implementaiton. :param: object Realm object of appropriate type :returns: YES if performing fetch would include this object */ open func evaluateObject(_ object: T) -> Bool { if let predicate = self.predicate { return predicate.evaluate(with: object) } return true } // MARK: Private functions/properties internal let rbqFetchRequest: RBQFetchRequest } ================================================ FILE: RBQFetchedResultsController/Source/Swift/FetchedResultsController.swift ================================================ // // FetchedResultsController.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import RBQSafeRealmObject import SafeRealmObject import Realm import RealmSwift /** This class is used by the FetchedResultsController to pass along section info. */ open class FetchResultsSectionInfo { // MARK: Properties /** The number of objects in the section. */ open var numberOfObjects: UInt { return self.rbqFetchedResultsSectionInfo.numberOfObjects } /** The objects in the section (generated on-demand and not thread-safe). */ open var objects: Results { if self.sectionNameKeyPath != nil { return self.fetchRequest.fetchObjects().filter("%K == %@", self.sectionNameKeyPath!, self.rbqFetchedResultsSectionInfo.name) } return self.fetchRequest.fetchObjects() } /** The name of the section. */ open var name: String { return self.rbqFetchedResultsSectionInfo.name } // MARK: Private functions/properties internal let rbqFetchedResultsSectionInfo: RBQFetchedResultsSectionInfo internal let fetchRequest: FetchRequest internal let sectionNameKeyPath: String? internal init(rbqFetchedResultsSectionInfo: RBQFetchedResultsSectionInfo, fetchRequest: FetchRequest, sectionNameKeyPath: String?) { self.rbqFetchedResultsSectionInfo = rbqFetchedResultsSectionInfo self.fetchRequest = fetchRequest self.sectionNameKeyPath = sectionNameKeyPath } } /** Delegate to pass along the changes identified by the FetchedResultsController. */ public protocol FetchedResultsControllerDelegate: class { /** Indicates that the controller has started identifying changes. :param: controller controller instance that noticed the change on its fetched objects */ func controllerWillChangeContent(_ controller: FetchedResultsController) /** Notifies the delegate that a fetched object has been changed due to an add, remove, move, or update. Enables FetchedResultsController change tracking. Changes are reported with the following heuristics: On add and remove operations, only the added/removed object is reported. It’s assumed that all objects that come after the affected object are also moved, but these moves are not reported. A move is reported when the changed attribute on the object is one of the sort descriptors used in the fetch request. An update of the object is assumed in this case, but no separate update message is sent to the delegate. An update is reported when an object’s state changes, but the changed attributes aren’t part of the sort keys. :param: controller controller instance that noticed the change on its fetched objects :param: anObject changed object represented as a SafeObject for thread safety :param: indexPath indexPath of changed object (nil for inserts) :param: type indicates if the change was an insert, delete, move, or update :param: newIndexPath the destination path for inserted or moved objects, nil otherwise */ func controller(_ controller: FetchedResultsController, didChangeObject anObject: SafeObject, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) /** The fetched results controller reports changes to its section before changes to the fetched result objects. :param: controller controller controller instance that noticed the change on its fetched objects :param: section changed section represented as a FetchedResultsSectionInfo object :param: sectionIndex the section index of the changed section :param: type indicates if the change was an insert or delete */ func controllerDidChangeSection(_ controller: FetchedResultsController, section: FetchResultsSectionInfo, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) /** This method is called at the end of processing changes by the controller :param: controller controller instance that noticed the change on its fetched objects */ func controllerDidChangeContent(_ controller: FetchedResultsController) /** This method is called before the controller performs the fetch. :param: controller controller instance that will perform the fetch */ func controllerWillPerformFetch(_ controller: FetchedResultsController) /** This method is called after the controller successfully fetches objects. It will not be called if the fetchRequest is nil. :param: controller controller instance that performed the fetch */ func controllerDidPerformFetch(_ controller: FetchedResultsController) } /** Default implementation of the optional methods in FetchedResultsControllerDelegate Conforming class only has to implement these if it wants to override :nodoc: */ public extension FetchedResultsControllerDelegate { // NOOP func controllerWillPerformFetch(_ controller: FetchedResultsController) {} // NOOP func controllerDidPerformFetch(_ controller: FetchedResultsController) {} } /** The class is used to monitor changes from a RBQRealmNotificationManager to convert these changes into specific index path or section index changes. Typically this is used to back a UITableView and support animations when items are inserted, deleted, or changed. */ open class FetchedResultsController { // MARK: Class Functions /** Deletes the cached section information with the given name If name is not nil, then the cache will be cleaned, but not deleted from disk. If name is nil, then all caches will be deleted by removing the files from disk. :warning: If clearing all caches (name is nil), it is recommended to do this in didFinishLaunchingWithOptions: in AppDelegate because Realm files cannot be deleted from disk safely, if there are strong references to them. :param: name The name of the cache file to delete. If name is nil, deletes all cache files. */ open class func deleteCache(_ cacheName: String) { RBQFetchedResultsController.deleteCache(withName: cacheName) } /** Retrieves all the paths for the Realm files being used as FRC caches on disk. The typical use case for this method is to use the paths to perform migrations in AppDelegate. The FRC cache files need to be migrated along with your other Realm files because by default Realm includes all of the properties defined in your model in all Realm files. Thus the FRC cache files will throw an exception if they are not migrated. Call setSchemaVersion:forRealmAtPath:withMigrationBlock: for each path returned in the array. :returns: NSArray of NSStrings representing the paths on disk for all FRC cache Realm files */ open class func allCacheRealmPaths() -> [String] { var paths = [String]() let allPaths = RBQFetchedResultsController.allCacheRealmPaths() for aPath in allPaths { if let path = aPath as? String { paths.append(path) } } return paths } // MARK: Initializer /** Constructor method to initialize the controller :warning: Specify a cache name if deletion of the cache later on is necessary :param: fetchRequest the FetchRequest for the controller :param: sectionNameKeyPath A key path on result objects that returns the section name. Pass nil to indicate that the controller should generate a single section. If this key path is not the same as that specified by the first sort descriptor in fetchRequest, they must generate the same relative orderings. :param: name the cache name (if nil, cache will not be persisted and built using an in-memory Realm) :returns: A new instance of FetchedResultsController */ public init(fetchRequest: FetchRequest, sectionNameKeyPath: String?, cacheName: String?) { self.fetchRequest = fetchRequest self.rbqFetchedResultsController = RBQFetchedResultsController(fetchRequest: fetchRequest.rbqFetchRequest, sectionNameKeyPath: sectionNameKeyPath, cacheName: cacheName) self.delegateProxy = DelegateProxy(delegate: self) self.rbqFetchedResultsController.delegate = self.delegateProxy! } // MARK: Properties public var logging: Bool { get { return self.rbqFetchedResultsController.logging } set { self.rbqFetchedResultsController.logging = newValue } } /// The fetch request for the controller public let fetchRequest: FetchRequest /// The section name key path used to create the sections. Can be nil if no sections. open var sectionNameKeyPath: String? { return self.rbqFetchedResultsController.sectionNameKeyPath } /// The delegate to pass the index path and section changes to. weak open var delegate: FetchedResultsControllerDelegate? /// The name of the cache used internally to represent the tableview structure. open var cacheName: String? { return self.rbqFetchedResultsController.cacheName } /// All the objects that match the fetch request. open var fetchedObjects: Results { return self.fetchRequest.fetchObjects() } /// Returns all the section titles if using a section name key path open var sectionIndexTitles: [String]? { return self.rbqFetchedResultsController.sectionIndexTitles } // MARK: Functions /** Method to tell the controller to perform the fetch :returns: Indicates if the fetch was successful */ open func performFetch() -> Bool { return self.rbqFetchedResultsController.performFetch() } /** Call this method to force the cache to be rebuilt. A potential use case would be to call this in a @catch after trying to call endUpdates for the table view. If an exception is thrown, then the cache will be rebuilt and you can call reloadData on the table view. */ open func reset() { self.rbqFetchedResultsController.reset() } /** Method to retrieve the number of rows for a given section index :param: index section index :returns: number of rows in the section */ open func numberOfRowsForSectionIndex(_ index: Int) -> Int { return self.rbqFetchedResultsController.numberOfRows(forSectionIndex: index) } /** Method to retrieve the number of sections represented by the fetch request :returns: number of sections */ open func numberOfSections() -> Int { return self.rbqFetchedResultsController.numberOfSections() } /** Method to retrieve the title for a given section index :param: section section index * :returns: The title of the section */ open func titleForHeaderInSection(_ section: Int) -> String { return self.rbqFetchedResultsController.titleForHeader(inSection: section) } /** Method to retrieve the section index given a section name :warning: Returns NSNotFound if there is not a section with the given name :param: sectionName the name of the section :returns: the index of the section (returns NSNotFound if no section with the given name) */ open func sectionIndexForSectionName(_ sectionName: String) -> UInt { return self.rbqFetchedResultsController.sectionIndex(forSectionName: sectionName) } /** Retrieve the SafeObject for a given index path :param: indexPath the index path of the object :returns: SafeObject */ open func safeObjectAtIndexPath(_ indexPath: IndexPath) -> SafeObject? { if let rbqSafeObject = self.rbqFetchedResultsController.safeObject(at: indexPath) { let safeObject = SafeObject(rbqSafeRealmObject: rbqSafeObject) return safeObject } return nil } /** Retrieve the Object for a given index path :warning: Returned object is not thread-safe. :param: indexPath the index path of the object :returns: Object */ open func objectAtIndexPath(_ indexPath: IndexPath) -> T? { if let rlmObject = self.rbqFetchedResultsController.object(at: indexPath) { return unsafeDowncast(rlmObject as! RLMObjectBase, to: T.self) } return nil } /** Retrieve the index path for a safe object in the fetch request :param: safeObject an instance of SafeObject :returns: index path of the object */ open func indexPathForSafeObject(_ safeObject: SafeObject) -> IndexPath? { return self.rbqFetchedResultsController.indexPath(forSafeObject: safeObject.rbqSafeRealmObject) } /** Retrieve the index path for a Object in the fetch request :param: object an instance of Object :returns: index path of the object */ open func indexPathForObject(_ object: T) -> IndexPath? { return self.rbqFetchedResultsController.indexPath(forObject: object as RLMObjectBase) } /** Convenience method to safely update the fetch request for an existing FetchResultsController :param: fetchRequest a new instance of FetchRequest :param: sectionNameKeyPath the section name key path for this fetch request (if nil, no sections will be shown) :param: performFetch indicates whether you want to immediately performFetch using the new fetch request to rebuild the cache */ open func updateFetchRequest(_ fetchRequest: FetchRequest, sectionNameKeyPath: String?, performFetch: Bool) { self.rbqFetchedResultsController.updateFetchRequest(fetchRequest.rbqFetchRequest, sectionNameKeyPath: sectionNameKeyPath, andPerformFetch: performFetch) } // MARK: Private functions/properties internal let rbqFetchedResultsController: RBQFetchedResultsController internal var delegateProxy: DelegateProxy? } // Internal Proxy To Manage Converting The Objc Delegate extension FetchedResultsController: DelegateProxyProtocol { func controllerWillChangeContent(_ controller: RBQFetchedResultsController!) { if let delegate = self.delegate { delegate.controllerWillChangeContent(self) } } func controller(_ controller: RBQFetchedResultsController!, didChangeObject anObject: RBQSafeRealmObject!, atIndexPath indexPath: IndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath!) { if let delegate = self.delegate { let safeObject = SafeObject(rbqSafeRealmObject: anObject) delegate.controller(self, didChangeObject: safeObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath) } } func controller(_ controller: RBQFetchedResultsController!, didChangeSection section: RBQFetchedResultsSectionInfo!, atIndex sectionIndex: UInt, forChangeType type: NSFetchedResultsChangeType) { if let delegate = self.delegate { let sectionInfo = FetchResultsSectionInfo(rbqFetchedResultsSectionInfo: section, fetchRequest: self.fetchRequest, sectionNameKeyPath: self.sectionNameKeyPath) delegate.controllerDidChangeSection(self, section: sectionInfo, sectionIndex: sectionIndex, changeType: type) } } func controllerDidChangeContent(_ controller: RBQFetchedResultsController!) { if let delegate = self.delegate { delegate.controllerDidChangeContent(self) } } func controllerWillPerformFetch(_ controller: RBQFetchedResultsController!) { if let delegate = self.delegate { delegate.controllerWillPerformFetch(self) } } func controllerDidPerformFetch(_ controller: RBQFetchedResultsController!) { if let delegate = self.delegate { delegate.controllerDidPerformFetch(self) } } } // Internal Proxy To Manage Converting The Objc Delegate internal protocol DelegateProxyProtocol: class { func controllerWillChangeContent(_ controller: RBQFetchedResultsController!) func controller(_ controller: RBQFetchedResultsController!, didChangeObject anObject: RBQSafeRealmObject!, atIndexPath indexPath: IndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath!) func controller(_ controller: RBQFetchedResultsController!, didChangeSection section: RBQFetchedResultsSectionInfo!, atIndex sectionIndex: UInt, forChangeType type: NSFetchedResultsChangeType) func controllerDidChangeContent(_ controller: RBQFetchedResultsController!) func controllerWillPerformFetch(_ controller: RBQFetchedResultsController!) func controllerDidPerformFetch(_ controller: RBQFetchedResultsController!) } // Internal Proxy To Manage Converting The Objc Delegate internal class DelegateProxy: NSObject, RBQFetchedResultsControllerDelegate { weak internal var delegate: DelegateProxyProtocol? init(delegate: DelegateProxyProtocol) { self.delegate = delegate super.init() } // @objc func controllerWillChangeContent(_ controller: RBQFetchedResultsController) { self.delegate?.controllerWillChangeContent(controller) } @objc func controller(_ controller: RBQFetchedResultsController, didChange anObject: RBQSafeRealmObject, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { self.delegate?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath) } @objc func controller(_ controller: RBQFetchedResultsController, didChangeSection section: RBQFetchedResultsSectionInfo, at sectionIndex: UInt, for type: NSFetchedResultsChangeType) { self.delegate?.controller(controller, didChangeSection: section, atIndex: sectionIndex, forChangeType: type) } @objc func controllerDidChangeContent(_ controller: RBQFetchedResultsController) { self.delegate?.controllerDidChangeContent(controller) } @objc func controllerWillPerformFetch(_ controller: RBQFetchedResultsController) { self.delegate?.controllerWillPerformFetch(controller) } @objc func controllerDidPerformFetch(_ controller: RBQFetchedResultsController) { self.delegate?.controllerDidPerformFetch(controller) } } ================================================ FILE: RBQFetchedResultsController/Source/Swift/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass ================================================ FILE: RBQFetchedResultsController/Source/Swift/RBQFRCSwift-BridgingHeader.h ================================================ // // RBQFRCSwift-BridgingHeader.h // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // @import RBQFetchedResultsController; ================================================ FILE: RBQFetchedResultsController/Source/Swift/SwiftFetchedResultsController.h ================================================ // // SwiftFetchedResultsController.h // SwiftFetchedResultsController // // Created by Adam Fish on 2/16/16. // Copyright © 2016 Atai Barkai. All rights reserved. // #import //! Project version number for SwiftFetchedResultsController. FOUNDATION_EXPORT double SwiftFetchedResultsControllerVersionNumber; //! Project version string for SwiftFetchedResultsController. FOUNDATION_EXPORT const unsigned char SwiftFetchedResultsControllerVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import @import RBQFetchedResultsController; ================================================ FILE: RBQFetchedResultsController/Source/Swift/Utilities.swift ================================================ // // Utilities.swift // RBQFRCSwiftExample // // Created by Adam Fish on 7/23/15. // Copyright (c) 2015 Adam Fish. All rights reserved. // import Foundation import RealmSwift import Realm import Realm.Dynamic import RealmUtilities /** This utility category provides convenience methods to retrieve the primary key and original class name for an Object. */ extension Object { // MARK: Functions /** Checks if an object is contained in a specific Realm :param: object Object with a primary key :returns: Bool indicating if the object is in a given Realm */ public func isContainedIn(_ realm: Realm) -> Bool { if self.objectSchema.primaryKeyProperty == nil { return false } else if self.realm == nil { return false } let primaryKeyValue: Any? = Object.primaryKeyValue(forObject: self) let object = realm.dynamicObject(ofType: self.objectSchema.className, forPrimaryKey: primaryKeyValue!) if object != nil { return true } return false } } ================================================ FILE: RBQFetchedResultsController.podspec ================================================ Pod::Spec.new do |s| s.name = "RBQFetchedResultsController" s.version = "5.0.2" s.summary = "Drop-in replacement for NSFetchedResultsController backed by Realm." s.description = <<-DESC The RBQFetchedResultsController (FRC) is a replacement for NSFetchedResultsController when used in conjunction with RBQRealmNotificationManager and RBQRealmChangeLogger. The controller and delegate follow the same paradigm as NSFetchedResultsController, and allow the developer to monitor changes of an RLMObject subclass. RBQFetchedResultsController supports tableview sections and implements a drop-in replacement delegate to pass the changes to the tableview for section and row animations. DESC s.homepage = "http://github.com/Roobiq/RBQFetchedResultsController" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Roobiq" => "support@roobiq.com" } s.social_media_url = "http://twitter.com/Roobiq" s.platform = :ios, "7.0" s.source = { :git => "https://github.com/Roobiq/RBQFetchedResultsController.git", :tag => "v#{s.version}", :submodules => true } s.source_files = [ "RBQFetchedResultsController/Source/**/*.{h,m}", "RBQFetchedResultsController/RBQFRC.h" ] s.exclude_files = "RBQFetchedResultsController/Source/Swift/*" s.requires_arc = true s.dependency "Realm", ">=1.0.0" s.dependency "RBQSafeRealmObject" s.dependency "RealmUtilities" end ================================================ FILE: RBQFetchedResultsController.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 6361D73F1C4051A8005CD430 /* RBQFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7341C4051A8005CD430 /* RBQFetchedResultsController.framework */; }; 6361D7991C4052CC005CD430 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7971C4052CC005CD430 /* Realm.framework */; }; A0519B0D1C56DDB300307EB5 /* RBQFRC.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B0B1C56DDB300307EB5 /* RBQFRC.h */; settings = {ATTRIBUTES = (Public, ); }; }; A0519B3F1C56EC9A00307EB5 /* RBQControllerCacheObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B0F1C56EC9A00307EB5 /* RBQControllerCacheObject.h */; }; A0519B401C56EC9A00307EB5 /* RBQControllerCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B101C56EC9A00307EB5 /* RBQControllerCacheObject.m */; }; A0519B411C56EC9A00307EB5 /* RBQObjectCacheObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B111C56EC9A00307EB5 /* RBQObjectCacheObject.h */; }; A0519B421C56EC9A00307EB5 /* RBQObjectCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B121C56EC9A00307EB5 /* RBQObjectCacheObject.m */; }; A0519B431C56EC9A00307EB5 /* RBQSectionCacheObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B131C56EC9A00307EB5 /* RBQSectionCacheObject.h */; }; A0519B441C56EC9A00307EB5 /* RBQSectionCacheObject.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B141C56EC9A00307EB5 /* RBQSectionCacheObject.m */; }; A0519B451C56EC9A00307EB5 /* RBQFetchedResultsController.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B151C56EC9A00307EB5 /* RBQFetchedResultsController.h */; settings = {ATTRIBUTES = (Public, ); }; }; A0519B461C56EC9A00307EB5 /* RBQFetchedResultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B161C56EC9A00307EB5 /* RBQFetchedResultsController.m */; }; A0519B471C56EC9A00307EB5 /* RBQFetchRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A0519B171C56EC9A00307EB5 /* RBQFetchRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; A0519B481C56EC9A00307EB5 /* RBQFetchRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A0519B181C56EC9A00307EB5 /* RBQFetchRequest.m */; }; A090E5C91C73B23F0046788B /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7971C4052CC005CD430 /* Realm.framework */; }; A090E5CA1C73B2420046788B /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7981C4052CC005CD430 /* RealmSwift.framework */; }; A090E5CD1C73B2E30046788B /* RBQFetchedResultsController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7341C4051A8005CD430 /* RBQFetchedResultsController.framework */; }; A0C594D51CCF0E5E0041A382 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6361D7971C4052CC005CD430 /* Realm.framework */; }; A0F2DB731C73C642002BE6BA /* FetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F2DB6D1C73C642002BE6BA /* FetchedResultsController.swift */; }; A0F2DB741C73C642002BE6BA /* FetchRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F2DB6E1C73C642002BE6BA /* FetchRequest.swift */; }; A0F2DB761C73C642002BE6BA /* SwiftFetchedResultsController.h in Headers */ = {isa = PBXBuildFile; fileRef = A0F2DB701C73C642002BE6BA /* SwiftFetchedResultsController.h */; settings = {ATTRIBUTES = (Public, ); }; }; A0F2DB771C73C642002BE6BA /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F2DB711C73C642002BE6BA /* Utilities.swift */; }; F9C9CC3B1DF6BAC900A85A48 /* RBQSafeRealmObject.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC381DF6BAC900A85A48 /* RBQSafeRealmObject.framework */; }; F9C9CC3C1DF6BAC900A85A48 /* RealmUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC391DF6BAC900A85A48 /* RealmUtilities.framework */; }; F9C9CC3E1DF6BACD00A85A48 /* SafeRealmObject.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C9CC3A1DF6BAC900A85A48 /* SafeRealmObject.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 6361D7401C4051A8005CD430 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6361D72B1C4051A8005CD430 /* Project object */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsControllerFramework; }; A090E5CB1C73B2DB0046788B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6361D72B1C4051A8005CD430 /* Project object */; proxyType = 1; remoteGlobalIDString = 6361D7331C4051A8005CD430; remoteInfo = RBQFetchedResultsController; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 6361D7341C4051A8005CD430 /* RBQFetchedResultsController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RBQFetchedResultsController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6361D73E1C4051A8005CD430 /* RBQFetchedResultsController.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RBQFetchedResultsController.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6361D7971C4052CC005CD430 /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = Carthage/Build/iOS/Realm.framework; sourceTree = ""; }; 6361D7981C4052CC005CD430 /* RealmSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmSwift.framework; path = Carthage/Build/iOS/RealmSwift.framework; sourceTree = ""; }; A0519AE51C56DD8200307EB5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A0519B0A1C56DDB300307EB5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RBQFetchedResultsController/Info.plist; sourceTree = SOURCE_ROOT; }; A0519B0B1C56DDB300307EB5 /* RBQFRC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFRC.h; path = RBQFetchedResultsController/RBQFRC.h; sourceTree = SOURCE_ROOT; }; A0519B0F1C56EC9A00307EB5 /* RBQControllerCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQControllerCacheObject.h; sourceTree = ""; }; A0519B101C56EC9A00307EB5 /* RBQControllerCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQControllerCacheObject.m; sourceTree = ""; }; A0519B111C56EC9A00307EB5 /* RBQObjectCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQObjectCacheObject.h; sourceTree = ""; }; A0519B121C56EC9A00307EB5 /* RBQObjectCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQObjectCacheObject.m; sourceTree = ""; }; A0519B131C56EC9A00307EB5 /* RBQSectionCacheObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBQSectionCacheObject.h; sourceTree = ""; }; A0519B141C56EC9A00307EB5 /* RBQSectionCacheObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBQSectionCacheObject.m; sourceTree = ""; }; A0519B151C56EC9A00307EB5 /* RBQFetchedResultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchedResultsController.h; path = RBQFetchedResultsController/Source/RBQFetchedResultsController.h; sourceTree = SOURCE_ROOT; }; A0519B161C56EC9A00307EB5 /* RBQFetchedResultsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchedResultsController.m; path = RBQFetchedResultsController/Source/RBQFetchedResultsController.m; sourceTree = SOURCE_ROOT; }; A0519B171C56EC9A00307EB5 /* RBQFetchRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RBQFetchRequest.h; path = RBQFetchedResultsController/Source/RBQFetchRequest.h; sourceTree = SOURCE_ROOT; }; A0519B181C56EC9A00307EB5 /* RBQFetchRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RBQFetchRequest.m; path = RBQFetchedResultsController/Source/RBQFetchRequest.m; sourceTree = SOURCE_ROOT; }; A090E5A01C73B17B0046788B /* SwiftFetchedResultsController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftFetchedResultsController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A0F2DB6D1C73C642002BE6BA /* FetchedResultsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FetchedResultsController.swift; path = RBQFetchedResultsController/Source/Swift/FetchedResultsController.swift; sourceTree = SOURCE_ROOT; }; A0F2DB6E1C73C642002BE6BA /* FetchRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FetchRequest.swift; path = RBQFetchedResultsController/Source/Swift/FetchRequest.swift; sourceTree = SOURCE_ROOT; }; A0F2DB6F1C73C642002BE6BA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RBQFetchedResultsController/Source/Swift/Info.plist; sourceTree = SOURCE_ROOT; }; A0F2DB701C73C642002BE6BA /* SwiftFetchedResultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SwiftFetchedResultsController.h; path = RBQFetchedResultsController/Source/Swift/SwiftFetchedResultsController.h; sourceTree = SOURCE_ROOT; }; A0F2DB711C73C642002BE6BA /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utilities.swift; path = RBQFetchedResultsController/Source/Swift/Utilities.swift; sourceTree = SOURCE_ROOT; }; F9C9CC381DF6BAC900A85A48 /* RBQSafeRealmObject.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RBQSafeRealmObject.framework; path = Carthage/Build/iOS/RBQSafeRealmObject.framework; sourceTree = ""; }; F9C9CC391DF6BAC900A85A48 /* RealmUtilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmUtilities.framework; path = Carthage/Build/iOS/RealmUtilities.framework; sourceTree = ""; }; F9C9CC3A1DF6BAC900A85A48 /* SafeRealmObject.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafeRealmObject.framework; path = Carthage/Build/iOS/SafeRealmObject.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6361D7301C4051A8005CD430 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F9C9CC3C1DF6BAC900A85A48 /* RealmUtilities.framework in Frameworks */, F9C9CC3B1DF6BAC900A85A48 /* RBQSafeRealmObject.framework in Frameworks */, 6361D7991C4052CC005CD430 /* Realm.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 6361D73B1C4051A8005CD430 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A0C594D51CCF0E5E0041A382 /* Realm.framework in Frameworks */, 6361D73F1C4051A8005CD430 /* RBQFetchedResultsController.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; A090E59C1C73B17B0046788B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F9C9CC3E1DF6BACD00A85A48 /* SafeRealmObject.framework in Frameworks */, A090E5CD1C73B2E30046788B /* RBQFetchedResultsController.framework in Frameworks */, A090E5CA1C73B2420046788B /* RealmSwift.framework in Frameworks */, A090E5C91C73B23F0046788B /* Realm.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 6361D72A1C4051A8005CD430 = { isa = PBXGroup; children = ( 6361D7361C4051A8005CD430 /* RBQFetchedResultsController */, A0519AE41C56DD8200307EB5 /* RBQFetchedResultsControllerTests */, 6361D7351C4051A8005CD430 /* Products */, F8FD46561DD4099C00033F0B /* Frameworks */, ); sourceTree = ""; }; 6361D7351C4051A8005CD430 /* Products */ = { isa = PBXGroup; children = ( 6361D7341C4051A8005CD430 /* RBQFetchedResultsController.framework */, 6361D73E1C4051A8005CD430 /* RBQFetchedResultsController.xctest */, A090E5A01C73B17B0046788B /* SwiftFetchedResultsController.framework */, ); name = Products; sourceTree = ""; }; 6361D7361C4051A8005CD430 /* RBQFetchedResultsController */ = { isa = PBXGroup; children = ( A0519B0B1C56DDB300307EB5 /* RBQFRC.h */, A0519B0A1C56DDB300307EB5 /* Info.plist */, 6361D74E1C4051ED005CD430 /* Source */, ); name = RBQFetchedResultsController; path = RBQFetchedResultsControllerFramework; sourceTree = ""; }; 6361D74E1C4051ED005CD430 /* Source */ = { isa = PBXGroup; children = ( A0F2DB691C73C472002BE6BA /* RBQFetchedResultsController */, A0F2DB5C1C73C467002BE6BA /* SwiftFetchedResultsController */, ); path = Source; sourceTree = ""; }; A0519AE41C56DD8200307EB5 /* RBQFetchedResultsControllerTests */ = { isa = PBXGroup; children = ( A0519AE51C56DD8200307EB5 /* Info.plist */, ); name = RBQFetchedResultsControllerTests; path = RBQFetchedResultsController/RBQFetchedResultsControllerTests; sourceTree = ""; }; A0519B0E1C56EC9A00307EB5 /* CacheObjects */ = { isa = PBXGroup; children = ( A0519B0F1C56EC9A00307EB5 /* RBQControllerCacheObject.h */, A0519B101C56EC9A00307EB5 /* RBQControllerCacheObject.m */, A0519B111C56EC9A00307EB5 /* RBQObjectCacheObject.h */, A0519B121C56EC9A00307EB5 /* RBQObjectCacheObject.m */, A0519B131C56EC9A00307EB5 /* RBQSectionCacheObject.h */, A0519B141C56EC9A00307EB5 /* RBQSectionCacheObject.m */, ); name = CacheObjects; path = RBQFetchedResultsController/Source/CacheObjects; sourceTree = SOURCE_ROOT; }; A0F2DB5C1C73C467002BE6BA /* SwiftFetchedResultsController */ = { isa = PBXGroup; children = ( A0F2DB6D1C73C642002BE6BA /* FetchedResultsController.swift */, A0F2DB6E1C73C642002BE6BA /* FetchRequest.swift */, A0F2DB6F1C73C642002BE6BA /* Info.plist */, A0F2DB701C73C642002BE6BA /* SwiftFetchedResultsController.h */, A0F2DB711C73C642002BE6BA /* Utilities.swift */, ); name = SwiftFetchedResultsController; path = RBQFetchedResultsController/Source/SwiftFetchedResultsController; sourceTree = SOURCE_ROOT; }; A0F2DB691C73C472002BE6BA /* RBQFetchedResultsController */ = { isa = PBXGroup; children = ( A0519B0E1C56EC9A00307EB5 /* CacheObjects */, A0519B151C56EC9A00307EB5 /* RBQFetchedResultsController.h */, A0519B161C56EC9A00307EB5 /* RBQFetchedResultsController.m */, A0519B171C56EC9A00307EB5 /* RBQFetchRequest.h */, A0519B181C56EC9A00307EB5 /* RBQFetchRequest.m */, ); name = RBQFetchedResultsController; sourceTree = ""; }; F8FD46561DD4099C00033F0B /* Frameworks */ = { isa = PBXGroup; children = ( F9C9CC381DF6BAC900A85A48 /* RBQSafeRealmObject.framework */, F9C9CC391DF6BAC900A85A48 /* RealmUtilities.framework */, F9C9CC3A1DF6BAC900A85A48 /* SafeRealmObject.framework */, 6361D7971C4052CC005CD430 /* Realm.framework */, 6361D7981C4052CC005CD430 /* RealmSwift.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 6361D7311C4051A8005CD430 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( A0519B471C56EC9A00307EB5 /* RBQFetchRequest.h in Headers */, A0519B0D1C56DDB300307EB5 /* RBQFRC.h in Headers */, A0519B451C56EC9A00307EB5 /* RBQFetchedResultsController.h in Headers */, A0519B411C56EC9A00307EB5 /* RBQObjectCacheObject.h in Headers */, A0519B3F1C56EC9A00307EB5 /* RBQControllerCacheObject.h in Headers */, A0519B431C56EC9A00307EB5 /* RBQSectionCacheObject.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; A090E59D1C73B17B0046788B /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( A0F2DB761C73C642002BE6BA /* SwiftFetchedResultsController.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 6361D7331C4051A8005CD430 /* RBQFetchedResultsController */ = { isa = PBXNativeTarget; buildConfigurationList = 6361D7481C4051A8005CD430 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsController" */; buildPhases = ( 6361D72F1C4051A8005CD430 /* Sources */, 6361D7301C4051A8005CD430 /* Frameworks */, 6361D7311C4051A8005CD430 /* Headers */, 6361D7321C4051A8005CD430 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = RBQFetchedResultsController; productName = RBQFetchedResultsControllerFramework; productReference = 6361D7341C4051A8005CD430 /* RBQFetchedResultsController.framework */; productType = "com.apple.product-type.framework"; }; 6361D73D1C4051A8005CD430 /* RBQFetchedResultsControllerTests */ = { isa = PBXNativeTarget; buildConfigurationList = 6361D74B1C4051A8005CD430 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerTests" */; buildPhases = ( 6361D73A1C4051A8005CD430 /* Sources */, 6361D73B1C4051A8005CD430 /* Frameworks */, 6361D73C1C4051A8005CD430 /* Resources */, ); buildRules = ( ); dependencies = ( 6361D7411C4051A8005CD430 /* PBXTargetDependency */, ); name = RBQFetchedResultsControllerTests; productName = RBQFetchedResultsControllerFrameworkTests; productReference = 6361D73E1C4051A8005CD430 /* RBQFetchedResultsController.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; A090E59F1C73B17B0046788B /* SwiftFetchedResultsController */ = { isa = PBXNativeTarget; buildConfigurationList = A090E5A71C73B17B0046788B /* Build configuration list for PBXNativeTarget "SwiftFetchedResultsController" */; buildPhases = ( A090E59B1C73B17B0046788B /* Sources */, A090E59C1C73B17B0046788B /* Frameworks */, A090E59D1C73B17B0046788B /* Headers */, A090E59E1C73B17B0046788B /* Resources */, ); buildRules = ( ); dependencies = ( A090E5CC1C73B2DB0046788B /* PBXTargetDependency */, ); name = SwiftFetchedResultsController; productName = SwiftFetchedResultsController; productReference = A090E5A01C73B17B0046788B /* SwiftFetchedResultsController.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6361D72B1C4051A8005CD430 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Atai Barkai"; TargetAttributes = { 6361D7331C4051A8005CD430 = { CreatedOnToolsVersion = 7.2; }; 6361D73D1C4051A8005CD430 = { CreatedOnToolsVersion = 7.2; }; A090E59F1C73B17B0046788B = { CreatedOnToolsVersion = 7.2.1; }; }; }; buildConfigurationList = 6361D72E1C4051A8005CD430 /* Build configuration list for PBXProject "RBQFetchedResultsController" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 6361D72A1C4051A8005CD430; productRefGroup = 6361D7351C4051A8005CD430 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6361D7331C4051A8005CD430 /* RBQFetchedResultsController */, 6361D73D1C4051A8005CD430 /* RBQFetchedResultsControllerTests */, A090E59F1C73B17B0046788B /* SwiftFetchedResultsController */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6361D7321C4051A8005CD430 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 6361D73C1C4051A8005CD430 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; A090E59E1C73B17B0046788B /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6361D72F1C4051A8005CD430 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0519B441C56EC9A00307EB5 /* RBQSectionCacheObject.m in Sources */, A0519B481C56EC9A00307EB5 /* RBQFetchRequest.m in Sources */, A0519B421C56EC9A00307EB5 /* RBQObjectCacheObject.m in Sources */, A0519B461C56EC9A00307EB5 /* RBQFetchedResultsController.m in Sources */, A0519B401C56EC9A00307EB5 /* RBQControllerCacheObject.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6361D73A1C4051A8005CD430 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; A090E59B1C73B17B0046788B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0F2DB741C73C642002BE6BA /* FetchRequest.swift in Sources */, A0F2DB731C73C642002BE6BA /* FetchedResultsController.swift in Sources */, A0F2DB771C73C642002BE6BA /* Utilities.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 6361D7411C4051A8005CD430 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6361D7331C4051A8005CD430 /* RBQFetchedResultsController */; targetProxy = 6361D7401C4051A8005CD430 /* PBXContainerItemProxy */; }; A090E5CC1C73B2DB0046788B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6361D7331C4051A8005CD430 /* RBQFetchedResultsController */; targetProxy = A090E5CB1C73B2DB0046788B /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 6361D7461C4051A8005CD430 /* 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; CURRENT_PROJECT_VERSION = 1; 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 = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 6361D7471C4051A8005CD430 /* 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; CURRENT_PROJECT_VERSION = 1; 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.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0.1; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 6361D7491C4051A8005CD430 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); HEADER_SEARCH_PATHS = "$(SRCROOT)/RBQFetchedResultsController/Source"; INFOPLIST_FILE = RBQFetchedResultsController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "$(SRCROOT)/RBQFetchedResultsController/ModuleMapFile"; PRODUCT_BUNDLE_IDENTIFIER = Atai.RBQFetchedResultsController; PRODUCT_NAME = RBQFetchedResultsController; SKIP_INSTALL = YES; }; name = Debug; }; 6361D74A1C4051A8005CD430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); HEADER_SEARCH_PATHS = "$(SRCROOT)/RBQFetchedResultsController/Source"; INFOPLIST_FILE = RBQFetchedResultsController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "$(SRCROOT)/RBQFetchedResultsController/ModuleMapFile"; PRODUCT_BUNDLE_IDENTIFIER = Atai.RBQFetchedResultsController; PRODUCT_NAME = RBQFetchedResultsController; SKIP_INSTALL = YES; }; name = Release; }; 6361D74C1C4051A8005CD430 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = RBQFetchedResultsController/RBQFetchedResultsControllerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Atai.RBQFetchedResultsControllerFrameworkTests; PRODUCT_NAME = RBQFetchedResultsController; }; name = Debug; }; 6361D74D1C4051A8005CD430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = RBQFetchedResultsController/RBQFetchedResultsControllerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Atai.RBQFetchedResultsControllerFrameworkTests; PRODUCT_NAME = RBQFetchedResultsController; }; name = Release; }; A090E5A51C73B17B0046788B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = RBQFetchedResultsController/Source/Swift/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.Roobiq.SwiftFetchedResultsController; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 3.0; }; name = Debug; }; A090E5A61C73B17B0046788B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); INFOPLIST_FILE = RBQFetchedResultsController/Source/Swift/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.Roobiq.SwiftFetchedResultsController; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6361D72E1C4051A8005CD430 /* Build configuration list for PBXProject "RBQFetchedResultsController" */ = { isa = XCConfigurationList; buildConfigurations = ( 6361D7461C4051A8005CD430 /* Debug */, 6361D7471C4051A8005CD430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6361D7481C4051A8005CD430 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsController" */ = { isa = XCConfigurationList; buildConfigurations = ( 6361D7491C4051A8005CD430 /* Debug */, 6361D74A1C4051A8005CD430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6361D74B1C4051A8005CD430 /* Build configuration list for PBXNativeTarget "RBQFetchedResultsControllerTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 6361D74C1C4051A8005CD430 /* Debug */, 6361D74D1C4051A8005CD430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A090E5A71C73B17B0046788B /* Build configuration list for PBXNativeTarget "SwiftFetchedResultsController" */ = { isa = XCConfigurationList; buildConfigurations = ( A090E5A51C73B17B0046788B /* Debug */, A090E5A61C73B17B0046788B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 6361D72B1C4051A8005CD430 /* Project object */; } ================================================ FILE: RBQFetchedResultsController.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: RBQFetchedResultsController.xcodeproj/xcshareddata/xcschemes/RBQFetchedResultsController.xcscheme ================================================ ================================================ FILE: RBQFetchedResultsController.xcodeproj/xcshareddata/xcschemes/SwiftFetchedResultsController.xcscheme ================================================ ================================================ FILE: README.md ================================================ RBQFetchedResultsController =========================== [![CocoaPods](https://img.shields.io/cocoapods/v/RBQFetchedResultsController.svg)]() [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) #####Drop-in replacement for `NSFetchedResultsController` backed by Realm. ##### _Now Supports Realm Swift With A Complete Swift API!_ The `RBQFetchedResultsController` (FRC) is a replacement for `NSFetchedResultsController` that works with [Realm](http://www.realm.io). The controller and delegate follow the same paradigm as `NSFetchedResultsController`, and allow the developer to monitor changes of a `RLMObject` subclass. `RBQFetchedResultsController` supports tableview sections and implements a drop-in replacement delegate to pass the changes to the tableview for section and row animations. **Realm class requires a primary key to work with `RBQFetchedResultsController`** The Swift API mirrors Objective-C with the following classes: * `FetchedResultsController` * `FetchRequest` * `SafeObject` ####Example Basic todo list application built with [ABFRealmTableViewController](https://github.com/bigfish24/ABFRealmTableViewController) which relies on `RBQFetchedResultsController`: ![Todo List Backed By ABFRealmTableViewController](http://fat.gfycat.com/TinyMagnificentGermanspaniel.gif "Todo List Backed By ABFRealmTableViewController") ####How It Works: **Starting with v4.0 and Realm v0.99, `RBQFetchedResultsController` works automatically with Realm's fine-grained notification support. It is recommended to use Realm's API directly instead of `RBQFetchedResultsController` unless you need support for sections.** Changes produced by Realm will be reprocessed to calculate changes accomodating any sections. These changes will then be passed to a delegate: **Objective-C** ```Objective-C -(void)controllerWillChangeContent:(RBQFetchedResultsController *)controller; -(void)controller:(RBQFetchedResultsController *)controller didChangeObject:(RBQSafeRealmObject *)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath; -(void)controller:(RBQFetchedResultsController *)controller didChangeSection:(RBQFetchedResultsSectionInfo *)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type; -(void)controllerDidChangeContent:(RBQFetchedResultsController *)controller; ``` **Swift** ```Swift func controllerWillChangeContent(controller: FetchedResultsController) func controllerDidChangeObject(controller: FetchedResultsController, anObject: SafeObject, indexPath: NSIndexPath?, changeType: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) func controllerDidChangeSection(controller: FetchedResultsController, section: FetchResultsSectionInfo, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) func controllerDidChangeContent(controller: FetchedResultsController) ``` ####Documentation [Click Here](http://htmlpreview.github.io/?https://raw.githubusercontent.com/Roobiq/RBQFetchedResultsController/master/Documentation/html/index.html) #####Migrations **Starting with v4.0, `RBQFetchedResultsController` now only uses the schemas specific to its internal Realm for section caching. This means handling migrations of the cache Realm is no longer necessary!** ####Installation `RBQFetchedResultsController` is available through [CocoaPods](http://cocoapods.org) or [Carthage](https://github.com/Carthage/Carthage). ####Cocoapods To install it, simply add the following line to your Podfile: **Objective-C** ``` pod "RBQFetchedResultsController" ``` **Swift** ``` use_frameworks! // For Realm 0.96 (use latest) pod 'SwiftFetchedResultsController' // For Realm < 0.96 pod 'SwiftFetchedResultsController', '2.3' ``` Then run `pod install`. ####Carthage To install it, simply add the following line to your Cartfile: **Objective-C** ``` github "Roobiq/RBQFetchedResultsController" ``` **Swift** ``` github "Roobiq/SwiftFetchedResultsController" ``` Then run `carthage update` and drag `RBQFetchedResultsController.framework` or `SwiftFetchedResultsController.framework` from the appropriate platform directory in `Carthage/Build/` to the "Linked Frameworks and Libraries" section of your Xcode project’s "General" settings. ####Demo Build and run/test the Example project in Xcode to see `RBQFetchedResultsController` in action. This project uses CocoaPods. If you don't have [CocoaPods](http://cocoapods.org/) installed, grab it with [sudo] gem install cocoapods. **Objective-C** ``` git clone http://github.com/Roobiq/RBQFetchedResultsController git submodule init git submodule update cd Examples/ObjC pod install open RBQFetchedResultsControllerExample.xcworkspace ``` **Swift** ``` git clone http://github.com/Roobiq/RBQFetchedResultsController git submodule init git submodule update cd Examples/Swift pod install open RBQFRCSwiftExample.xcworkspace ``` **Note:** the example projects install the framework by directly including the source files and using Cocoapods to install Realm. There are also example projects that test/demonstrate installation of the framework with Cocoapods and Carthage. For the Cocoapods install example apps (`ObjC-cocoapods`/`Swift-cocoapods`) the framework is installed as a development pod, referencing the local podspec and source files. Follow the same instructions as above, since the `pod install` will simply include the framework. For the Carthage example apps (`ObjC-carthage`/`Swift-carthage`), you must run `carthage update` after `git submodule update` in the steps above so that Carthage can build the Realm framework(s) locally. The example project then uses the `RBQFetchedResultsController.xcodeproj` directly in the same way as you would the resulting framework produced by Carthage. ####Current State The example project includes various functional and unit tests. In addition, the project is used in our [Roobiq](http://www.roobiq.com) app and is quite stable. ================================================ FILE: SwiftFetchedResultsController.podspec ================================================ Pod::Spec.new do |s| s.name = "SwiftFetchedResultsController" s.version = "5.0.2" s.summary = "Swift drop-in replacement for NSFetchedResultsController backed by Realm" s.description = <<-DESC The FetchedResultsController (FRC) is a Swift replacement for NSFetchedResultsController when used in conjunction with the ChangeLogger class. The controller and delegate follow the same paradigm as NSFetchedResultsController, and allow the developer to monitor changes of a Realm Swift Object subclass. FetchedResultsController supports tableview sections and implements a drop-in replacement delegate to pass the changes to the tableview for section and row animations. DESC s.homepage = "http://github.com/Roobiq/RBQFetchedResultsController" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Roobiq" => "support@roobiq.com" } s.social_media_url = "http://twitter.com/Roobiq" s.platform = :ios, "8.0" s.source = { :git => "https://github.com/Roobiq/RBQFetchedResultsController.git", :tag => "v#{s.version}", :submodules => true } s.source_files = [ "RBQFetchedResultsController/Source/Swift/*.{h,swift}", "RBQFetchedResultsController/Source/RBQSafeRealmObject/*.{swift}" ] s.requires_arc = true s.dependency "RealmSwift", ">=2.1.1" s.dependency "RBQFetchedResultsController", ">=#{s.version}" s.dependency "SafeRealmObject" end