From 4cd295e18fc8b965319399586258855f8ad493dc Mon Sep 17 00:00:00 2001 From: Sami Samhuri Date: Wed, 22 Apr 2015 01:21:33 -0700 Subject: [PATCH] add ObjectiveSugar and remove OHHTTPStubs --- Podfile | 6 +- Podfile.lock | 143 +- .../Build/Mantle/MTLManagedObjectAdapter.h | 1 - Pods/Headers/Build/OHHTTPStubs/OHHTTPStubs.h | 1 - .../OHHTTPStubsResponse+HTTPMessage.h | 1 - .../OHHTTPStubs/OHHTTPStubsResponse+JSON.h | 1 - .../Build/OHHTTPStubs/OHHTTPStubsResponse.h | 1 - .../Build/PromiseKit/PromiseKit+Foundation.h | 1 - .../Build/PromiseKit/PromiseKit+UIKit.h | 1 - Pods/Headers/Build/YapDatabase/YapCache.h | 1 - .../YapDatabaseSecondaryIndexSetupPrivate.h | 1 - .../CocoaLumberjack/DDASLLogCapture.h | 0 .../CocoaLumberjack/DDASLLogger.h | 0 .../DDAbstractDatabaseLogger.h | 0 .../CocoaLumberjack/DDAssert.h | 0 .../DDContextFilterLogFormatter.h | 0 .../DDDispatchQueueLogFormatter.h | 0 .../CocoaLumberjack/DDFileLogger.h | 0 .../CocoaLumberjack/DDLog+LOGV.h | 0 .../CocoaLumberjack/DDLog.h | 0 .../CocoaLumberjack/DDMultiFormatter.h | 0 .../CocoaLumberjack/DDTTYLogger.h | 0 .../Mantle/EXTKeyPathCoding.h | 0 .../Mantle/EXTRuntimeExtensions.h | 0 .../{Build => Private}/Mantle/EXTScope.h | 0 .../Mantle/MTLJSONAdapter.h | 0 .../Mantle/MTLModel+NSCoding.h | 0 .../{Build => Private}/Mantle/MTLModel.h | 0 .../{Build => Private}/Mantle/MTLReflection.h | 0 .../Mantle/MTLTransformerErrorHandling.h | 1 + .../Mantle/MTLValueTransformer.h | 0 .../{Build => Private}/Mantle/Mantle.h | 0 .../Mantle/NSArray+MTLManipulationAdditions.h | 0 .../Mantle/NSDictionary+MTLJSONKeyPath.h | 1 + .../NSDictionary+MTLManipulationAdditions.h | 0 .../Mantle/NSDictionary+MTLMappingAdditions.h | 1 + .../Mantle/NSError+MTLModelException.h | 0 .../Mantle/NSObject+MTLComparisonAdditions.h | 0 ...NSValueTransformer+MTLInversionAdditions.h | 0 ...former+MTLPredefinedTransformerAdditions.h | 0 .../{Build => Private}/Mantle/metamacros.h | 0 .../OMGHTTPURLRQ/OMGFormURLEncode.h | 0 .../OMGHTTPURLRQ/OMGHTTPURLRQ.h | 0 .../OMGHTTPURLRQ/OMGUserAgent.h | 0 .../ObjectiveSugar/NSArray+ObjectiveSugar.h | 1 + .../NSDictionary+ObjectiveSugar.h | 1 + .../NSMutableArray+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSNumber+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSSet+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSString+ObjectiveSugar.h | 1 + .../Private/ObjectiveSugar/ObjectiveSugar.h | 1 + .../Private/PromiseKit/CALayer+PromiseKit.h | 1 + .../NSNotificationCenter+PromiseKit.h | 0 .../PromiseKit/NSURLConnection+PromiseKit.h | 0 .../PromiseKit/Promise+Pause.h | 0 .../PromiseKit/Promise+Until.h | 0 .../PromiseKit/Promise+When.h | 0 .../{Build => Private}/PromiseKit/Promise.h | 0 .../PromiseKit/PromiseKit.h | 0 .../PromiseKit/UIActionSheet+PromiseKit.h | 0 .../PromiseKit/UIAlertView+PromiseKit.h | 0 .../PromiseKit/UIView+PromiseKit.h | 0 .../PromiseKit/UIViewController+PromiseKit.h | 0 .../{Build => Private}/PromiseKit/fwd.h | 0 .../YapDatabase/NSDictionary+YapDatabase.h | 0 .../Private/YapDatabase/YDBCKAttachRequest.h | 1 + .../Private/YapDatabase/YDBCKChangeQueue.h | 1 + .../Private/YapDatabase/YDBCKChangeRecord.h | 1 + .../Private/YapDatabase/YDBCKChangeSet.h | 1 + .../YapDatabase/YDBCKMappingTableInfo.h | 1 + .../Private/YapDatabase/YDBCKMergeInfo.h | 1 + .../Headers/Private/YapDatabase/YDBCKRecord.h | 1 + .../Private/YapDatabase/YDBCKRecordInfo.h | 1 + .../YapDatabase/YDBCKRecordTableInfo.h | 1 + Pods/Headers/Private/YapDatabase/YapCache.h | 1 + .../YapDatabase/YapCollectionKey.h | 0 .../YapDatabase/YapDatabase.h | 0 .../Private/YapDatabase/YapDatabaseCloudKit.h | 1 + .../YapDatabaseCloudKitConnection.h | 1 + .../YapDatabase/YapDatabaseCloudKitOptions.h | 1 + .../YapDatabase/YapDatabaseCloudKitPrivate.h | 1 + .../YapDatabaseCloudKitTransaction.h | 1 + .../YapDatabase/YapDatabaseCloudKitTypes.h | 1 + .../YapDatabase/YapDatabaseConnection.h | 0 .../YapDatabaseConnectionDefaults.h | 0 .../YapDatabase/YapDatabaseConnectionState.h | 0 .../YapDatabase/YapDatabaseExtension.h | 0 .../YapDatabaseExtensionConnection.h | 0 .../YapDatabase/YapDatabaseExtensionPrivate.h | 0 .../YapDatabaseExtensionTransaction.h | 0 .../YapDatabase/YapDatabaseFilteredView.h | 0 .../YapDatabaseFilteredViewConnection.h | 0 .../YapDatabaseFilteredViewPrivate.h | 0 .../YapDatabaseFilteredViewTransaction.h | 0 .../YapDatabaseFilteredViewTypes.h | 0 .../YapDatabase/YapDatabaseFullTextSearch.h | 0 .../YapDatabaseFullTextSearchConnection.h | 0 .../YapDatabaseFullTextSearchHandler.h | 1 + .../YapDatabaseFullTextSearchPrivate.h | 0 .../YapDatabaseFullTextSearchSnippetOptions.h | 0 .../YapDatabaseFullTextSearchTransaction.h | 0 .../YapDatabase/YapDatabaseLogging.h | 0 .../YapDatabase/YapDatabaseManager.h | 0 .../YapDatabase/YapDatabaseOptions.h | 0 .../YapDatabase/YapDatabasePrivate.h | 0 .../YapDatabase/YapDatabaseQuery.h | 0 .../YapDatabase/YapDatabaseRelationship.h | 0 .../YapDatabaseRelationshipConnection.h | 0 .../YapDatabase/YapDatabaseRelationshipEdge.h | 0 .../YapDatabaseRelationshipEdgePrivate.h | 0 .../YapDatabase/YapDatabaseRelationshipNode.h | 0 .../YapDatabaseRelationshipOptions.h | 0 .../YapDatabaseRelationshipPrivate.h | 0 .../YapDatabaseRelationshipTransaction.h | 0 .../YapDatabase/YapDatabaseSearchQueue.h | 0 .../YapDatabaseSearchQueuePrivate.h | 0 .../YapDatabaseSearchResultsView.h | 0 .../YapDatabaseSearchResultsViewConnection.h | 0 .../YapDatabaseSearchResultsViewOptions.h | 0 .../YapDatabaseSearchResultsViewPrivate.h | 0 .../YapDatabaseSearchResultsViewTransaction.h | 0 .../YapDatabase/YapDatabaseSecondaryIndex.h | 0 .../YapDatabaseSecondaryIndexConnection.h | 0 .../YapDatabaseSecondaryIndexHandler.h | 1 + .../YapDatabaseSecondaryIndexOptions.h | 0 .../YapDatabaseSecondaryIndexPrivate.h | 0 .../YapDatabaseSecondaryIndexSetup.h | 0 .../YapDatabaseSecondaryIndexTransaction.h | 0 .../YapDatabase/YapDatabaseStatement.h | 0 .../YapDatabase/YapDatabaseString.h | 0 .../YapDatabase/YapDatabaseTransaction.h | 0 .../YapDatabase/YapDatabaseView.h | 0 .../YapDatabase/YapDatabaseViewChange.h | 0 .../YapDatabaseViewChangePrivate.h | 0 .../YapDatabase/YapDatabaseViewConnection.h | 0 .../YapDatabase/YapDatabaseViewMappings.h | 0 .../YapDatabaseViewMappingsPrivate.h | 0 .../YapDatabase/YapDatabaseViewOptions.h | 0 .../YapDatabase/YapDatabaseViewPage.h | 0 .../YapDatabase/YapDatabaseViewPageMetadata.h | 0 .../YapDatabase/YapDatabaseViewPrivate.h | 0 .../YapDatabase/YapDatabaseViewRangeOptions.h | 0 .../YapDatabaseViewRangeOptionsPrivate.h | 0 .../YapDatabase/YapDatabaseViewState.h | 0 .../YapDatabase/YapDatabaseViewTransaction.h | 0 .../YapDatabase/YapDatabaseViewTypes.h | 0 .../Private/YapDatabase/YapDebugDictionary.h | 1 + .../YapDatabase/YapMemoryTable.h | 0 .../Private/YapDatabase/YapMurmurHash.h | 1 + .../{Build => Private}/YapDatabase/YapNull.h | 0 .../YapDatabase/YapRowidSet.h | 0 .../{Build => Private}/YapDatabase/YapSet.h | 0 .../{Build => Private}/YapDatabase/YapTouch.h | 0 .../YapDatabase/YapWhitelistBlacklist.h | 1 + .../{Build => Private}/libextobjc/EXTADT.h | 0 .../libextobjc/EXTConcreteProtocol.h | 0 .../libextobjc/EXTKeyPathCoding.h | 0 .../{Build => Private}/libextobjc/EXTNil.h | 0 .../libextobjc/EXTRuntimeExtensions.h | 0 .../libextobjc/EXTSafeCategory.h | 0 .../{Build => Private}/libextobjc/EXTScope.h | 0 .../libextobjc/EXTSelectorChecking.h | 0 .../libextobjc/EXTSynthesize.h | 0 .../libextobjc/NSInvocation+EXT.h | 0 .../libextobjc/NSMethodSignature+EXT.h | 0 .../{Build => Private}/libextobjc/extobjc.h | 0 .../libextobjc/metamacros.h | 0 .../Public/Mantle/MTLManagedObjectAdapter.h | 1 - .../Mantle/MTLTransformerErrorHandling.h | 1 + .../Mantle/NSDictionary+MTLJSONKeyPath.h | 1 + .../Mantle/NSDictionary+MTLMappingAdditions.h | 1 + Pods/Headers/Public/OHHTTPStubs/OHHTTPStubs.h | 1 - .../OHHTTPStubsResponse+HTTPMessage.h | 1 - .../OHHTTPStubs/OHHTTPStubsResponse+JSON.h | 1 - .../Public/OHHTTPStubs/OHHTTPStubsResponse.h | 1 - .../ObjectiveSugar/NSArray+ObjectiveSugar.h | 1 + .../NSDictionary+ObjectiveSugar.h | 1 + .../NSMutableArray+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSNumber+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSSet+ObjectiveSugar.h | 1 + .../ObjectiveSugar/NSString+ObjectiveSugar.h | 1 + .../Public/ObjectiveSugar/ObjectiveSugar.h | 1 + .../Public/PromiseKit/CALayer+PromiseKit.h | 1 + .../Public/PromiseKit/PromiseKit+Foundation.h | 1 - .../Public/PromiseKit/PromiseKit+UIKit.h | 1 - .../Public/YapDatabase/YDBCKChangeSet.h | 1 + .../Public/YapDatabase/YDBCKMergeInfo.h | 1 + Pods/Headers/Public/YapDatabase/YDBCKRecord.h | 1 + .../Public/YapDatabase/YDBCKRecordInfo.h | 1 + Pods/Headers/Public/YapDatabase/YapCache.h | 1 + .../Public/YapDatabase/YapDatabaseCloudKit.h | 1 + .../YapDatabaseCloudKitConnection.h | 1 + .../YapDatabase/YapDatabaseCloudKitOptions.h | 1 + .../YapDatabaseCloudKitTransaction.h | 1 + .../YapDatabase/YapDatabaseCloudKitTypes.h | 1 + .../YapDatabaseFullTextSearchHandler.h | 1 + .../YapDatabaseSecondaryIndexHandler.h | 1 + .../Public/YapDatabase/YapMurmurHash.h | 1 + .../YapDatabase/YapWhitelistBlacklist.h | 1 + Pods/Manifest.lock | 143 +- Pods/Mantle/LICENSE.md | 2 +- Pods/Mantle/Mantle/MTLJSONAdapter.h | 351 +- Pods/Mantle/Mantle/MTLJSONAdapter.m | 605 +- Pods/Mantle/Mantle/MTLManagedObjectAdapter.h | 215 - Pods/Mantle/Mantle/MTLManagedObjectAdapter.m | 645 - Pods/Mantle/Mantle/MTLModel+NSCoding.h | 182 +- Pods/Mantle/Mantle/MTLModel+NSCoding.m | 1 - Pods/Mantle/Mantle/MTLModel.h | 246 +- Pods/Mantle/Mantle/MTLModel.m | 120 +- Pods/Mantle/Mantle/MTLReflection.h | 36 +- .../Mantle/MTLTransformerErrorHandling.h | 66 + .../Mantle/MTLTransformerErrorHandling.m | 15 + Pods/Mantle/Mantle/MTLValueTransformer.h | 49 +- Pods/Mantle/Mantle/MTLValueTransformer.m | 78 +- Pods/Mantle/Mantle/Mantle.h | 11 +- .../Mantle/NSArray+MTLManipulationAdditions.h | 14 +- .../Mantle/NSDictionary+MTLJSONKeyPath.h | 27 + .../Mantle/NSDictionary+MTLJSONKeyPath.m | 47 + .../NSDictionary+MTLManipulationAdditions.h | 24 +- .../NSDictionary+MTLManipulationAdditions.m | 17 +- .../Mantle/NSDictionary+MTLMappingAdditions.h | 21 + .../Mantle/NSDictionary+MTLMappingAdditions.m | 23 + .../Mantle/Mantle/NSError+MTLModelException.h | 16 +- .../Mantle/NSObject+MTLComparisonAdditions.h | 2 +- ...NSValueTransformer+MTLInversionAdditions.h | 12 +- ...NSValueTransformer+MTLInversionAdditions.m | 23 +- ...former+MTLPredefinedTransformerAdditions.h | 121 +- ...former+MTLPredefinedTransformerAdditions.m | 316 +- .../Mantle/extobjc/EXTRuntimeExtensions.m | 2 + Pods/Mantle/README.md | 23 +- Pods/OHHTTPStubs/LICENSE | 9 - .../OHHTTPStubs+NSURLSessionConfiguration.m | 70 - .../OHHTTPStubs/Sources/OHHTTPStubs.h | 120 - .../OHHTTPStubs/Sources/OHHTTPStubs.m | 535 - .../Sources/OHHTTPStubsResponse+HTTPMessage.h | 35 - .../Sources/OHHTTPStubsResponse+HTTPMessage.m | 54 - .../Sources/OHHTTPStubsResponse+JSON.h | 27 - .../Sources/OHHTTPStubsResponse+JSON.m | 31 - .../OHHTTPStubs/Sources/OHHTTPStubsResponse.h | 219 - .../OHHTTPStubs/Sources/OHHTTPStubsResponse.m | 187 - Pods/OHHTTPStubs/README.md | 123 - .../Classes/NSArray+ObjectiveSugar.h | 221 + .../Classes/NSArray+ObjectiveSugar.m | 203 + .../Classes/NSDictionary+ObjectiveSugar.h | 19 + .../Classes/NSDictionary+ObjectiveSugar.m | 48 + .../Classes/NSMutableArray+ObjectiveSugar.h | 44 + .../Classes/NSMutableArray+ObjectiveSugar.m | 64 + .../Classes/NSNumber+ObjectiveSugar.h | 45 + .../Classes/NSNumber+ObjectiveSugar.m | 117 + .../Classes/NSSet+ObjectiveSugar.h | 26 + .../Classes/NSSet+ObjectiveSugar.m | 84 + .../Classes/NSString+ObjectiveSugar.h | 56 + .../Classes/NSString+ObjectiveSugar.m | 61 + Pods/ObjectiveSugar/Classes/ObjectiveSugar.h | 11 + Pods/ObjectiveSugar/LICENSE | 7 + Pods/ObjectiveSugar/README.md | 314 + Pods/Pods.xcodeproj/project.pbxproj | 16499 +++------------- Pods/PromiseKit/README.markdown | 102 +- Pods/PromiseKit/objc/CALayer+PromiseKit.h | 38 + Pods/PromiseKit/objc/CALayer+PromiseKit.m | 41 + .../objc/NSNotificationCenter+PromiseKit.h | 23 +- .../objc/NSNotificationCenter+PromiseKit.m | 2 + .../objc/NSURLConnection+PromiseKit.h | 133 +- .../objc/NSURLConnection+PromiseKit.m | 8 +- Pods/PromiseKit/objc/PMKPromise+When.m | 2 +- Pods/PromiseKit/objc/PMKPromise.m | 291 +- .../objc/Private/NSMethodSignatureForBlock.m | 4 + Pods/PromiseKit/objc/Private/xctest.rb | 121 - Pods/PromiseKit/objc/PromiseKit.h | 3 + .../PromiseKit/objc/PromiseKit/Promise+Hang.h | 18 + .../PromiseKit/objc/PromiseKit/Promise+Join.h | 28 + .../objc/PromiseKit/Promise+Pause.h | 27 +- .../PromiseKit/objc/PromiseKit/Promise+When.h | 17 +- .../objc/PromiseKit/Promise+Zalgo.h | 35 + Pods/PromiseKit/objc/PromiseKit/Promise.h | 231 +- Pods/PromiseKit/objc/PromiseKit/fwd.h | 10 + .../objc/UIActionSheet+PromiseKit.h | 28 +- Pods/PromiseKit/objc/UIAlertView+PromiseKit.h | 26 +- Pods/PromiseKit/objc/UIView+PromiseKit.h | 13 + .../objc/UIViewController+PromiseKit.h | 39 +- .../objc/UIViewController+PromiseKit.m | 3 +- .../objc/deprecated/PromiseKit+Foundation.h | 4 - .../objc/deprecated/PromiseKit+UIKit.h | 5 - ...BlogTests-CocoaLumberjack-Private.xcconfig | 5 - .../Pods-BlogTests-CocoaLumberjack-dummy.m | 5 - .../Pods-BlogTests-Mantle-Private.xcconfig | 5 - .../Pods-BlogTests-Mantle-dummy.m | 5 - .../Pods-BlogTests-Mantle-prefix.pch | 5 - .../Pods-BlogTests-Mantle.xcconfig | 1 - ...ods-BlogTests-OHHTTPStubs-Private.xcconfig | 5 - .../Pods-BlogTests-OHHTTPStubs-dummy.m | 5 - .../Pods-BlogTests-OHHTTPStubs-prefix.pch | 5 - .../Pods-BlogTests-OHHTTPStubs.xcconfig | 2 - ...ds-BlogTests-OMGHTTPURLRQ-Private.xcconfig | 5 - .../Pods-BlogTests-OMGHTTPURLRQ-dummy.m | 5 - .../Pods-BlogTests-OMGHTTPURLRQ-prefix.pch | 5 - .../Pods-BlogTests-OMGHTTPURLRQ.xcconfig | 0 ...Pods-BlogTests-PromiseKit-Private.xcconfig | 5 - .../Pods-BlogTests-PromiseKit-dummy.m | 5 - .../Pods-BlogTests-PromiseKit-prefix.pch | 5 - .../Pods-BlogTests-PromiseKit.xcconfig | 2 - ...ods-BlogTests-YapDatabase-Private.xcconfig | 5 - .../Pods-BlogTests-YapDatabase-dummy.m | 5 - .../Pods-BlogTests-YapDatabase-prefix.pch | 5 - .../Pods-BlogTests-YapDatabase.xcconfig | 1 - ...Pods-BlogTests-libextobjc-Private.xcconfig | 5 - .../Pods-BlogTests-libextobjc-dummy.m | 5 - .../Pods-BlogTests-libextobjc-prefix.pch | 5 - .../Pods-BlogTests-libextobjc.xcconfig | 0 .../Pods-BlogTests-acknowledgements.markdown | 120 - .../Pods-BlogTests-acknowledgements.plist | 174 - .../Pods-BlogTests/Pods-BlogTests-dummy.m | 5 - .../Pods-BlogTests-environment.h | 236 - .../Pods-BlogTests-resources.sh | 70 - .../Pods-BlogTests.debug.xcconfig | 6 - .../Pods-BlogTests.release.xcconfig | 6 - .../Pods-CocoaLumberjack-Private.xcconfig | 5 +- .../Pods-Mantle/Pods-Mantle-Private.xcconfig | 5 +- .../Pods-OMGHTTPURLRQ-Private.xcconfig | 5 +- .../Pods-ObjectiveSugar-Private.xcconfig | 6 + .../Pods-ObjectiveSugar-dummy.m | 5 + .../Pods-ObjectiveSugar-prefix.pch} | 2 +- .../Pods-ObjectiveSugar.xcconfig} | 0 .../Pods-PromiseKit-Private.xcconfig | 5 +- .../Pods-PromiseKit/Pods-PromiseKit.xcconfig | 4 +- .../Pods-YapDatabase-Private.xcconfig | 5 +- .../Pods-libextobjc-Private.xcconfig | 5 +- .../Pods/Pods-acknowledgements.markdown | 32 +- .../Pods/Pods-acknowledgements.plist | 36 +- .../Pods/Pods-environment.h | 106 +- .../Pods/Pods-resources.sh | 27 +- .../Pods/Pods.debug.xcconfig | 8 +- .../Pods/Pods.release.xcconfig | 8 +- Pods/YapDatabase/README.md | 2 + .../CloudKit/Internal/YDBCKAttachRequest.h | 12 + .../CloudKit/Internal/YDBCKAttachRequest.m | 11 + .../CloudKit/Internal/YDBCKChangeQueue.h | 261 + .../CloudKit/Internal/YDBCKChangeQueue.m | 1205 ++ .../CloudKit/Internal/YDBCKChangeRecord.h | 18 + .../CloudKit/Internal/YDBCKChangeRecord.m | 120 + .../CloudKit/Internal/YDBCKMappingTableInfo.h | 47 + .../CloudKit/Internal/YDBCKMappingTableInfo.m | 60 + .../CloudKit/Internal/YDBCKRecordTableInfo.h | 84 + .../CloudKit/Internal/YDBCKRecordTableInfo.m | 163 + .../Internal/YapDatabaseCloudKitPrivate.h | 251 + .../CloudKit/Utilities/YDBCKChangeSet.h | 29 + .../CloudKit/Utilities/YDBCKChangeSet.m | 241 + .../CloudKit/Utilities/YDBCKMergeInfo.h | 68 + .../CloudKit/Utilities/YDBCKMergeInfo.m | 65 + .../CloudKit/Utilities/YDBCKRecord.h | 49 + .../CloudKit/Utilities/YDBCKRecord.m | 153 + .../CloudKit/Utilities/YDBCKRecordInfo.h | 88 + .../CloudKit/Utilities/YDBCKRecordInfo.m | 13 + .../Extensions/CloudKit/YapDatabaseCloudKit.h | 199 + .../Extensions/CloudKit/YapDatabaseCloudKit.m | 786 + .../CloudKit/YapDatabaseCloudKitConnection.h | 14 + .../CloudKit/YapDatabaseCloudKitConnection.m | 821 + .../CloudKit/YapDatabaseCloudKitOptions.h | 32 + .../CloudKit/YapDatabaseCloudKitOptions.m | 15 + .../CloudKit/YapDatabaseCloudKitTransaction.h | 339 + .../CloudKit/YapDatabaseCloudKitTransaction.m | 4532 +++++ .../CloudKit/YapDatabaseCloudKitTypes.h | 100 + .../CloudKit/YapDatabaseCloudKitTypes.m | 54 + .../Internal/YapDatabaseFilteredViewPrivate.h | 13 + .../FilteredViews/YapDatabaseFilteredView.h | 57 +- .../FilteredViews/YapDatabaseFilteredView.m | 96 +- .../YapDatabaseFilteredViewTransaction.h | 6 +- .../YapDatabaseFilteredViewTransaction.m | 52 +- .../YapDatabaseFilteredViewTypes.h | 13 +- .../YapDatabaseFilteredViewTypes.m | 67 + .../YapDatabaseFullTextSearchPrivate.h | 14 + .../YapDatabaseFullTextSearch.h | 82 +- .../YapDatabaseFullTextSearch.m | 71 +- .../YapDatabaseFullTextSearchConnection.h | 4 +- .../YapDatabaseFullTextSearchConnection.m | 17 +- .../YapDatabaseFullTextSearchHandler.h | 49 + .../YapDatabaseFullTextSearchHandler.m | 68 + .../YapDatabaseFullTextSearchTransaction.h | 4 +- .../YapDatabaseFullTextSearchTransaction.m | 4 +- .../Internal/YapDatabaseExtensionPrivate.h | 32 +- .../Protocol/YapDatabaseExtension.m | 13 +- .../Protocol/YapDatabaseExtensionConnection.h | 2 +- .../YapDatabaseExtensionTransaction.h | 2 +- .../YapDatabaseExtensionTransaction.m | 127 +- .../Internal/YapDatabaseRelationshipPrivate.h | 2 +- .../Relationships/YapDatabaseRelationship.h | 6 +- .../YapDatabaseRelationshipConnection.h | 6 +- .../YapDatabaseRelationshipConnection.m | 283 +- .../YapDatabaseRelationshipEdge.h | 6 +- .../YapDatabaseRelationshipNode.h | 6 +- .../YapDatabaseRelationshipOptions.h | 9 +- .../YapDatabaseRelationshipTransaction.h | 8 +- .../YapDatabaseRelationshipTransaction.m | 42 +- .../YapDatabaseSearchResultsView.h | 26 +- .../YapDatabaseSearchResultsView.m | 65 +- .../YapDatabaseSearchResultsViewConnection.m | 64 +- .../YapDatabaseSearchResultsViewOptions.h | 3 +- .../YapDatabaseSearchResultsViewTransaction.m | 112 +- .../YapDatabaseSecondaryIndexPrivate.h | 38 +- .../YapDatabaseSecondaryIndexSetupPrivate.h | 18 - .../YapDatabaseSecondaryIndex.h | 140 +- .../YapDatabaseSecondaryIndex.m | 79 +- .../YapDatabaseSecondaryIndexConnection.m | 66 +- .../YapDatabaseSecondaryIndexHandler.h | 51 + .../YapDatabaseSecondaryIndexHandler.m | 68 + .../YapDatabaseSecondaryIndexOptions.h | 9 +- .../YapDatabaseSecondaryIndexOptions.m | 6 +- .../YapDatabaseSecondaryIndexTransaction.m | 90 +- .../Views/Internal/YapDatabaseViewPrivate.h | 18 + .../Views/Internal/YapDatabaseViewState.m | 9 +- .../Views/Utilities/YapDatabaseViewChange.h | 8 +- .../Views/Utilities/YapDatabaseViewChange.m | 151 +- .../Views/Utilities/YapDatabaseViewMappings.h | 16 +- .../Views/Utilities/YapDatabaseViewMappings.m | 10 +- .../Extensions/Views/YapDatabaseView.h | 60 +- .../Extensions/Views/YapDatabaseView.m | 135 +- .../Views/YapDatabaseViewConnection.h | 6 +- .../Views/YapDatabaseViewConnection.m | 173 +- .../Extensions/Views/YapDatabaseViewOptions.h | 16 +- .../Extensions/Views/YapDatabaseViewOptions.m | 4 +- .../Views/YapDatabaseViewTransaction.h | 40 +- .../Views/YapDatabaseViewTransaction.m | 579 +- .../Extensions/Views/YapDatabaseViewTypes.h | 52 +- .../Extensions/Views/YapDatabaseViewTypes.m | 221 + .../YapDatabase/Internal/YapCache.h | 94 - .../YapDatabase/Internal/YapDatabasePrivate.h | 88 +- .../YapDatabase/Internal/YapDebugDictionary.h | 34 + .../YapDatabase/Internal/YapDebugDictionary.m | 108 + .../YapDatabase/Internal/YapRowidSet.h | 6 +- .../YapDatabase/Utilities/YapCache.h | 144 + .../{Internal => Utilities}/YapCache.m | 104 +- .../YapDatabase/Utilities/YapCollectionKey.m | 127 +- .../YapDatabase/Utilities/YapDatabaseQuery.h | 13 + .../YapDatabase/Utilities/YapDatabaseQuery.m | 66 +- .../YapDatabase/Utilities/YapMurmurHash.h | 20 + .../YapDatabase/Utilities/YapMurmurHash.m | 403 + .../YapDatabase/Utilities/YapSet.h | 2 +- .../Utilities/YapWhitelistBlacklist.h | 55 + .../Utilities/YapWhitelistBlacklist.m | 61 + Pods/YapDatabase/YapDatabase/YapDatabase.h | 306 +- Pods/YapDatabase/YapDatabase/YapDatabase.m | 453 +- .../YapDatabase/YapDatabaseConnection.h | 238 +- .../YapDatabase/YapDatabaseConnection.m | 469 +- .../YapDatabase/YapDatabaseOptions.h | 19 +- .../YapDatabase/YapDatabaseOptions.m | 9 +- .../YapDatabase/YapDatabaseTransaction.h | 367 +- .../YapDatabase/YapDatabaseTransaction.m | 1142 +- Pods/libextobjc/LICENSE.md | 2 +- Pods/libextobjc/extobjc/EXTKeyPathCoding.h | 5 +- .../libextobjc/extobjc/EXTRuntimeExtensions.m | 2 +- Pods/libextobjc/extobjc/EXTScope.h | 25 +- 451 files changed, 21987 insertions(+), 20844 deletions(-) delete mode 120000 Pods/Headers/Build/Mantle/MTLManagedObjectAdapter.h delete mode 120000 Pods/Headers/Build/OHHTTPStubs/OHHTTPStubs.h delete mode 120000 Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h delete mode 120000 Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+JSON.h delete mode 120000 Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse.h delete mode 120000 Pods/Headers/Build/PromiseKit/PromiseKit+Foundation.h delete mode 120000 Pods/Headers/Build/PromiseKit/PromiseKit+UIKit.h delete mode 120000 Pods/Headers/Build/YapDatabase/YapCache.h delete mode 120000 Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDASLLogCapture.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDASLLogger.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDAbstractDatabaseLogger.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDAssert.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDContextFilterLogFormatter.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDDispatchQueueLogFormatter.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDFileLogger.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDLog+LOGV.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDLog.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDMultiFormatter.h (100%) rename Pods/Headers/{Build => Private}/CocoaLumberjack/DDTTYLogger.h (100%) rename Pods/Headers/{Build => Private}/Mantle/EXTKeyPathCoding.h (100%) rename Pods/Headers/{Build => Private}/Mantle/EXTRuntimeExtensions.h (100%) rename Pods/Headers/{Build => Private}/Mantle/EXTScope.h (100%) rename Pods/Headers/{Build => Private}/Mantle/MTLJSONAdapter.h (100%) rename Pods/Headers/{Build => Private}/Mantle/MTLModel+NSCoding.h (100%) rename Pods/Headers/{Build => Private}/Mantle/MTLModel.h (100%) rename Pods/Headers/{Build => Private}/Mantle/MTLReflection.h (100%) create mode 120000 Pods/Headers/Private/Mantle/MTLTransformerErrorHandling.h rename Pods/Headers/{Build => Private}/Mantle/MTLValueTransformer.h (100%) rename Pods/Headers/{Build => Private}/Mantle/Mantle.h (100%) rename Pods/Headers/{Build => Private}/Mantle/NSArray+MTLManipulationAdditions.h (100%) create mode 120000 Pods/Headers/Private/Mantle/NSDictionary+MTLJSONKeyPath.h rename Pods/Headers/{Build => Private}/Mantle/NSDictionary+MTLManipulationAdditions.h (100%) create mode 120000 Pods/Headers/Private/Mantle/NSDictionary+MTLMappingAdditions.h rename Pods/Headers/{Build => Private}/Mantle/NSError+MTLModelException.h (100%) rename Pods/Headers/{Build => Private}/Mantle/NSObject+MTLComparisonAdditions.h (100%) rename Pods/Headers/{Build => Private}/Mantle/NSValueTransformer+MTLInversionAdditions.h (100%) rename Pods/Headers/{Build => Private}/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h (100%) rename Pods/Headers/{Build => Private}/Mantle/metamacros.h (100%) rename Pods/Headers/{Build => Private}/OMGHTTPURLRQ/OMGFormURLEncode.h (100%) rename Pods/Headers/{Build => Private}/OMGHTTPURLRQ/OMGHTTPURLRQ.h (100%) rename Pods/Headers/{Build => Private}/OMGHTTPURLRQ/OMGUserAgent.h (100%) create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSArray+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSDictionary+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSNumber+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSSet+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/NSString+ObjectiveSugar.h create mode 120000 Pods/Headers/Private/ObjectiveSugar/ObjectiveSugar.h create mode 120000 Pods/Headers/Private/PromiseKit/CALayer+PromiseKit.h rename Pods/Headers/{Build => Private}/PromiseKit/NSNotificationCenter+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/NSURLConnection+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/Promise+Pause.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/Promise+Until.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/Promise+When.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/Promise.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/UIActionSheet+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/UIAlertView+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/UIView+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/UIViewController+PromiseKit.h (100%) rename Pods/Headers/{Build => Private}/PromiseKit/fwd.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/NSDictionary+YapDatabase.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKAttachRequest.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKChangeQueue.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKChangeRecord.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKChangeSet.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKMappingTableInfo.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKMergeInfo.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKRecord.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKRecordInfo.h create mode 120000 Pods/Headers/Private/YapDatabase/YDBCKRecordTableInfo.h create mode 120000 Pods/Headers/Private/YapDatabase/YapCache.h rename Pods/Headers/{Build => Private}/YapDatabase/YapCollectionKey.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabase.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKit.h create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitConnection.h create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitOptions.h create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitPrivate.h create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTransaction.h create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTypes.h rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseConnectionDefaults.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseConnectionState.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseExtension.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseExtensionConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseExtensionPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseExtensionTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFilteredView.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFilteredViewConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFilteredViewPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFilteredViewTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFilteredViewTypes.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFullTextSearch.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFullTextSearchConnection.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchHandler.h rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFullTextSearchPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseFullTextSearchTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseLogging.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseManager.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabasePrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseQuery.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationship.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipEdge.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipEdgePrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipNode.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseRelationshipTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchQueue.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchQueuePrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchResultsView.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchResultsViewConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchResultsViewOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchResultsViewPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSearchResultsViewTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndex.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndexConnection.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexHandler.h rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndexOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndexPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndexSetup.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseSecondaryIndexTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseStatement.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseString.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseView.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewChange.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewChangePrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewConnection.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewMappings.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewMappingsPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewPage.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewPageMetadata.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewRangeOptions.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewState.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewTransaction.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapDatabaseViewTypes.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapDebugDictionary.h rename Pods/Headers/{Build => Private}/YapDatabase/YapMemoryTable.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapMurmurHash.h rename Pods/Headers/{Build => Private}/YapDatabase/YapNull.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapRowidSet.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapSet.h (100%) rename Pods/Headers/{Build => Private}/YapDatabase/YapTouch.h (100%) create mode 120000 Pods/Headers/Private/YapDatabase/YapWhitelistBlacklist.h rename Pods/Headers/{Build => Private}/libextobjc/EXTADT.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTConcreteProtocol.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTKeyPathCoding.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTNil.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTRuntimeExtensions.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTSafeCategory.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTScope.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTSelectorChecking.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/EXTSynthesize.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/NSInvocation+EXT.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/NSMethodSignature+EXT.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/extobjc.h (100%) rename Pods/Headers/{Build => Private}/libextobjc/metamacros.h (100%) delete mode 120000 Pods/Headers/Public/Mantle/MTLManagedObjectAdapter.h create mode 120000 Pods/Headers/Public/Mantle/MTLTransformerErrorHandling.h create mode 120000 Pods/Headers/Public/Mantle/NSDictionary+MTLJSONKeyPath.h create mode 120000 Pods/Headers/Public/Mantle/NSDictionary+MTLMappingAdditions.h delete mode 120000 Pods/Headers/Public/OHHTTPStubs/OHHTTPStubs.h delete mode 120000 Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h delete mode 120000 Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+JSON.h delete mode 120000 Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSArray+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSDictionary+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSNumber+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSSet+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/NSString+ObjectiveSugar.h create mode 120000 Pods/Headers/Public/ObjectiveSugar/ObjectiveSugar.h create mode 120000 Pods/Headers/Public/PromiseKit/CALayer+PromiseKit.h delete mode 120000 Pods/Headers/Public/PromiseKit/PromiseKit+Foundation.h delete mode 120000 Pods/Headers/Public/PromiseKit/PromiseKit+UIKit.h create mode 120000 Pods/Headers/Public/YapDatabase/YDBCKChangeSet.h create mode 120000 Pods/Headers/Public/YapDatabase/YDBCKMergeInfo.h create mode 120000 Pods/Headers/Public/YapDatabase/YDBCKRecord.h create mode 120000 Pods/Headers/Public/YapDatabase/YDBCKRecordInfo.h create mode 120000 Pods/Headers/Public/YapDatabase/YapCache.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseCloudKit.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitConnection.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitOptions.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTransaction.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTypes.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseFullTextSearchHandler.h create mode 120000 Pods/Headers/Public/YapDatabase/YapDatabaseSecondaryIndexHandler.h create mode 120000 Pods/Headers/Public/YapDatabase/YapMurmurHash.h create mode 120000 Pods/Headers/Public/YapDatabase/YapWhitelistBlacklist.h delete mode 100644 Pods/Mantle/Mantle/MTLManagedObjectAdapter.h delete mode 100644 Pods/Mantle/Mantle/MTLManagedObjectAdapter.m create mode 100644 Pods/Mantle/Mantle/MTLTransformerErrorHandling.h create mode 100644 Pods/Mantle/Mantle/MTLTransformerErrorHandling.m create mode 100644 Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h create mode 100644 Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.m create mode 100644 Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.h create mode 100644 Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.m delete mode 100644 Pods/OHHTTPStubs/LICENSE delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h delete mode 100644 Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m delete mode 100644 Pods/OHHTTPStubs/README.md create mode 100644 Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.m create mode 100644 Pods/ObjectiveSugar/Classes/ObjectiveSugar.h create mode 100644 Pods/ObjectiveSugar/LICENSE create mode 100644 Pods/ObjectiveSugar/README.md create mode 100644 Pods/PromiseKit/objc/CALayer+PromiseKit.h create mode 100644 Pods/PromiseKit/objc/CALayer+PromiseKit.m delete mode 100755 Pods/PromiseKit/objc/Private/xctest.rb create mode 100644 Pods/PromiseKit/objc/PromiseKit/Promise+Hang.h create mode 100644 Pods/PromiseKit/objc/PromiseKit/Promise+Join.h create mode 100644 Pods/PromiseKit/objc/PromiseKit/Promise+Zalgo.h delete mode 100644 Pods/PromiseKit/objc/deprecated/PromiseKit+Foundation.h delete mode 100644 Pods/PromiseKit/objc/deprecated/PromiseKit+UIKit.h delete mode 100644 Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-Private.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch delete mode 100644 Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.markdown delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.plist delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-dummy.m delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-environment.h delete mode 100755 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-resources.sh delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.debug.xcconfig delete mode 100644 Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.release.xcconfig create mode 100644 Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-Private.xcconfig create mode 100644 Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-dummy.m rename Pods/Target Support Files/{Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch => Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch} (55%) rename Pods/Target Support Files/{Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack.xcconfig => Pods-ObjectiveSugar/Pods-ObjectiveSugar.xcconfig} (100%) create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.m delete mode 100644 Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.m create mode 100644 Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.m delete mode 100644 Pods/YapDatabase/YapDatabase/Internal/YapCache.h create mode 100644 Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.h create mode 100644 Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.m create mode 100644 Pods/YapDatabase/YapDatabase/Utilities/YapCache.h rename Pods/YapDatabase/YapDatabase/{Internal => Utilities}/YapCache.m (80%) create mode 100644 Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.h create mode 100644 Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.m create mode 100644 Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h create mode 100644 Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.m diff --git a/Podfile b/Podfile index 0e6a7e5..709cdb8 100644 --- a/Podfile +++ b/Podfile @@ -7,10 +7,10 @@ pod 'Mantle' pod 'PromiseKit' pod 'YapDatabase' pod 'libextobjc' +pod 'ObjectiveSugar' # target 'Blog' do # end -target 'BlogTests' do - pod 'OHHTTPStubs' -end +# target 'BlogTests' do +# end diff --git a/Podfile.lock b/Podfile.lock index 2127bb9..f1d50ac 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,115 +1,110 @@ PODS: - CocoaLumberjack (1.9.2): - - CocoaLumberjack/Extensions + - CocoaLumberjack/Extensions (= 1.9.2) - CocoaLumberjack/Core (1.9.2) - CocoaLumberjack/Extensions (1.9.2): - CocoaLumberjack/Core - - libextobjc (0.4): - - libextobjc/EXTADT - - libextobjc/EXTConcreteProtocol - - libextobjc/EXTKeyPathCoding - - libextobjc/EXTNil - - libextobjc/EXTSafeCategory - - libextobjc/EXTScope - - libextobjc/EXTSelectorChecking - - libextobjc/EXTSynthesize - - libextobjc/NSInvocation+EXT - - libextobjc/NSMethodSignature+EXT + - libextobjc (0.4.1): + - libextobjc/EXTADT (= 0.4.1) + - libextobjc/EXTConcreteProtocol (= 0.4.1) + - libextobjc/EXTKeyPathCoding (= 0.4.1) + - libextobjc/EXTNil (= 0.4.1) + - libextobjc/EXTSafeCategory (= 0.4.1) + - libextobjc/EXTScope (= 0.4.1) + - libextobjc/EXTSelectorChecking (= 0.4.1) + - libextobjc/EXTSynthesize (= 0.4.1) + - libextobjc/NSInvocation+EXT (= 0.4.1) + - libextobjc/NSMethodSignature+EXT (= 0.4.1) + - libextobjc/RuntimeExtensions (= 0.4.1) + - libextobjc/UmbrellaHeader (= 0.4.1) + - libextobjc/EXTADT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/UmbrellaHeader - - libextobjc/EXTADT (0.4): + - libextobjc/EXTConcreteProtocol (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTConcreteProtocol (0.4): + - libextobjc/EXTKeyPathCoding (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTKeyPathCoding (0.4): + - libextobjc/EXTNil (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTNil (0.4): + - libextobjc/EXTSafeCategory (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSafeCategory (0.4): + - libextobjc/EXTScope (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTScope (0.4): + - libextobjc/EXTSelectorChecking (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSelectorChecking (0.4): + - libextobjc/EXTSynthesize (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSynthesize (0.4): + - libextobjc/NSInvocation+EXT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/NSInvocation+EXT (0.4): + - libextobjc/NSMethodSignature+EXT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/NSMethodSignature+EXT (0.4): - - libextobjc/RuntimeExtensions - - libextobjc/RuntimeExtensions (0.4) - - libextobjc/UmbrellaHeader (0.4) - - Mantle (1.5.1): - - Mantle/extobjc - - Mantle/extobjc (1.5.1) - - OHHTTPStubs (3.1.6): - - OHHTTPStubs/Core - - OHHTTPStubs/Core (3.1.6) + - libextobjc/RuntimeExtensions (0.4.1) + - libextobjc/UmbrellaHeader (0.4.1) + - Mantle (2.0): + - Mantle/extobjc (= 2.0) + - Mantle/extobjc (2.0) + - ObjectiveSugar (1.1.0) - OMGHTTPURLRQ (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/RQ - - OMGHTTPURLRQ/UserAgent - - OMGHTTPURLRQ/FormURLEncode (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/UserAgent + - OMGHTTPURLRQ/RQ (= 2.1) + - OMGHTTPURLRQ/FormURLEncode (2.1) - OMGHTTPURLRQ/RQ (2.1): - OMGHTTPURLRQ/FormURLEncode - OMGHTTPURLRQ/UserAgent - - OMGHTTPURLRQ/UserAgent (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/UserAgent - - PromiseKit (1.0): - - PromiseKit/NSNotificationCenter - - PromiseKit/NSURLConnection - - PromiseKit/Pause - - PromiseKit/UIActionSheet - - PromiseKit/UIAlertView - - PromiseKit/UIView - - PromiseKit/UIViewController - - PromiseKit/Until - - PromiseKit/When - - PromiseKit/NSNotificationCenter (1.0): + - OMGHTTPURLRQ/UserAgent (2.1) + - PromiseKit (1.5.1): + - PromiseKit/CALayer (= 1.5.1) + - PromiseKit/NSNotificationCenter (= 1.5.1) + - PromiseKit/NSURLConnection (= 1.5.1) + - PromiseKit/Pause (= 1.5.1) + - PromiseKit/UIActionSheet (= 1.5.1) + - PromiseKit/UIAlertView (= 1.5.1) + - PromiseKit/UIView (= 1.5.1) + - PromiseKit/UIViewController (= 1.5.1) + - PromiseKit/Until (= 1.5.1) + - PromiseKit/When (= 1.5.1) + - PromiseKit/CALayer (1.5.1): - PromiseKit/Promise - - PromiseKit/NSURLConnection (1.0): + - PromiseKit/NSNotificationCenter (1.5.1): + - PromiseKit/Promise + - PromiseKit/NSURLConnection (1.5.1): - OMGHTTPURLRQ - PromiseKit/Promise - - PromiseKit/Pause (1.0): + - PromiseKit/Pause (1.5.1): - PromiseKit/Promise - - PromiseKit/Promise (1.0) - - PromiseKit/UIActionSheet (1.0): + - PromiseKit/Promise (1.5.1) + - PromiseKit/UIActionSheet (1.5.1): - PromiseKit/Promise - - PromiseKit/UIAlertView (1.0): + - PromiseKit/UIAlertView (1.5.1): - PromiseKit/Promise - - PromiseKit/UIView (1.0): + - PromiseKit/UIView (1.5.1): - PromiseKit/Promise - - PromiseKit/UIViewController (1.0): + - PromiseKit/UIViewController (1.5.1): - PromiseKit/Promise - - PromiseKit/Until (1.0): + - PromiseKit/Until (1.5.1): - PromiseKit/Promise - PromiseKit/When - - PromiseKit/When (1.0): + - PromiseKit/When (1.5.1): - PromiseKit/Promise - - YapDatabase (2.5.2): - - YapDatabase/standard - - YapDatabase/common (2.5.2): + - YapDatabase (2.6.1): + - YapDatabase/standard (= 2.6.1) + - YapDatabase/common (2.6.1): - CocoaLumberjack (~> 1) - - YapDatabase/standard (2.5.2): + - YapDatabase/standard (2.6.1): - YapDatabase/common DEPENDENCIES: - libextobjc - Mantle - - OHHTTPStubs + - ObjectiveSugar - PromiseKit - YapDatabase SPEC CHECKSUMS: - CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817 - libextobjc: ba42e4111f433273a886cd54f0ddaddb7f62f82f - Mantle: d7c5ac734579ec751c58fecbf56189853056c58c - OHHTTPStubs: 6781373b69e0a67b27239799f11764d0fbefac55 - OMGHTTPURLRQ: 16564bcee86d8dfa298b65cdf60015c3065f67df - PromiseKit: 3a8eb40bb66c8f74ebd629f03ad8b0d5581a744c - YapDatabase: 50f763e49374c38025e8255b4c468d26d81b1048 + CocoaLumberjack: 628fca2e88ef06f7cf6817309aa405f325d9a6fa + libextobjc: a650fc1bf489a3d3a9bc2e621efa3e1006fc5471 + Mantle: 17de73ef929db2234d76fde2aacfb89ab11c61e8 + ObjectiveSugar: a6a25f23d657c19df0a0b972466d5b5ca9f5295c + OMGHTTPURLRQ: f8c515dfd2f57a5d74c710978f600231f52afec5 + PromiseKit: b1145ebb1dd0780566952689191ea31466198ee8 + YapDatabase: 13566c87dc9226a0f15d755edba08e8ad94cac9f -COCOAPODS: 0.34.4 +COCOAPODS: 0.37.0.beta.1 diff --git a/Pods/Headers/Build/Mantle/MTLManagedObjectAdapter.h b/Pods/Headers/Build/Mantle/MTLManagedObjectAdapter.h deleted file mode 120000 index d30d351..0000000 --- a/Pods/Headers/Build/Mantle/MTLManagedObjectAdapter.h +++ /dev/null @@ -1 +0,0 @@ -../../../Mantle/Mantle/MTLManagedObjectAdapter.h \ No newline at end of file diff --git a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubs.h b/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubs.h deleted file mode 120000 index 984cead..0000000 --- a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubs.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h \ No newline at end of file diff --git a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h b/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h deleted file mode 120000 index e378133..0000000 --- a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h \ No newline at end of file diff --git a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+JSON.h b/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+JSON.h deleted file mode 120000 index 8af13cb..0000000 --- a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse+JSON.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h \ No newline at end of file diff --git a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse.h b/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse.h deleted file mode 120000 index 9a5e7fc..0000000 --- a/Pods/Headers/Build/OHHTTPStubs/OHHTTPStubsResponse.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h \ No newline at end of file diff --git a/Pods/Headers/Build/PromiseKit/PromiseKit+Foundation.h b/Pods/Headers/Build/PromiseKit/PromiseKit+Foundation.h deleted file mode 120000 index e8bfbf7..0000000 --- a/Pods/Headers/Build/PromiseKit/PromiseKit+Foundation.h +++ /dev/null @@ -1 +0,0 @@ -../../../PromiseKit/objc/deprecated/PromiseKit+Foundation.h \ No newline at end of file diff --git a/Pods/Headers/Build/PromiseKit/PromiseKit+UIKit.h b/Pods/Headers/Build/PromiseKit/PromiseKit+UIKit.h deleted file mode 120000 index a3deade..0000000 --- a/Pods/Headers/Build/PromiseKit/PromiseKit+UIKit.h +++ /dev/null @@ -1 +0,0 @@ -../../../PromiseKit/objc/deprecated/PromiseKit+UIKit.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapCache.h b/Pods/Headers/Build/YapDatabase/YapCache.h deleted file mode 120000 index 58f7d80..0000000 --- a/Pods/Headers/Build/YapDatabase/YapCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../YapDatabase/YapDatabase/Internal/YapCache.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h b/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h deleted file mode 120000 index a032275..0000000 --- a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h +++ /dev/null @@ -1 +0,0 @@ -../../../YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h \ No newline at end of file diff --git a/Pods/Headers/Build/CocoaLumberjack/DDASLLogCapture.h b/Pods/Headers/Private/CocoaLumberjack/DDASLLogCapture.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDASLLogCapture.h rename to Pods/Headers/Private/CocoaLumberjack/DDASLLogCapture.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDASLLogger.h b/Pods/Headers/Private/CocoaLumberjack/DDASLLogger.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDASLLogger.h rename to Pods/Headers/Private/CocoaLumberjack/DDASLLogger.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDAbstractDatabaseLogger.h b/Pods/Headers/Private/CocoaLumberjack/DDAbstractDatabaseLogger.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDAbstractDatabaseLogger.h rename to Pods/Headers/Private/CocoaLumberjack/DDAbstractDatabaseLogger.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDAssert.h b/Pods/Headers/Private/CocoaLumberjack/DDAssert.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDAssert.h rename to Pods/Headers/Private/CocoaLumberjack/DDAssert.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDContextFilterLogFormatter.h b/Pods/Headers/Private/CocoaLumberjack/DDContextFilterLogFormatter.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDContextFilterLogFormatter.h rename to Pods/Headers/Private/CocoaLumberjack/DDContextFilterLogFormatter.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDDispatchQueueLogFormatter.h b/Pods/Headers/Private/CocoaLumberjack/DDDispatchQueueLogFormatter.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDDispatchQueueLogFormatter.h rename to Pods/Headers/Private/CocoaLumberjack/DDDispatchQueueLogFormatter.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDFileLogger.h b/Pods/Headers/Private/CocoaLumberjack/DDFileLogger.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDFileLogger.h rename to Pods/Headers/Private/CocoaLumberjack/DDFileLogger.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDLog+LOGV.h b/Pods/Headers/Private/CocoaLumberjack/DDLog+LOGV.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDLog+LOGV.h rename to Pods/Headers/Private/CocoaLumberjack/DDLog+LOGV.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDLog.h b/Pods/Headers/Private/CocoaLumberjack/DDLog.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDLog.h rename to Pods/Headers/Private/CocoaLumberjack/DDLog.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDMultiFormatter.h b/Pods/Headers/Private/CocoaLumberjack/DDMultiFormatter.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDMultiFormatter.h rename to Pods/Headers/Private/CocoaLumberjack/DDMultiFormatter.h diff --git a/Pods/Headers/Build/CocoaLumberjack/DDTTYLogger.h b/Pods/Headers/Private/CocoaLumberjack/DDTTYLogger.h similarity index 100% rename from Pods/Headers/Build/CocoaLumberjack/DDTTYLogger.h rename to Pods/Headers/Private/CocoaLumberjack/DDTTYLogger.h diff --git a/Pods/Headers/Build/Mantle/EXTKeyPathCoding.h b/Pods/Headers/Private/Mantle/EXTKeyPathCoding.h similarity index 100% rename from Pods/Headers/Build/Mantle/EXTKeyPathCoding.h rename to Pods/Headers/Private/Mantle/EXTKeyPathCoding.h diff --git a/Pods/Headers/Build/Mantle/EXTRuntimeExtensions.h b/Pods/Headers/Private/Mantle/EXTRuntimeExtensions.h similarity index 100% rename from Pods/Headers/Build/Mantle/EXTRuntimeExtensions.h rename to Pods/Headers/Private/Mantle/EXTRuntimeExtensions.h diff --git a/Pods/Headers/Build/Mantle/EXTScope.h b/Pods/Headers/Private/Mantle/EXTScope.h similarity index 100% rename from Pods/Headers/Build/Mantle/EXTScope.h rename to Pods/Headers/Private/Mantle/EXTScope.h diff --git a/Pods/Headers/Build/Mantle/MTLJSONAdapter.h b/Pods/Headers/Private/Mantle/MTLJSONAdapter.h similarity index 100% rename from Pods/Headers/Build/Mantle/MTLJSONAdapter.h rename to Pods/Headers/Private/Mantle/MTLJSONAdapter.h diff --git a/Pods/Headers/Build/Mantle/MTLModel+NSCoding.h b/Pods/Headers/Private/Mantle/MTLModel+NSCoding.h similarity index 100% rename from Pods/Headers/Build/Mantle/MTLModel+NSCoding.h rename to Pods/Headers/Private/Mantle/MTLModel+NSCoding.h diff --git a/Pods/Headers/Build/Mantle/MTLModel.h b/Pods/Headers/Private/Mantle/MTLModel.h similarity index 100% rename from Pods/Headers/Build/Mantle/MTLModel.h rename to Pods/Headers/Private/Mantle/MTLModel.h diff --git a/Pods/Headers/Build/Mantle/MTLReflection.h b/Pods/Headers/Private/Mantle/MTLReflection.h similarity index 100% rename from Pods/Headers/Build/Mantle/MTLReflection.h rename to Pods/Headers/Private/Mantle/MTLReflection.h diff --git a/Pods/Headers/Private/Mantle/MTLTransformerErrorHandling.h b/Pods/Headers/Private/Mantle/MTLTransformerErrorHandling.h new file mode 120000 index 0000000..b885860 --- /dev/null +++ b/Pods/Headers/Private/Mantle/MTLTransformerErrorHandling.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/MTLTransformerErrorHandling.h \ No newline at end of file diff --git a/Pods/Headers/Build/Mantle/MTLValueTransformer.h b/Pods/Headers/Private/Mantle/MTLValueTransformer.h similarity index 100% rename from Pods/Headers/Build/Mantle/MTLValueTransformer.h rename to Pods/Headers/Private/Mantle/MTLValueTransformer.h diff --git a/Pods/Headers/Build/Mantle/Mantle.h b/Pods/Headers/Private/Mantle/Mantle.h similarity index 100% rename from Pods/Headers/Build/Mantle/Mantle.h rename to Pods/Headers/Private/Mantle/Mantle.h diff --git a/Pods/Headers/Build/Mantle/NSArray+MTLManipulationAdditions.h b/Pods/Headers/Private/Mantle/NSArray+MTLManipulationAdditions.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSArray+MTLManipulationAdditions.h rename to Pods/Headers/Private/Mantle/NSArray+MTLManipulationAdditions.h diff --git a/Pods/Headers/Private/Mantle/NSDictionary+MTLJSONKeyPath.h b/Pods/Headers/Private/Mantle/NSDictionary+MTLJSONKeyPath.h new file mode 120000 index 0000000..b35a019 --- /dev/null +++ b/Pods/Headers/Private/Mantle/NSDictionary+MTLJSONKeyPath.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h \ No newline at end of file diff --git a/Pods/Headers/Build/Mantle/NSDictionary+MTLManipulationAdditions.h b/Pods/Headers/Private/Mantle/NSDictionary+MTLManipulationAdditions.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSDictionary+MTLManipulationAdditions.h rename to Pods/Headers/Private/Mantle/NSDictionary+MTLManipulationAdditions.h diff --git a/Pods/Headers/Private/Mantle/NSDictionary+MTLMappingAdditions.h b/Pods/Headers/Private/Mantle/NSDictionary+MTLMappingAdditions.h new file mode 120000 index 0000000..3cd348a --- /dev/null +++ b/Pods/Headers/Private/Mantle/NSDictionary+MTLMappingAdditions.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/NSDictionary+MTLMappingAdditions.h \ No newline at end of file diff --git a/Pods/Headers/Build/Mantle/NSError+MTLModelException.h b/Pods/Headers/Private/Mantle/NSError+MTLModelException.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSError+MTLModelException.h rename to Pods/Headers/Private/Mantle/NSError+MTLModelException.h diff --git a/Pods/Headers/Build/Mantle/NSObject+MTLComparisonAdditions.h b/Pods/Headers/Private/Mantle/NSObject+MTLComparisonAdditions.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSObject+MTLComparisonAdditions.h rename to Pods/Headers/Private/Mantle/NSObject+MTLComparisonAdditions.h diff --git a/Pods/Headers/Build/Mantle/NSValueTransformer+MTLInversionAdditions.h b/Pods/Headers/Private/Mantle/NSValueTransformer+MTLInversionAdditions.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSValueTransformer+MTLInversionAdditions.h rename to Pods/Headers/Private/Mantle/NSValueTransformer+MTLInversionAdditions.h diff --git a/Pods/Headers/Build/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h b/Pods/Headers/Private/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h similarity index 100% rename from Pods/Headers/Build/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h rename to Pods/Headers/Private/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h diff --git a/Pods/Headers/Build/Mantle/metamacros.h b/Pods/Headers/Private/Mantle/metamacros.h similarity index 100% rename from Pods/Headers/Build/Mantle/metamacros.h rename to Pods/Headers/Private/Mantle/metamacros.h diff --git a/Pods/Headers/Build/OMGHTTPURLRQ/OMGFormURLEncode.h b/Pods/Headers/Private/OMGHTTPURLRQ/OMGFormURLEncode.h similarity index 100% rename from Pods/Headers/Build/OMGHTTPURLRQ/OMGFormURLEncode.h rename to Pods/Headers/Private/OMGHTTPURLRQ/OMGFormURLEncode.h diff --git a/Pods/Headers/Build/OMGHTTPURLRQ/OMGHTTPURLRQ.h b/Pods/Headers/Private/OMGHTTPURLRQ/OMGHTTPURLRQ.h similarity index 100% rename from Pods/Headers/Build/OMGHTTPURLRQ/OMGHTTPURLRQ.h rename to Pods/Headers/Private/OMGHTTPURLRQ/OMGHTTPURLRQ.h diff --git a/Pods/Headers/Build/OMGHTTPURLRQ/OMGUserAgent.h b/Pods/Headers/Private/OMGHTTPURLRQ/OMGUserAgent.h similarity index 100% rename from Pods/Headers/Build/OMGHTTPURLRQ/OMGUserAgent.h rename to Pods/Headers/Private/OMGHTTPURLRQ/OMGUserAgent.h diff --git a/Pods/Headers/Private/ObjectiveSugar/NSArray+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSArray+ObjectiveSugar.h new file mode 120000 index 0000000..f215c39 --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSArray+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/NSDictionary+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSDictionary+ObjectiveSugar.h new file mode 120000 index 0000000..7fdf1b5 --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSDictionary+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h new file mode 120000 index 0000000..ff14d4f --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/NSNumber+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSNumber+ObjectiveSugar.h new file mode 120000 index 0000000..7d6da55 --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSNumber+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/NSSet+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSSet+ObjectiveSugar.h new file mode 120000 index 0000000..3ae788d --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSSet+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/NSString+ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/NSString+ObjectiveSugar.h new file mode 120000 index 0000000..16c0c49 --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/NSString+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSString+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/ObjectiveSugar/ObjectiveSugar.h b/Pods/Headers/Private/ObjectiveSugar/ObjectiveSugar.h new file mode 120000 index 0000000..0155cfa --- /dev/null +++ b/Pods/Headers/Private/ObjectiveSugar/ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Private/PromiseKit/CALayer+PromiseKit.h b/Pods/Headers/Private/PromiseKit/CALayer+PromiseKit.h new file mode 120000 index 0000000..4fec14e --- /dev/null +++ b/Pods/Headers/Private/PromiseKit/CALayer+PromiseKit.h @@ -0,0 +1 @@ +../../../PromiseKit/objc/CALayer+PromiseKit.h \ No newline at end of file diff --git a/Pods/Headers/Build/PromiseKit/NSNotificationCenter+PromiseKit.h b/Pods/Headers/Private/PromiseKit/NSNotificationCenter+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/NSNotificationCenter+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/NSNotificationCenter+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/NSURLConnection+PromiseKit.h b/Pods/Headers/Private/PromiseKit/NSURLConnection+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/NSURLConnection+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/NSURLConnection+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/Promise+Pause.h b/Pods/Headers/Private/PromiseKit/Promise+Pause.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/Promise+Pause.h rename to Pods/Headers/Private/PromiseKit/Promise+Pause.h diff --git a/Pods/Headers/Build/PromiseKit/Promise+Until.h b/Pods/Headers/Private/PromiseKit/Promise+Until.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/Promise+Until.h rename to Pods/Headers/Private/PromiseKit/Promise+Until.h diff --git a/Pods/Headers/Build/PromiseKit/Promise+When.h b/Pods/Headers/Private/PromiseKit/Promise+When.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/Promise+When.h rename to Pods/Headers/Private/PromiseKit/Promise+When.h diff --git a/Pods/Headers/Build/PromiseKit/Promise.h b/Pods/Headers/Private/PromiseKit/Promise.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/Promise.h rename to Pods/Headers/Private/PromiseKit/Promise.h diff --git a/Pods/Headers/Build/PromiseKit/PromiseKit.h b/Pods/Headers/Private/PromiseKit/PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/PromiseKit.h rename to Pods/Headers/Private/PromiseKit/PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/UIActionSheet+PromiseKit.h b/Pods/Headers/Private/PromiseKit/UIActionSheet+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/UIActionSheet+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/UIActionSheet+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/UIAlertView+PromiseKit.h b/Pods/Headers/Private/PromiseKit/UIAlertView+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/UIAlertView+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/UIAlertView+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/UIView+PromiseKit.h b/Pods/Headers/Private/PromiseKit/UIView+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/UIView+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/UIView+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/UIViewController+PromiseKit.h b/Pods/Headers/Private/PromiseKit/UIViewController+PromiseKit.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/UIViewController+PromiseKit.h rename to Pods/Headers/Private/PromiseKit/UIViewController+PromiseKit.h diff --git a/Pods/Headers/Build/PromiseKit/fwd.h b/Pods/Headers/Private/PromiseKit/fwd.h similarity index 100% rename from Pods/Headers/Build/PromiseKit/fwd.h rename to Pods/Headers/Private/PromiseKit/fwd.h diff --git a/Pods/Headers/Build/YapDatabase/NSDictionary+YapDatabase.h b/Pods/Headers/Private/YapDatabase/NSDictionary+YapDatabase.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/NSDictionary+YapDatabase.h rename to Pods/Headers/Private/YapDatabase/NSDictionary+YapDatabase.h diff --git a/Pods/Headers/Private/YapDatabase/YDBCKAttachRequest.h b/Pods/Headers/Private/YapDatabase/YDBCKAttachRequest.h new file mode 120000 index 0000000..7bf531b --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKAttachRequest.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKChangeQueue.h b/Pods/Headers/Private/YapDatabase/YDBCKChangeQueue.h new file mode 120000 index 0000000..ce349c9 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKChangeQueue.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKChangeRecord.h b/Pods/Headers/Private/YapDatabase/YDBCKChangeRecord.h new file mode 120000 index 0000000..a3d3d6f --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKChangeRecord.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKChangeSet.h b/Pods/Headers/Private/YapDatabase/YDBCKChangeSet.h new file mode 120000 index 0000000..8263d1c --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKChangeSet.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKMappingTableInfo.h b/Pods/Headers/Private/YapDatabase/YDBCKMappingTableInfo.h new file mode 120000 index 0000000..c72d9d1 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKMappingTableInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKMergeInfo.h b/Pods/Headers/Private/YapDatabase/YDBCKMergeInfo.h new file mode 120000 index 0000000..a2705b4 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKMergeInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKRecord.h b/Pods/Headers/Private/YapDatabase/YDBCKRecord.h new file mode 120000 index 0000000..02cd007 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKRecord.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKRecordInfo.h b/Pods/Headers/Private/YapDatabase/YDBCKRecordInfo.h new file mode 120000 index 0000000..e185752 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKRecordInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YDBCKRecordTableInfo.h b/Pods/Headers/Private/YapDatabase/YDBCKRecordTableInfo.h new file mode 120000 index 0000000..28fb98f --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YDBCKRecordTableInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapCache.h b/Pods/Headers/Private/YapDatabase/YapCache.h new file mode 120000 index 0000000..6bb6a3a --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapCache.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapCache.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapCollectionKey.h b/Pods/Headers/Private/YapDatabase/YapCollectionKey.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapCollectionKey.h rename to Pods/Headers/Private/YapDatabase/YapCollectionKey.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabase.h b/Pods/Headers/Private/YapDatabase/YapDatabase.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabase.h rename to Pods/Headers/Private/YapDatabase/YapDatabase.h diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKit.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKit.h new file mode 120000 index 0000000..0d34f8c --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKit.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitConnection.h new file mode 120000 index 0000000..d3b2571 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitConnection.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitOptions.h new file mode 120000 index 0000000..654e837 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitOptions.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitPrivate.h new file mode 120000 index 0000000..a7b3b21 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitPrivate.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTransaction.h new file mode 120000 index 0000000..416973a --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTransaction.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h \ No newline at end of file diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTypes.h b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTypes.h new file mode 120000 index 0000000..7ace17e --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseCloudKitTypes.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseConnectionDefaults.h b/Pods/Headers/Private/YapDatabase/YapDatabaseConnectionDefaults.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseConnectionDefaults.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseConnectionDefaults.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseConnectionState.h b/Pods/Headers/Private/YapDatabase/YapDatabaseConnectionState.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseConnectionState.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseConnectionState.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseExtension.h b/Pods/Headers/Private/YapDatabase/YapDatabaseExtension.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseExtension.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseExtension.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseExtensionConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseExtensionConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseExtensionConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseExtensionConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseExtensionPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseExtensionPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseExtensionPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseExtensionPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseExtensionTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseExtensionTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseExtensionTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseExtensionTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFilteredView.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFilteredView.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFilteredView.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFilteredView.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewTypes.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewTypes.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFilteredViewTypes.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFilteredViewTypes.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearch.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearch.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearch.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearch.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchConnection.h diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchHandler.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchHandler.h new file mode 120000 index 0000000..bed0f01 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchHandler.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseFullTextSearchTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseFullTextSearchTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseLogging.h b/Pods/Headers/Private/YapDatabase/YapDatabaseLogging.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseLogging.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseLogging.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseManager.h b/Pods/Headers/Private/YapDatabase/YapDatabaseManager.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseManager.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseManager.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabasePrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabasePrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabasePrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabasePrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseQuery.h b/Pods/Headers/Private/YapDatabase/YapDatabaseQuery.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseQuery.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseQuery.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationship.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationship.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationship.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationship.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipEdge.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipEdge.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipEdge.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipEdge.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipEdgePrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipEdgePrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipEdgePrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipEdgePrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipNode.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipNode.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipNode.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipNode.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseRelationshipTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseRelationshipTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchQueue.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchQueue.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchQueue.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchQueue.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchQueuePrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchQueuePrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchQueuePrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchQueuePrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsView.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsView.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsView.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsView.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSearchResultsViewTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSearchResultsViewTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndex.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndex.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndex.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndex.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexConnection.h diff --git a/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexHandler.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexHandler.h new file mode 120000 index 0000000..0bfd5b6 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexHandler.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetup.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexSetup.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexSetup.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexSetup.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseSecondaryIndexTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseSecondaryIndexTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseStatement.h b/Pods/Headers/Private/YapDatabase/YapDatabaseStatement.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseStatement.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseStatement.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseString.h b/Pods/Headers/Private/YapDatabase/YapDatabaseString.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseString.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseString.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseView.h b/Pods/Headers/Private/YapDatabase/YapDatabaseView.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseView.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseView.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewChange.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewChange.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewChange.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewChange.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewChangePrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewChangePrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewChangePrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewChangePrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewConnection.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewConnection.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewConnection.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewConnection.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewMappings.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewMappings.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewMappings.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewMappings.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewMappingsPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewMappingsPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewMappingsPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewMappingsPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewPage.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewPage.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewPage.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewPage.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewPageMetadata.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewPageMetadata.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewPageMetadata.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewPageMetadata.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewRangeOptions.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewRangeOptions.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewRangeOptions.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewRangeOptions.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewState.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewState.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewState.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewState.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewTransaction.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewTransaction.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewTransaction.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewTransaction.h diff --git a/Pods/Headers/Build/YapDatabase/YapDatabaseViewTypes.h b/Pods/Headers/Private/YapDatabase/YapDatabaseViewTypes.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapDatabaseViewTypes.h rename to Pods/Headers/Private/YapDatabase/YapDatabaseViewTypes.h diff --git a/Pods/Headers/Private/YapDatabase/YapDebugDictionary.h b/Pods/Headers/Private/YapDatabase/YapDebugDictionary.h new file mode 120000 index 0000000..c527bd8 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapDebugDictionary.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Internal/YapDebugDictionary.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapMemoryTable.h b/Pods/Headers/Private/YapDatabase/YapMemoryTable.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapMemoryTable.h rename to Pods/Headers/Private/YapDatabase/YapMemoryTable.h diff --git a/Pods/Headers/Private/YapDatabase/YapMurmurHash.h b/Pods/Headers/Private/YapDatabase/YapMurmurHash.h new file mode 120000 index 0000000..1529c94 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapMurmurHash.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapMurmurHash.h \ No newline at end of file diff --git a/Pods/Headers/Build/YapDatabase/YapNull.h b/Pods/Headers/Private/YapDatabase/YapNull.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapNull.h rename to Pods/Headers/Private/YapDatabase/YapNull.h diff --git a/Pods/Headers/Build/YapDatabase/YapRowidSet.h b/Pods/Headers/Private/YapDatabase/YapRowidSet.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapRowidSet.h rename to Pods/Headers/Private/YapDatabase/YapRowidSet.h diff --git a/Pods/Headers/Build/YapDatabase/YapSet.h b/Pods/Headers/Private/YapDatabase/YapSet.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapSet.h rename to Pods/Headers/Private/YapDatabase/YapSet.h diff --git a/Pods/Headers/Build/YapDatabase/YapTouch.h b/Pods/Headers/Private/YapDatabase/YapTouch.h similarity index 100% rename from Pods/Headers/Build/YapDatabase/YapTouch.h rename to Pods/Headers/Private/YapDatabase/YapTouch.h diff --git a/Pods/Headers/Private/YapDatabase/YapWhitelistBlacklist.h b/Pods/Headers/Private/YapDatabase/YapWhitelistBlacklist.h new file mode 120000 index 0000000..cee9d23 --- /dev/null +++ b/Pods/Headers/Private/YapDatabase/YapWhitelistBlacklist.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h \ No newline at end of file diff --git a/Pods/Headers/Build/libextobjc/EXTADT.h b/Pods/Headers/Private/libextobjc/EXTADT.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTADT.h rename to Pods/Headers/Private/libextobjc/EXTADT.h diff --git a/Pods/Headers/Build/libextobjc/EXTConcreteProtocol.h b/Pods/Headers/Private/libextobjc/EXTConcreteProtocol.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTConcreteProtocol.h rename to Pods/Headers/Private/libextobjc/EXTConcreteProtocol.h diff --git a/Pods/Headers/Build/libextobjc/EXTKeyPathCoding.h b/Pods/Headers/Private/libextobjc/EXTKeyPathCoding.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTKeyPathCoding.h rename to Pods/Headers/Private/libextobjc/EXTKeyPathCoding.h diff --git a/Pods/Headers/Build/libextobjc/EXTNil.h b/Pods/Headers/Private/libextobjc/EXTNil.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTNil.h rename to Pods/Headers/Private/libextobjc/EXTNil.h diff --git a/Pods/Headers/Build/libextobjc/EXTRuntimeExtensions.h b/Pods/Headers/Private/libextobjc/EXTRuntimeExtensions.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTRuntimeExtensions.h rename to Pods/Headers/Private/libextobjc/EXTRuntimeExtensions.h diff --git a/Pods/Headers/Build/libextobjc/EXTSafeCategory.h b/Pods/Headers/Private/libextobjc/EXTSafeCategory.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTSafeCategory.h rename to Pods/Headers/Private/libextobjc/EXTSafeCategory.h diff --git a/Pods/Headers/Build/libextobjc/EXTScope.h b/Pods/Headers/Private/libextobjc/EXTScope.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTScope.h rename to Pods/Headers/Private/libextobjc/EXTScope.h diff --git a/Pods/Headers/Build/libextobjc/EXTSelectorChecking.h b/Pods/Headers/Private/libextobjc/EXTSelectorChecking.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTSelectorChecking.h rename to Pods/Headers/Private/libextobjc/EXTSelectorChecking.h diff --git a/Pods/Headers/Build/libextobjc/EXTSynthesize.h b/Pods/Headers/Private/libextobjc/EXTSynthesize.h similarity index 100% rename from Pods/Headers/Build/libextobjc/EXTSynthesize.h rename to Pods/Headers/Private/libextobjc/EXTSynthesize.h diff --git a/Pods/Headers/Build/libextobjc/NSInvocation+EXT.h b/Pods/Headers/Private/libextobjc/NSInvocation+EXT.h similarity index 100% rename from Pods/Headers/Build/libextobjc/NSInvocation+EXT.h rename to Pods/Headers/Private/libextobjc/NSInvocation+EXT.h diff --git a/Pods/Headers/Build/libextobjc/NSMethodSignature+EXT.h b/Pods/Headers/Private/libextobjc/NSMethodSignature+EXT.h similarity index 100% rename from Pods/Headers/Build/libextobjc/NSMethodSignature+EXT.h rename to Pods/Headers/Private/libextobjc/NSMethodSignature+EXT.h diff --git a/Pods/Headers/Build/libextobjc/extobjc.h b/Pods/Headers/Private/libextobjc/extobjc.h similarity index 100% rename from Pods/Headers/Build/libextobjc/extobjc.h rename to Pods/Headers/Private/libextobjc/extobjc.h diff --git a/Pods/Headers/Build/libextobjc/metamacros.h b/Pods/Headers/Private/libextobjc/metamacros.h similarity index 100% rename from Pods/Headers/Build/libextobjc/metamacros.h rename to Pods/Headers/Private/libextobjc/metamacros.h diff --git a/Pods/Headers/Public/Mantle/MTLManagedObjectAdapter.h b/Pods/Headers/Public/Mantle/MTLManagedObjectAdapter.h deleted file mode 120000 index d30d351..0000000 --- a/Pods/Headers/Public/Mantle/MTLManagedObjectAdapter.h +++ /dev/null @@ -1 +0,0 @@ -../../../Mantle/Mantle/MTLManagedObjectAdapter.h \ No newline at end of file diff --git a/Pods/Headers/Public/Mantle/MTLTransformerErrorHandling.h b/Pods/Headers/Public/Mantle/MTLTransformerErrorHandling.h new file mode 120000 index 0000000..b885860 --- /dev/null +++ b/Pods/Headers/Public/Mantle/MTLTransformerErrorHandling.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/MTLTransformerErrorHandling.h \ No newline at end of file diff --git a/Pods/Headers/Public/Mantle/NSDictionary+MTLJSONKeyPath.h b/Pods/Headers/Public/Mantle/NSDictionary+MTLJSONKeyPath.h new file mode 120000 index 0000000..b35a019 --- /dev/null +++ b/Pods/Headers/Public/Mantle/NSDictionary+MTLJSONKeyPath.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h \ No newline at end of file diff --git a/Pods/Headers/Public/Mantle/NSDictionary+MTLMappingAdditions.h b/Pods/Headers/Public/Mantle/NSDictionary+MTLMappingAdditions.h new file mode 120000 index 0000000..3cd348a --- /dev/null +++ b/Pods/Headers/Public/Mantle/NSDictionary+MTLMappingAdditions.h @@ -0,0 +1 @@ +../../../Mantle/Mantle/NSDictionary+MTLMappingAdditions.h \ No newline at end of file diff --git a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubs.h b/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubs.h deleted file mode 120000 index 984cead..0000000 --- a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubs.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h \ No newline at end of file diff --git a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h b/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h deleted file mode 120000 index e378133..0000000 --- a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+HTTPMessage.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h \ No newline at end of file diff --git a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+JSON.h b/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+JSON.h deleted file mode 120000 index 8af13cb..0000000 --- a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse+JSON.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h \ No newline at end of file diff --git a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse.h b/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse.h deleted file mode 120000 index 9a5e7fc..0000000 --- a/Pods/Headers/Public/OHHTTPStubs/OHHTTPStubsResponse.h +++ /dev/null @@ -1 +0,0 @@ -../../../OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSArray+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSArray+ObjectiveSugar.h new file mode 120000 index 0000000..f215c39 --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSArray+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSDictionary+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSDictionary+ObjectiveSugar.h new file mode 120000 index 0000000..7fdf1b5 --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSDictionary+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h new file mode 120000 index 0000000..ff14d4f --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSMutableArray+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSNumber+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSNumber+ObjectiveSugar.h new file mode 120000 index 0000000..7d6da55 --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSNumber+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSSet+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSSet+ObjectiveSugar.h new file mode 120000 index 0000000..3ae788d --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSSet+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/NSString+ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/NSString+ObjectiveSugar.h new file mode 120000 index 0000000..16c0c49 --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/NSString+ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/NSString+ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/ObjectiveSugar/ObjectiveSugar.h b/Pods/Headers/Public/ObjectiveSugar/ObjectiveSugar.h new file mode 120000 index 0000000..0155cfa --- /dev/null +++ b/Pods/Headers/Public/ObjectiveSugar/ObjectiveSugar.h @@ -0,0 +1 @@ +../../../ObjectiveSugar/Classes/ObjectiveSugar.h \ No newline at end of file diff --git a/Pods/Headers/Public/PromiseKit/CALayer+PromiseKit.h b/Pods/Headers/Public/PromiseKit/CALayer+PromiseKit.h new file mode 120000 index 0000000..4fec14e --- /dev/null +++ b/Pods/Headers/Public/PromiseKit/CALayer+PromiseKit.h @@ -0,0 +1 @@ +../../../PromiseKit/objc/CALayer+PromiseKit.h \ No newline at end of file diff --git a/Pods/Headers/Public/PromiseKit/PromiseKit+Foundation.h b/Pods/Headers/Public/PromiseKit/PromiseKit+Foundation.h deleted file mode 120000 index e8bfbf7..0000000 --- a/Pods/Headers/Public/PromiseKit/PromiseKit+Foundation.h +++ /dev/null @@ -1 +0,0 @@ -../../../PromiseKit/objc/deprecated/PromiseKit+Foundation.h \ No newline at end of file diff --git a/Pods/Headers/Public/PromiseKit/PromiseKit+UIKit.h b/Pods/Headers/Public/PromiseKit/PromiseKit+UIKit.h deleted file mode 120000 index a3deade..0000000 --- a/Pods/Headers/Public/PromiseKit/PromiseKit+UIKit.h +++ /dev/null @@ -1 +0,0 @@ -../../../PromiseKit/objc/deprecated/PromiseKit+UIKit.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YDBCKChangeSet.h b/Pods/Headers/Public/YapDatabase/YDBCKChangeSet.h new file mode 120000 index 0000000..8263d1c --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YDBCKChangeSet.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YDBCKMergeInfo.h b/Pods/Headers/Public/YapDatabase/YDBCKMergeInfo.h new file mode 120000 index 0000000..a2705b4 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YDBCKMergeInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YDBCKRecord.h b/Pods/Headers/Public/YapDatabase/YDBCKRecord.h new file mode 120000 index 0000000..02cd007 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YDBCKRecord.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YDBCKRecordInfo.h b/Pods/Headers/Public/YapDatabase/YDBCKRecordInfo.h new file mode 120000 index 0000000..e185752 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YDBCKRecordInfo.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapCache.h b/Pods/Headers/Public/YapDatabase/YapCache.h new file mode 120000 index 0000000..6bb6a3a --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapCache.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapCache.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKit.h b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKit.h new file mode 120000 index 0000000..0d34f8c --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKit.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitConnection.h b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitConnection.h new file mode 120000 index 0000000..d3b2571 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitConnection.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitOptions.h b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitOptions.h new file mode 120000 index 0000000..654e837 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitOptions.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTransaction.h b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTransaction.h new file mode 120000 index 0000000..416973a --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTransaction.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTypes.h b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTypes.h new file mode 120000 index 0000000..7ace17e --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseCloudKitTypes.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseFullTextSearchHandler.h b/Pods/Headers/Public/YapDatabase/YapDatabaseFullTextSearchHandler.h new file mode 120000 index 0000000..bed0f01 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseFullTextSearchHandler.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapDatabaseSecondaryIndexHandler.h b/Pods/Headers/Public/YapDatabase/YapDatabaseSecondaryIndexHandler.h new file mode 120000 index 0000000..0bfd5b6 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapDatabaseSecondaryIndexHandler.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapMurmurHash.h b/Pods/Headers/Public/YapDatabase/YapMurmurHash.h new file mode 120000 index 0000000..1529c94 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapMurmurHash.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapMurmurHash.h \ No newline at end of file diff --git a/Pods/Headers/Public/YapDatabase/YapWhitelistBlacklist.h b/Pods/Headers/Public/YapDatabase/YapWhitelistBlacklist.h new file mode 120000 index 0000000..cee9d23 --- /dev/null +++ b/Pods/Headers/Public/YapDatabase/YapWhitelistBlacklist.h @@ -0,0 +1 @@ +../../../YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h \ No newline at end of file diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index 2127bb9..f1d50ac 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -1,115 +1,110 @@ PODS: - CocoaLumberjack (1.9.2): - - CocoaLumberjack/Extensions + - CocoaLumberjack/Extensions (= 1.9.2) - CocoaLumberjack/Core (1.9.2) - CocoaLumberjack/Extensions (1.9.2): - CocoaLumberjack/Core - - libextobjc (0.4): - - libextobjc/EXTADT - - libextobjc/EXTConcreteProtocol - - libextobjc/EXTKeyPathCoding - - libextobjc/EXTNil - - libextobjc/EXTSafeCategory - - libextobjc/EXTScope - - libextobjc/EXTSelectorChecking - - libextobjc/EXTSynthesize - - libextobjc/NSInvocation+EXT - - libextobjc/NSMethodSignature+EXT + - libextobjc (0.4.1): + - libextobjc/EXTADT (= 0.4.1) + - libextobjc/EXTConcreteProtocol (= 0.4.1) + - libextobjc/EXTKeyPathCoding (= 0.4.1) + - libextobjc/EXTNil (= 0.4.1) + - libextobjc/EXTSafeCategory (= 0.4.1) + - libextobjc/EXTScope (= 0.4.1) + - libextobjc/EXTSelectorChecking (= 0.4.1) + - libextobjc/EXTSynthesize (= 0.4.1) + - libextobjc/NSInvocation+EXT (= 0.4.1) + - libextobjc/NSMethodSignature+EXT (= 0.4.1) + - libextobjc/RuntimeExtensions (= 0.4.1) + - libextobjc/UmbrellaHeader (= 0.4.1) + - libextobjc/EXTADT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/UmbrellaHeader - - libextobjc/EXTADT (0.4): + - libextobjc/EXTConcreteProtocol (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTConcreteProtocol (0.4): + - libextobjc/EXTKeyPathCoding (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTKeyPathCoding (0.4): + - libextobjc/EXTNil (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTNil (0.4): + - libextobjc/EXTSafeCategory (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSafeCategory (0.4): + - libextobjc/EXTScope (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTScope (0.4): + - libextobjc/EXTSelectorChecking (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSelectorChecking (0.4): + - libextobjc/EXTSynthesize (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/EXTSynthesize (0.4): + - libextobjc/NSInvocation+EXT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/NSInvocation+EXT (0.4): + - libextobjc/NSMethodSignature+EXT (0.4.1): - libextobjc/RuntimeExtensions - - libextobjc/NSMethodSignature+EXT (0.4): - - libextobjc/RuntimeExtensions - - libextobjc/RuntimeExtensions (0.4) - - libextobjc/UmbrellaHeader (0.4) - - Mantle (1.5.1): - - Mantle/extobjc - - Mantle/extobjc (1.5.1) - - OHHTTPStubs (3.1.6): - - OHHTTPStubs/Core - - OHHTTPStubs/Core (3.1.6) + - libextobjc/RuntimeExtensions (0.4.1) + - libextobjc/UmbrellaHeader (0.4.1) + - Mantle (2.0): + - Mantle/extobjc (= 2.0) + - Mantle/extobjc (2.0) + - ObjectiveSugar (1.1.0) - OMGHTTPURLRQ (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/RQ - - OMGHTTPURLRQ/UserAgent - - OMGHTTPURLRQ/FormURLEncode (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/UserAgent + - OMGHTTPURLRQ/RQ (= 2.1) + - OMGHTTPURLRQ/FormURLEncode (2.1) - OMGHTTPURLRQ/RQ (2.1): - OMGHTTPURLRQ/FormURLEncode - OMGHTTPURLRQ/UserAgent - - OMGHTTPURLRQ/UserAgent (2.1): - - OMGHTTPURLRQ/FormURLEncode - - OMGHTTPURLRQ/UserAgent - - PromiseKit (1.0): - - PromiseKit/NSNotificationCenter - - PromiseKit/NSURLConnection - - PromiseKit/Pause - - PromiseKit/UIActionSheet - - PromiseKit/UIAlertView - - PromiseKit/UIView - - PromiseKit/UIViewController - - PromiseKit/Until - - PromiseKit/When - - PromiseKit/NSNotificationCenter (1.0): + - OMGHTTPURLRQ/UserAgent (2.1) + - PromiseKit (1.5.1): + - PromiseKit/CALayer (= 1.5.1) + - PromiseKit/NSNotificationCenter (= 1.5.1) + - PromiseKit/NSURLConnection (= 1.5.1) + - PromiseKit/Pause (= 1.5.1) + - PromiseKit/UIActionSheet (= 1.5.1) + - PromiseKit/UIAlertView (= 1.5.1) + - PromiseKit/UIView (= 1.5.1) + - PromiseKit/UIViewController (= 1.5.1) + - PromiseKit/Until (= 1.5.1) + - PromiseKit/When (= 1.5.1) + - PromiseKit/CALayer (1.5.1): - PromiseKit/Promise - - PromiseKit/NSURLConnection (1.0): + - PromiseKit/NSNotificationCenter (1.5.1): + - PromiseKit/Promise + - PromiseKit/NSURLConnection (1.5.1): - OMGHTTPURLRQ - PromiseKit/Promise - - PromiseKit/Pause (1.0): + - PromiseKit/Pause (1.5.1): - PromiseKit/Promise - - PromiseKit/Promise (1.0) - - PromiseKit/UIActionSheet (1.0): + - PromiseKit/Promise (1.5.1) + - PromiseKit/UIActionSheet (1.5.1): - PromiseKit/Promise - - PromiseKit/UIAlertView (1.0): + - PromiseKit/UIAlertView (1.5.1): - PromiseKit/Promise - - PromiseKit/UIView (1.0): + - PromiseKit/UIView (1.5.1): - PromiseKit/Promise - - PromiseKit/UIViewController (1.0): + - PromiseKit/UIViewController (1.5.1): - PromiseKit/Promise - - PromiseKit/Until (1.0): + - PromiseKit/Until (1.5.1): - PromiseKit/Promise - PromiseKit/When - - PromiseKit/When (1.0): + - PromiseKit/When (1.5.1): - PromiseKit/Promise - - YapDatabase (2.5.2): - - YapDatabase/standard - - YapDatabase/common (2.5.2): + - YapDatabase (2.6.1): + - YapDatabase/standard (= 2.6.1) + - YapDatabase/common (2.6.1): - CocoaLumberjack (~> 1) - - YapDatabase/standard (2.5.2): + - YapDatabase/standard (2.6.1): - YapDatabase/common DEPENDENCIES: - libextobjc - Mantle - - OHHTTPStubs + - ObjectiveSugar - PromiseKit - YapDatabase SPEC CHECKSUMS: - CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817 - libextobjc: ba42e4111f433273a886cd54f0ddaddb7f62f82f - Mantle: d7c5ac734579ec751c58fecbf56189853056c58c - OHHTTPStubs: 6781373b69e0a67b27239799f11764d0fbefac55 - OMGHTTPURLRQ: 16564bcee86d8dfa298b65cdf60015c3065f67df - PromiseKit: 3a8eb40bb66c8f74ebd629f03ad8b0d5581a744c - YapDatabase: 50f763e49374c38025e8255b4c468d26d81b1048 + CocoaLumberjack: 628fca2e88ef06f7cf6817309aa405f325d9a6fa + libextobjc: a650fc1bf489a3d3a9bc2e621efa3e1006fc5471 + Mantle: 17de73ef929db2234d76fde2aacfb89ab11c61e8 + ObjectiveSugar: a6a25f23d657c19df0a0b972466d5b5ca9f5295c + OMGHTTPURLRQ: f8c515dfd2f57a5d74c710978f600231f52afec5 + PromiseKit: b1145ebb1dd0780566952689191ea31466198ee8 + YapDatabase: 13566c87dc9226a0f15d755edba08e8ad94cac9f -COCOAPODS: 0.34.4 +COCOAPODS: 0.37.0.beta.1 diff --git a/Pods/Mantle/LICENSE.md b/Pods/Mantle/LICENSE.md index 0c46720..4e9825a 100644 --- a/Pods/Mantle/LICENSE.md +++ b/Pods/Mantle/LICENSE.md @@ -1,4 +1,4 @@ -**Copyright (c) 2012 - 2014, GitHub, Inc.** +**Copyright (c) GitHub, Inc.** **All rights reserved.** 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: diff --git a/Pods/Mantle/Mantle/MTLJSONAdapter.h b/Pods/Mantle/Mantle/MTLJSONAdapter.h index 368c5ab..93892d4 100644 --- a/Pods/Mantle/Mantle/MTLJSONAdapter.h +++ b/Pods/Mantle/Mantle/MTLJSONAdapter.h @@ -8,165 +8,270 @@ #import -@class MTLModel; +@protocol MTLModel; +@protocol MTLTransformerErrorHandling; -// A MTLModel object that supports being parsed from and serialized to JSON. -@protocol MTLJSONSerializing +/// A MTLModel object that supports being parsed from and serialized to JSON. +@protocol MTLJSONSerializing @required -// Specifies how to map property keys to different key paths in JSON. -// -// Subclasses overriding this method should combine their values with those of -// `super`. -// -// Any property keys not present in the dictionary are assumed to match the JSON -// key that should be used. Any keys associated with NSNull will not participate -// in JSON serialization. -// -// Returns a dictionary mapping property keys to JSON key paths (as strings) or -// NSNull values. +/// Specifies how to map property keys to different key paths in JSON. +/// +/// Subclasses overriding this method should combine their values with those of +/// `super`. +/// +/// Values in the dictionary can either be key paths in the JSON representation +/// of the receiver or an array of such key paths. If an array is used, the +/// deserialized value will be a dictionary containing all of the keys in the +/// array. +/// +/// Any keys omitted will not participate in JSON serialization. +/// +/// Examples +/// +/// + (NSDictionary *)JSONKeyPathsByPropertyKey { +/// return @{ +/// @"name": @"POI.name", +/// @"point": @[ @"latitude", @"longitude" ], +/// @"starred": @"starred" +/// }; +/// } +/// +/// This will map the `starred` property to `JSONDictionary[@"starred"]`, `name` +/// to `JSONDictionary[@"POI"][@"name"]` and `point` to a dictionary equivalent +/// to: +/// +/// @{ +/// @"latitude": JSONDictionary[@"latitude"], +/// @"longitude": JSONDictionary[@"longitude"] +/// } +/// +/// Returns a dictionary mapping property keys to one or multiple JSON key paths +/// (as strings or arrays of strings). + (NSDictionary *)JSONKeyPathsByPropertyKey; @optional -// Specifies how to convert a JSON value to the given property key. If -// reversible, the transformer will also be used to convert the property value -// back to JSON. -// -// If the receiver implements a `+JSONTransformer` method, MTLJSONAdapter -// will use the result of that method instead. -// -// Returns a value transformer, or nil if no transformation should be performed. +/// Specifies how to convert a JSON value to the given property key. If +/// reversible, the transformer will also be used to convert the property value +/// back to JSON. +/// +/// If the receiver implements a `+JSONTransformer` method, MTLJSONAdapter +/// will use the result of that method instead. +/// +/// Returns a value transformer, or nil if no transformation should be performed. + (NSValueTransformer *)JSONTransformerForKey:(NSString *)key; -// Overridden to parse the receiver as a different class, based on information -// in the provided dictionary. -// -// This is mostly useful for class clusters, where the abstract base class would -// be passed into -[MTLJSONAdapter initWithJSONDictionary:modelClass:], but -// a subclass should be instantiated instead. -// -// JSONDictionary - The JSON dictionary that will be parsed. -// -// Returns the class that should be parsed (which may be the receiver), or nil -// to abort parsing (e.g., if the data is invalid). +/// Overridden to parse the receiver as a different class, based on information +/// in the provided dictionary. +/// +/// This is mostly useful for class clusters, where the abstract base class would +/// be passed into -[MTLJSONAdapter initWithJSONDictionary:modelClass:], but +/// a subclass should be instantiated instead. +/// +/// JSONDictionary - The JSON dictionary that will be parsed. +/// +/// Returns the class that should be parsed (which may be the receiver), or nil +/// to abort parsing (e.g., if the data is invalid). + (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary; @end -// The domain for errors originating from MTLJSONAdapter. +/// The domain for errors originating from MTLJSONAdapter. extern NSString * const MTLJSONAdapterErrorDomain; -// +classForParsingJSONDictionary: returned nil for the given dictionary. +/// +classForParsingJSONDictionary: returned nil for the given dictionary. extern const NSInteger MTLJSONAdapterErrorNoClassFound; -// The provided JSONDictionary is not valid. +/// The provided JSONDictionary is not valid. extern const NSInteger MTLJSONAdapterErrorInvalidJSONDictionary; -// The model's implementation of +JSONKeyPathsByPropertyKey included a key which -// does not actually exist in +propertyKeys. +/// The model's implementation of +JSONKeyPathsByPropertyKey included a key which +/// does not actually exist in +propertyKeys. extern const NSInteger MTLJSONAdapterErrorInvalidJSONMapping; -// Converts a MTLModel object to and from a JSON dictionary. +/// Converts a MTLModel object to and from a JSON dictionary. @interface MTLJSONAdapter : NSObject -// The model object that the receiver was initialized with, or that the receiver -// parsed from a JSON dictionary. -@property (nonatomic, strong, readonly) MTLModel *model; - -// Attempts to parse a JSON dictionary into a model object. -// -// modelClass - The MTLModel subclass to attempt to parse from the JSON. -// This class must conform to . This -// argument must not be nil. -// JSONDictionary - A dictionary representing JSON data. This should match the -// format returned by NSJSONSerialization. If this argument is -// nil, the method returns nil. -// error - If not NULL, this may be set to an error that occurs during -// parsing or initializing an instance of `modelClass`. -// -// Returns an instance of `modelClass` upon success, or nil if a parsing error -// occurred. +/// Attempts to parse a JSON dictionary into a model object. +/// +/// modelClass - The MTLModel subclass to attempt to parse from the JSON. +/// This class must conform to . This +/// argument must not be nil. +/// JSONDictionary - A dictionary representing JSON data. This should match the +/// format returned by NSJSONSerialization. If this argument is +/// nil, the method returns nil. +/// error - If not NULL, this may be set to an error that occurs during +/// parsing or initializing an instance of `modelClass`. +/// +/// Returns an instance of `modelClass` upon success, or nil if a parsing error +/// occurred. + (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error; -// Attempts to parse an array of JSON dictionary objects into a model objects -// of a specific class. -// -// modelClass - The MTLModel subclass to attempt to parse from the JSON. This -// class must conform to . This argument must -// not be nil. -// JSONArray - A array of dictionaries representing JSON data. This should -// match the format returned by NSJSONSerialization. If this -// argument is nil, the method returns nil. -// error - If not NULL, this may be set to an error that occurs during -// parsing or initializing an any of the instances of -// `modelClass`. -// -// Returns an array of `modelClass` instances upon success, or nil if a parsing -// error occurred. +/// Attempts to parse an array of JSON dictionary objects into a model objects +/// of a specific class. +/// +/// modelClass - The MTLModel subclass to attempt to parse from the JSON. This +/// class must conform to . This argument must +/// not be nil. +/// JSONArray - A array of dictionaries representing JSON data. This should +/// match the format returned by NSJSONSerialization. If this +/// argument is nil, the method returns nil. +/// error - If not NULL, this may be set to an error that occurs during +/// parsing or initializing an any of the instances of +/// `modelClass`. +/// +/// Returns an array of `modelClass` instances upon success, or nil if a parsing +/// error occurred. + (NSArray *)modelsOfClass:(Class)modelClass fromJSONArray:(NSArray *)JSONArray error:(NSError **)error; -// Converts a model into a JSON representation. -// -// model - The model to use for JSON serialization. This argument must not be -// nil. -// -// Returns a JSON dictionary, or nil if a serialization error occurred. -+ (NSDictionary *)JSONDictionaryFromModel:(MTLModel *)model; +/// Converts a model into a JSON representation. +/// +/// model - The model to use for JSON serialization. This argument must not be +/// nil. +/// error - If not NULL, this may be set to an error that occurs during +/// serializing. +/// +/// Returns a JSON dictionary, or nil if a serialization error occurred. ++ (NSDictionary *)JSONDictionaryFromModel:(id)model error:(NSError **)error; -// Converts a array of models into a JSON representation. -// -// models - The array of models to use for JSON serialization. This argument -// must not be nil. -// -// Returns a JSON array, or nil if a serialization error occurred for any -// model. -+ (NSArray *)JSONArrayFromModels:(NSArray *)models; +/// Converts a array of models into a JSON representation. +/// +/// models - The array of models to use for JSON serialization. This argument +/// must not be nil. +/// error - If not NULL, this may be set to an error that occurs during +/// serializing. +/// +/// Returns a JSON array, or nil if a serialization error occurred for any +/// model. ++ (NSArray *)JSONArrayFromModels:(NSArray *)models error:(NSError **)error; -// Initializes the receiver by attempting to parse a JSON dictionary into -// a model object. -// -// JSONDictionary - A dictionary representing JSON data. This should match the -// format returned by NSJSONSerialization. If this argument is -// nil, the method returns nil and an error with code -// MTLJSONAdapterErrorInvalidJSONDictionary. -// modelClass - The MTLModel subclass to attempt to parse from the JSON. -// This class must conform to . This -// argument must not be nil. -// error - If not NULL, this may be set to an error that occurs during -// parsing or initializing an instance of `modelClass`. -// -// Returns an initialized adapter upon success, or nil if a parsing error -// occurred. -- (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass error:(NSError **)error; +/// Initializes the receiver with a given model class. +/// +/// modelClass - The MTLModel subclass to attempt to parse from the JSON and +/// back. This class must conform to . This +/// argument must not be nil. +/// +/// Returns an initialized adapter. +- (id)initWithModelClass:(Class)modelClass; -// Initializes the receiver with an existing model. -// -// model - The model to use for JSON serialization. This argument must not be -// nil. -- (id)initWithModel:(MTLModel *)model; +/// Deserializes a model from a JSON dictionary. +/// +/// The adapter will call -validate: on the model and consider it an error if the +/// validation fails. +/// +/// JSONDictionary - A dictionary representing JSON data. This should match the +/// format returned by NSJSONSerialization. This argument must +/// not be nil. +/// error - If not NULL, this may be set to an error that occurs during +/// deserializing or validation. +/// +/// Returns a model object, or nil if a deserialization error occurred or the +/// model did not validate successfully. +- (id)modelFromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error; -// Serializes the receiver's `model` into JSON. -// -// Returns a JSON dictionary, or nil if a serialization error occurred. -- (NSDictionary *)JSONDictionary; +/// Serializes a model into JSON. +/// +/// model - The model to use for JSON serialization. This argument must not be +/// nil. +/// error - If not NULL, this may be set to an error that occurs during +/// serializing. +/// +/// Returns a model object, or nil if a serialization error occurred. +- (NSDictionary *)JSONDictionaryFromModel:(id)model error:(NSError **)error; -// Looks up the JSON key path in the model's +propertyKeys. -// -// Subclasses may override this method to customize the adapter's seralizing -// behavior. You should not call this method directly. -// -// key - The property key to retrieve the corresponding JSON key path for. This -// argument must not be nil. -// -// Returns a key path to use, or nil to omit the property from JSON. -- (NSString *)JSONKeyPathForPropertyKey:(NSString *)key; +/// Filters the property keys used to serialize a given model. +/// +/// propertyKeys - The property keys for which `model` provides a mapping. +/// model - The model being serialized. +/// +/// Subclasses may override this method to determine which property keys should +/// be used when serializing `model`. For instance, this method can be used to +/// create more efficient updates of server-side resources. +/// +/// The default implementation simply returns `propertyKeys`. +/// +/// Returns a subset of propertyKeys that should be serialized for a given +/// model. +- (NSSet *)serializablePropertyKeys:(NSSet *)propertyKeys forModel:(id)model; + +/// An optional value transformer that should be used for properties of the given +/// class. +/// +/// A value transformer returned by the model's +JSONTransformerForKey: method +/// is given precedence over the one returned by this method. +/// +/// The default implementation invokes `+JSONTransformer` on the +/// receiver if it's implemented. It supports NSURL conversion through +/// +NSURLJSONTransformer. +/// +/// class - The class of the property to serialize. This property must not be +/// nil. +/// +/// Returns a value transformer or nil if no transformation should be used. ++ (NSValueTransformer *)transformerForModelPropertiesOfClass:(Class)class; + +/// A value transformer that should be used for a properties of the given +/// primitive type. +/// +/// If `objCType` matches @encode(id), the value transformer returned by +/// +transformerForModelPropertiesOfClass: is used instead. +/// +/// The default implementation transforms properties that match @encode(BOOL) +/// using the MTLBooleanValueTransformerName transformer. +/// +/// objCType - The type encoding for the value of this property. This is the type +/// as it would be returned by the @encode() directive. +/// +/// Returns a value transformer or nil if no transformation should be used. ++ (NSValueTransformer *)transformerForModelPropertiesOfObjCType:(const char *)objCType; @end +@interface MTLJSONAdapter (ValueTransformers) + +/// Creates a reversible transformer to convert a JSON dictionary into a MTLModel +/// object, and vice-versa. +/// +/// modelClass - The MTLModel subclass to attempt to parse from the JSON. This +/// class must conform to . This argument must +/// not be nil. +/// +/// Returns a reversible transformer which uses the class of the receiver for +/// transforming values back and forth. ++ (NSValueTransformer *)dictionaryTransformerWithModelClass:(Class)modelClass; + +/// Creates a reversible transformer to convert an array of JSON dictionaries +/// into an array of MTLModel objects, and vice-versa. +/// +/// modelClass - The MTLModel subclass to attempt to parse from each JSON +/// dictionary. This class must conform to . +/// This argument must not be nil. +/// +/// Returns a reversible transformer which uses the class of the receiver for +/// transforming array elements back and forth. ++ (NSValueTransformer *)arrayTransformerWithModelClass:(Class)modelClass; + +/// This value transformer is used by MTLJSONAdapter to automatically convert +/// NSURL properties to JSON strings and vice versa. ++ (NSValueTransformer *)NSURLJSONTransformer; + +@end + +@class MTLModel; + @interface MTLJSONAdapter (Deprecated) -+ (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary __attribute__((deprecated("Replaced by +modelOfClass:fromJSONDictionary:error:"))); -- (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass __attribute__((deprecated("Replaced by -initWithJSONDictionary:modelClass:error:"))); +@property (nonatomic, strong, readonly) id model __attribute__((unavailable("Replaced by -modelFromJSONDictionary:error:"))); + ++ (NSArray *)JSONArrayFromModels:(NSArray *)models __attribute__((deprecated("Replaced by +JSONArrayFromModels:error:"))); + ++ (NSDictionary *)JSONDictionaryFromModel:(MTLModel *)model __attribute__((deprecated("Replaced by +JSONDictionaryFromModel:error:"))); + +- (NSDictionary *)JSONDictionary __attribute__((unavailable("Replaced by -JSONDictionaryFromModel:error:"))); +- (NSString *)JSONKeyPathForPropertyKey:(NSString *)key __attribute__((unavailable("Replaced by -serializablePropertyKeys:forModel:"))); +- (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass error:(NSError **)error __attribute__((unavailable("Replaced by -initWithModelClass:"))); +- (id)initWithModel:(id)model __attribute__((unavailable("Replaced by -initWithModelClass:"))); +- (NSDictionary *)serializeToJSONDictionary:(NSError **)error __attribute__((unavailable("Replaced by -JSONDictionaryFromModel:error:"))); @end diff --git a/Pods/Mantle/Mantle/MTLJSONAdapter.m b/Pods/Mantle/Mantle/MTLJSONAdapter.m index 9872921..71e7ef0 100644 --- a/Pods/Mantle/Mantle/MTLJSONAdapter.m +++ b/Pods/Mantle/Mantle/MTLJSONAdapter.m @@ -6,9 +6,18 @@ // Copyright (c) 2013 GitHub. All rights reserved. // +#import + +#import "NSDictionary+MTLJSONKeyPath.h" + +#import "EXTRuntimeExtensions.h" +#import "EXTScope.h" #import "MTLJSONAdapter.h" #import "MTLModel.h" +#import "MTLTransformerErrorHandling.h" #import "MTLReflection.h" +#import "NSValueTransformer+MTLPredefinedTransformerAdditions.h" +#import "MTLValueTransformer.h" NSString * const MTLJSONAdapterErrorDomain = @"MTLJSONAdapterErrorDomain"; const NSInteger MTLJSONAdapterErrorNoClassFound = 2; @@ -30,12 +39,33 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter // A cached copy of the return value of +JSONKeyPathsByPropertyKey. @property (nonatomic, copy, readonly) NSDictionary *JSONKeyPathsByPropertyKey; -// Looks up the NSValueTransformer that should be used for the given key. +// A cached copy of the return value of -valueTransformersForModelClass: +@property (nonatomic, copy, readonly) NSDictionary *valueTransformersByPropertyKey; + +// Used to cache the JSON adapters returned by -JSONAdapterForModelClass:error:. +@property (nonatomic, strong, readonly) NSMapTable *JSONAdaptersByModelClass; + +// If +classForParsingJSONDictionary: returns a model class different from the +// one this adapter was initialized with, use this method to obtain a cached +// instance of a suitable adapter instead. // -// key - The property key to transform from or to. This argument must not be nil. +// modelClass - The class from which to parse the JSON. This class must conform +// to . This argument must not be nil. +// error - If not NULL, this may be set to an error that occurs during +// initializing the adapter. // -// Returns a transformer to use, or nil to not transform the property. -- (NSValueTransformer *)JSONTransformerForKey:(NSString *)key; +// Returns a JSON adapter for modelClass, creating one of necessary. If no +// adapter could be created, nil is returned. +- (MTLJSONAdapter *)JSONAdapterForModelClass:(Class)modelClass error:(NSError **)error; + +// Collect all value transformers needed for a given class. +// +// modelClass - The class from which to parse the JSON. This class must conform +// to . This argument must not be nil. +// +// Returns a dictionary with the properties of modelClass that need +// transformation as keys and the value transformers as values. ++ (NSDictionary *)valueTransformersForModelClass:(Class)modelClass; @end @@ -44,8 +74,9 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter #pragma mark Convenience methods + (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error { - MTLJSONAdapter *adapter = [[self alloc] initWithJSONDictionary:JSONDictionary modelClass:modelClass error:error]; - return adapter.model; + MTLJSONAdapter *adapter = [[self alloc] initWithModelClass:modelClass]; + + return [adapter modelFromJSONDictionary:JSONDictionary error:error]; } + (NSArray *)modelsOfClass:(Class)modelClass fromJSONArray:(NSArray *)JSONArray error:(NSError **)error { @@ -65,25 +96,26 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter MTLModel *model = [self modelOfClass:modelClass fromJSONDictionary:JSONDictionary error:error]; if (model == nil) return nil; - + [models addObject:model]; } - + return models; } -+ (NSDictionary *)JSONDictionaryFromModel:(MTLModel *)model { - MTLJSONAdapter *adapter = [[self alloc] initWithModel:model]; - return adapter.JSONDictionary; ++ (NSDictionary *)JSONDictionaryFromModel:(id)model error:(NSError **)error { + MTLJSONAdapter *adapter = [[self alloc] initWithModelClass:model.class]; + + return [adapter JSONDictionaryFromModel:model error:error]; } -+ (NSArray *)JSONArrayFromModels:(NSArray *)models { ++ (NSArray *)JSONArrayFromModels:(NSArray *)models error:(NSError **)error { NSParameterAssert(models != nil); NSParameterAssert([models isKindOfClass:NSArray.class]); NSMutableArray *JSONArray = [NSMutableArray arrayWithCapacity:models.count]; for (MTLModel *model in models) { - NSDictionary *JSONDictionary = [self JSONDictionaryFromModel:model]; + NSDictionary *JSONDictionary = [self JSONDictionaryFromModel:model error:error]; if (JSONDictionary == nil) return nil; [JSONArray addObject:JSONDictionary]; @@ -95,29 +127,139 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter #pragma mark Lifecycle - (id)init { - NSAssert(NO, @"%@ must be initialized with a JSON dictionary or model object", self.class); + NSAssert(NO, @"%@ must be initialized with a model class", self.class); return nil; } -- (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass error:(NSError **)error { +- (id)initWithModelClass:(Class)modelClass { NSParameterAssert(modelClass != nil); - NSParameterAssert([modelClass isSubclassOfClass:MTLModel.class]); NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]); - if (JSONDictionary == nil || ![JSONDictionary isKindOfClass:NSDictionary.class]) { - if (error != NULL) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Missing JSON dictionary", @""), - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"%@ could not be created because an invalid JSON dictionary was provided: %@", @""), NSStringFromClass(modelClass), JSONDictionary.class], - }; - *error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorInvalidJSONDictionary userInfo:userInfo]; + self = [super init]; + if (self == nil) return nil; + + _modelClass = modelClass; + + _JSONKeyPathsByPropertyKey = [modelClass JSONKeyPathsByPropertyKey]; + + NSSet *propertyKeys = [self.modelClass propertyKeys]; + + for (NSString *mappedPropertyKey in _JSONKeyPathsByPropertyKey) { + if (![propertyKeys containsObject:mappedPropertyKey]) { + NSAssert(NO, @"%@ is not a property of %@.", mappedPropertyKey, modelClass); + return nil; + } + + id value = _JSONKeyPathsByPropertyKey[mappedPropertyKey]; + + if ([value isKindOfClass:NSArray.class]) { + for (NSString *keyPath in value) { + if ([keyPath isKindOfClass:NSString.class]) continue; + + NSAssert(NO, @"%@ must either map to a JSON key path or a JSON array of key paths, got: %@.", mappedPropertyKey, value); + return nil; + } + } else if (![value isKindOfClass:NSString.class]) { + NSAssert(NO, @"%@ must either map to a JSON key path or a JSON array of key paths, got: %@.",mappedPropertyKey, value); + return nil; } - return nil; } - if ([modelClass respondsToSelector:@selector(classForParsingJSONDictionary:)]) { - modelClass = [modelClass classForParsingJSONDictionary:JSONDictionary]; - if (modelClass == nil) { + _valueTransformersByPropertyKey = [self.class valueTransformersForModelClass:modelClass]; + + _JSONAdaptersByModelClass = [NSMapTable strongToStrongObjectsMapTable]; + + return self; +} + +#pragma mark Serialization + +- (NSDictionary *)JSONDictionaryFromModel:(id)model error:(NSError **)error { + NSParameterAssert(model != nil); + NSParameterAssert([model isKindOfClass:self.modelClass]); + + if (self.modelClass != model.class) { + MTLJSONAdapter *otherAdapter = [self JSONAdapterForModelClass:model.class error:error]; + + return [otherAdapter JSONDictionaryFromModel:model error:error]; + } + + NSSet *propertyKeysToSerialize = [self serializablePropertyKeys:[NSSet setWithArray:self.JSONKeyPathsByPropertyKey.allKeys] forModel:model]; + + NSDictionary *dictionaryValue = [model.dictionaryValue dictionaryWithValuesForKeys:propertyKeysToSerialize.allObjects]; + NSMutableDictionary *JSONDictionary = [[NSMutableDictionary alloc] initWithCapacity:dictionaryValue.count]; + + __block BOOL success = YES; + __block NSError *tmpError = nil; + + [dictionaryValue enumerateKeysAndObjectsUsingBlock:^(NSString *propertyKey, id value, BOOL *stop) { + id JSONKeyPaths = self.JSONKeyPathsByPropertyKey[propertyKey]; + + if (JSONKeyPaths == nil) return; + + NSValueTransformer *transformer = self.valueTransformersByPropertyKey[propertyKey]; + if ([transformer.class allowsReverseTransformation]) { + // Map NSNull -> nil for the transformer, and then back for the + // dictionaryValue we're going to insert into. + if ([value isEqual:NSNull.null]) value = nil; + + if ([transformer respondsToSelector:@selector(reverseTransformedValue:success:error:)]) { + id errorHandlingTransformer = (id)transformer; + + value = [errorHandlingTransformer reverseTransformedValue:value success:&success error:&tmpError]; + + if (!success) { + *stop = YES; + return; + } + } else { + value = [transformer reverseTransformedValue:value] ?: NSNull.null; + } + } + + void (^createComponents)(id, NSString *) = ^(id obj, NSString *keyPath) { + NSArray *keyPathComponents = [keyPath componentsSeparatedByString:@"."]; + + // Set up dictionaries at each step of the key path. + for (NSString *component in keyPathComponents) { + if ([obj valueForKey:component] == nil) { + // Insert an empty mutable dictionary at this spot so that we + // can set the whole key path afterward. + [obj setValue:[NSMutableDictionary dictionary] forKey:component]; + } + + obj = [obj valueForKey:component]; + } + }; + + if ([JSONKeyPaths isKindOfClass:NSString.class]) { + createComponents(JSONDictionary, JSONKeyPaths); + + [JSONDictionary setValue:value forKeyPath:JSONKeyPaths]; + } + + if ([JSONKeyPaths isKindOfClass:NSArray.class]) { + for (NSString *JSONKeyPath in JSONKeyPaths) { + createComponents(JSONDictionary, JSONKeyPath); + + [JSONDictionary setValue:value[JSONKeyPath] forKeyPath:JSONKeyPath]; + } + } + }]; + + if (success) { + return JSONDictionary; + } else { + if (error != NULL) *error = tmpError; + + return nil; + } +} + +- (id)modelFromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error { + if ([self.modelClass respondsToSelector:@selector(classForParsingJSONDictionary:)]) { + Class class = [self.modelClass classForParsingJSONDictionary:JSONDictionary]; + if (class == nil) { if (error != NULL) { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not parse JSON", @""), @@ -130,69 +272,70 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter return nil; } - NSAssert([modelClass isSubclassOfClass:MTLModel.class], @"Class %@ returned from +classForParsingJSONDictionary: is not a subclass of MTLModel", modelClass); - NSAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)], @"Class %@ returned from +classForParsingJSONDictionary: does not conform to ", modelClass); + if (class != self.modelClass) { + NSAssert([class conformsToProtocol:@protocol(MTLJSONSerializing)], @"Class %@ returned from +classForParsingJSONDictionary: does not conform to ", class); + + MTLJSONAdapter *otherAdapter = [self JSONAdapterForModelClass:class error:error]; + + return [otherAdapter modelFromJSONDictionary:JSONDictionary error:error]; + } } - self = [super init]; - if (self == nil) return nil; - - _modelClass = modelClass; - _JSONKeyPathsByPropertyKey = [[modelClass JSONKeyPathsByPropertyKey] copy]; - NSMutableDictionary *dictionaryValue = [[NSMutableDictionary alloc] initWithCapacity:JSONDictionary.count]; - NSSet *propertyKeys = [self.modelClass propertyKeys]; + for (NSString *propertyKey in [self.modelClass propertyKeys]) { + id JSONKeyPaths = self.JSONKeyPathsByPropertyKey[propertyKey]; - for (NSString *mappedPropertyKey in self.JSONKeyPathsByPropertyKey) { - if (![propertyKeys containsObject:mappedPropertyKey]) { - NSAssert(NO, @"%@ is not a property of %@.", mappedPropertyKey, modelClass); - return nil; - } - - id value = self.JSONKeyPathsByPropertyKey[mappedPropertyKey]; - - if (![value isKindOfClass:NSString.class] && value != NSNull.null) { - NSAssert(NO, @"%@ must either map to a JSON key path or NSNull, got: %@.",mappedPropertyKey, value); - return nil; - } - } - - for (NSString *propertyKey in propertyKeys) { - NSString *JSONKeyPath = [self JSONKeyPathForPropertyKey:propertyKey]; - if (JSONKeyPath == nil) continue; + if (JSONKeyPaths == nil) continue; id value; - @try { - value = [JSONDictionary valueForKeyPath:JSONKeyPath]; - } @catch (NSException *ex) { - if (error != NULL) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid JSON dictionary", nil), - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"%1$@ could not be parsed because an invalid JSON dictionary was provided for key path \"%2$@\"", nil), modelClass, JSONKeyPath], - MTLJSONAdapterThrownExceptionErrorKey: ex - }; - *error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorInvalidJSONDictionary userInfo:userInfo]; + if ([JSONKeyPaths isKindOfClass:NSArray.class]) { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + + for (NSString *keyPath in JSONKeyPaths) { + BOOL success; + id value = [JSONDictionary mtl_valueForJSONKeyPath:keyPath success:&success error:error]; + + if (!success) return nil; + + if (value != nil) dictionary[keyPath] = value; } - return nil; + value = dictionary; + } else { + BOOL success; + value = [JSONDictionary mtl_valueForJSONKeyPath:JSONKeyPaths success:&success error:error]; + + if (!success) return nil; } if (value == nil) continue; @try { - NSValueTransformer *transformer = [self JSONTransformerForKey:propertyKey]; + NSValueTransformer *transformer = self.valueTransformersByPropertyKey[propertyKey]; if (transformer != nil) { // Map NSNull -> nil for the transformer, and then back for the // dictionary we're going to insert into. if ([value isEqual:NSNull.null]) value = nil; - value = [transformer transformedValue:value] ?: NSNull.null; + + if ([transformer respondsToSelector:@selector(transformedValue:success:error:)]) { + id errorHandlingTransformer = (id)transformer; + + BOOL success = YES; + value = [errorHandlingTransformer transformedValue:value success:&success error:error]; + + if (!success) return nil; + } else { + value = [transformer transformedValue:value]; + } + + if (value == nil) value = NSNull.null; } dictionaryValue[propertyKey] = value; } @catch (NSException *ex) { - NSLog(@"*** Caught exception %@ parsing JSON key path \"%@\" from: %@", ex, JSONKeyPath, JSONDictionary); + NSLog(@"*** Caught exception %@ parsing JSON key path \"%@\" from: %@", ex, JSONKeyPaths, JSONDictionary); // Fail fast in Debug builds. #if DEBUG @@ -213,96 +356,284 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter } } - _model = [self.modelClass modelWithDictionary:dictionaryValue error:error]; - if (_model == nil) return nil; + id model = [self.modelClass modelWithDictionary:dictionaryValue error:error]; - return self; + return [model validate:error] ? model : nil; } -- (id)initWithModel:(MTLModel *)model { - NSParameterAssert(model != nil); ++ (NSDictionary *)valueTransformersForModelClass:(Class)modelClass { + NSParameterAssert(modelClass != nil); + NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]); - self = [super init]; - if (self == nil) return nil; + NSMutableDictionary *result = [NSMutableDictionary dictionary]; - _model = model; - _modelClass = model.class; - _JSONKeyPathsByPropertyKey = [[model.class JSONKeyPathsByPropertyKey] copy]; + for (NSString *key in [modelClass propertyKeys]) { + SEL selector = MTLSelectorWithKeyPattern(key, "JSONTransformer"); + if ([modelClass respondsToSelector:selector]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[modelClass methodSignatureForSelector:selector]]; + invocation.target = modelClass; + invocation.selector = selector; + [invocation invoke]; - return self; -} + __unsafe_unretained id transformer = nil; + [invocation getReturnValue:&transformer]; -#pragma mark Serialization + if (transformer != nil) result[key] = transformer; -- (NSDictionary *)JSONDictionary { - NSDictionary *dictionaryValue = self.model.dictionaryValue; - NSMutableDictionary *JSONDictionary = [[NSMutableDictionary alloc] initWithCapacity:dictionaryValue.count]; - - [dictionaryValue enumerateKeysAndObjectsUsingBlock:^(NSString *propertyKey, id value, BOOL *stop) { - NSString *JSONKeyPath = [self JSONKeyPathForPropertyKey:propertyKey]; - if (JSONKeyPath == nil) return; - - NSValueTransformer *transformer = [self JSONTransformerForKey:propertyKey]; - if ([transformer.class allowsReverseTransformation]) { - // Map NSNull -> nil for the transformer, and then back for the - // dictionaryValue we're going to insert into. - if ([value isEqual:NSNull.null]) value = nil; - value = [transformer reverseTransformedValue:value] ?: NSNull.null; + continue; } - NSArray *keyPathComponents = [JSONKeyPath componentsSeparatedByString:@"."]; + if ([modelClass respondsToSelector:@selector(JSONTransformerForKey:)]) { + NSValueTransformer *transformer = [modelClass JSONTransformerForKey:key]; - // Set up dictionaries at each step of the key path. - id obj = JSONDictionary; - for (NSString *component in keyPathComponents) { - if ([obj valueForKey:component] == nil) { - // Insert an empty mutable dictionary at this spot so that we - // can set the whole key path afterward. - [obj setValue:[NSMutableDictionary dictionary] forKey:component]; + if (transformer != nil) result[key] = transformer; + + continue; + } + + objc_property_t property = class_getProperty(modelClass, key.UTF8String); + + if (property == NULL) continue; + + mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); + @onExit { + free(attributes); + }; + + NSValueTransformer *transformer = nil; + + if (*(attributes->type) == *(@encode(id))) { + Class propertyClass = attributes->objectClass; + + if (propertyClass != nil) { + transformer = [self transformerForModelPropertiesOfClass:propertyClass]; } - obj = [obj valueForKey:component]; + if (transformer == nil) transformer = [NSValueTransformer mtl_validatingTransformerForClass:NSObject.class]; + } else { + transformer = [self transformerForModelPropertiesOfObjCType:attributes->type] ?: [NSValueTransformer mtl_validatingTransformerForClass:NSValue.class]; } - [JSONDictionary setValue:value forKeyPath:JSONKeyPath]; - }]; - - return JSONDictionary; -} - -- (NSValueTransformer *)JSONTransformerForKey:(NSString *)key { - NSParameterAssert(key != nil); - - SEL selector = MTLSelectorWithKeyPattern(key, "JSONTransformer"); - if ([self.modelClass respondsToSelector:selector]) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self.modelClass methodSignatureForSelector:selector]]; - invocation.target = self.modelClass; - invocation.selector = selector; - [invocation invoke]; - - __unsafe_unretained id result = nil; - [invocation getReturnValue:&result]; - return result; + if (transformer != nil) result[key] = transformer; } - if ([self.modelClass respondsToSelector:@selector(JSONTransformerForKey:)]) { - return [self.modelClass JSONTransformerForKey:key]; + return result; +} + +- (MTLJSONAdapter *)JSONAdapterForModelClass:(Class)modelClass error:(NSError **)error { + NSParameterAssert(modelClass != nil); + NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]); + + @synchronized(self) { + MTLJSONAdapter *result = [self.JSONAdaptersByModelClass objectForKey:modelClass]; + + if (result != nil) return result; + + result = [[MTLJSONAdapter alloc] initWithModelClass:modelClass]; + + if (result != nil) { + [self.JSONAdaptersByModelClass setObject:result forKey:modelClass]; + } + + return result; + } +} + +- (NSSet *)serializablePropertyKeys:(NSSet *)propertyKeys forModel:(id)model { + return propertyKeys; +} + ++ (NSValueTransformer *)transformerForModelPropertiesOfClass:(Class)modelClass { + NSParameterAssert(modelClass != nil); + + SEL selector = MTLSelectorWithKeyPattern(NSStringFromClass(modelClass), "JSONTransformer"); + if (![self respondsToSelector:selector]) return nil; + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]]; + invocation.target = self; + invocation.selector = selector; + [invocation invoke]; + + __unsafe_unretained id result = nil; + [invocation getReturnValue:&result]; + return result; +} + ++ (NSValueTransformer *)transformerForModelPropertiesOfObjCType:(const char *)objCType { + NSParameterAssert(objCType != NULL); + + if (strcmp(objCType, @encode(BOOL)) == 0) { + return [NSValueTransformer valueTransformerForName:MTLBooleanValueTransformerName]; } return nil; } -- (NSString *)JSONKeyPathForPropertyKey:(NSString *)key { - NSParameterAssert(key != nil); +@end - id JSONKeyPath = self.JSONKeyPathsByPropertyKey[key]; - if ([JSONKeyPath isEqual:NSNull.null]) return nil; +@implementation MTLJSONAdapter (ValueTransformers) - if (JSONKeyPath == nil) { - return key; - } else { - return JSONKeyPath; - } ++ (NSValueTransformer *)dictionaryTransformerWithModelClass:(Class)modelClass { + NSParameterAssert([modelClass isSubclassOfClass:MTLModel.class]); + NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]); + + return [MTLValueTransformer + transformerUsingForwardBlock:^ id (id JSONDictionary, BOOL *success, NSError **error) { + if (JSONDictionary == nil) return nil; + + if (![JSONDictionary isKindOfClass:NSDictionary.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON dictionary to model object", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSDictionary, got: %@", @""), JSONDictionary], + MTLTransformerErrorHandlingInputValueErrorKey : JSONDictionary + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + id model = [self modelOfClass:modelClass fromJSONDictionary:JSONDictionary error:error]; + if (model == nil) { + *success = NO; + } + + return model; + } + reverseBlock:^ NSDictionary * (id model, BOOL *success, NSError **error) { + if (model == nil) return nil; + + if (![model isKindOfClass:MTLModel.class] || ![model conformsToProtocol:@protocol(MTLJSONSerializing)]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert model object to JSON dictionary", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected a MTLModel object conforming to , got: %@.", @""), model], + MTLTransformerErrorHandlingInputValueErrorKey : model + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSDictionary *result = [self JSONDictionaryFromModel:model error:error]; + if (result == nil) { + *success = NO; + } + + return result; + }]; +} + ++ (NSValueTransformer *)arrayTransformerWithModelClass:(Class)modelClass { + id dictionaryTransformer = [self dictionaryTransformerWithModelClass:modelClass]; + + return [MTLValueTransformer + transformerUsingForwardBlock:^ id (NSArray *dictionaries, BOOL *success, NSError **error) { + if (dictionaries == nil) return nil; + + if (![dictionaries isKindOfClass:NSArray.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), dictionaries], + MTLTransformerErrorHandlingInputValueErrorKey : dictionaries + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count]; + for (id JSONDictionary in dictionaries) { + if (JSONDictionary == NSNull.null) { + [models addObject:NSNull.null]; + continue; + } + + if (![JSONDictionary isKindOfClass:NSDictionary.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSDictionary or an NSNull, got: %@.", @""), JSONDictionary], + MTLTransformerErrorHandlingInputValueErrorKey : JSONDictionary + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + id model = [dictionaryTransformer transformedValue:JSONDictionary success:success error:error]; + + if (*success == NO) return nil; + + if (model == nil) continue; + + [models addObject:model]; + } + + return models; + } + reverseBlock:^ id (NSArray *models, BOOL *success, NSError **error) { + if (models == nil) return nil; + + if (![models isKindOfClass:NSArray.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert model array to JSON array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), models], + MTLTransformerErrorHandlingInputValueErrorKey : models + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count]; + for (id model in models) { + if (model == NSNull.null) { + [dictionaries addObject:NSNull.null]; + continue; + } + + if (![model isKindOfClass:MTLModel.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected a MTLModel or an NSNull, got: %@.", @""), model], + MTLTransformerErrorHandlingInputValueErrorKey : model + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSDictionary *dict = [dictionaryTransformer reverseTransformedValue:model success:success error:error]; + + if (*success == NO) return nil; + + if (dict == nil) continue; + + [dictionaries addObject:dict]; + } + + return dictionaries; + }]; +} + ++ (NSValueTransformer *)NSURLJSONTransformer { + return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName]; } @end @@ -312,12 +643,12 @@ static NSString * const MTLJSONAdapterThrownExceptionErrorKey = @"MTLJSONAdapter #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" -+ (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary { - return [self modelOfClass:modelClass fromJSONDictionary:JSONDictionary error:NULL]; ++ (NSArray *)JSONArrayFromModels:(NSArray *)models { + return [self JSONArrayFromModels:models error:NULL]; } -- (id)initWithJSONDictionary:(NSDictionary *)JSONDictionary modelClass:(Class)modelClass { - return [self initWithJSONDictionary:JSONDictionary modelClass:modelClass error:NULL]; ++ (NSDictionary *)JSONDictionaryFromModel:(MTLModel *)model { + return [self JSONDictionaryFromModel:model error:NULL]; } #pragma clang diagnostic pop diff --git a/Pods/Mantle/Mantle/MTLManagedObjectAdapter.h b/Pods/Mantle/Mantle/MTLManagedObjectAdapter.h deleted file mode 100644 index 11b2bcf..0000000 --- a/Pods/Mantle/Mantle/MTLManagedObjectAdapter.h +++ /dev/null @@ -1,215 +0,0 @@ -// -// MTLManagedObjectAdapter.h -// Mantle -// -// Created by Justin Spahr-Summers on 2013-03-29. -// Copyright (c) 2013 GitHub. All rights reserved. -// - -#import - -@class MTLModel; - -// A MTLModel object that supports being serialized to and from Core Data as an -// NSManagedObject. -@protocol MTLManagedObjectSerializing -@required - -// The name of the Core Data entity that the receiver serializes to and -// deserializes from. -// -// This method must not return nil. -+ (NSString *)managedObjectEntityName; - -// Specifies how to map property keys to different keys on the receiver's -// +managedObjectEntity. -// -// Entity attributes will be mapped to and from the receiver's properties using -// +entityAttributeTransformerForKey:. Entity relationships will be mapped to -// and from MTLModel objects using +relationshipModelClassesByPropertyKey. -// Fetched properties are not supported. -// -// Subclasses overriding this method should combine their values with those of -// `super`. -// -// Any property keys not present in the dictionary are assumed to match the -// entity key that should be used. Any keys associated with NSNull will not -// participate in managed object serialization. -// -// Returns a dictionary mapping property keys to entity keys (as strings) or -// NSNull values. -+ (NSDictionary *)managedObjectKeysByPropertyKey; - -@optional - -// Specifies a set of property keys used by the adapter to check for an already -// existing managed object when converting the MTLModel to its related -// NSManagedObject. -// -// The adapter will first map any keys provided by this method to the correct -// keys in managedObjectKeysByPropertyKey. -// -// The adapter will then perform a fetch request in the provided context for a -// managed object that matches the MTLModel's managedObjectEntityName and has -// equal values set for the property keys on the MTLModel. -// -// The managed object returned by the fetch request will then be set with all -// values from the MTLModel that the managed object is being converted from. -// -// If a property value of our MTLModel is yet another MTLModel which needs to be -// converted to a managed object, the class for that MTLModel can also implement -// this method to perform its own uniqing. -// -// For example: -// 1. An MTLModel subclass has id_number = 10. -// 2. An NSManagedObject accessible to the adapter's context has idnumber = 10. -// 3. managedObjectKeysByPropertyKey returns @{@"id_number" : @"idnumber"} -// 4. propertyKeysForManagedObjectUniquing returns -// [NSSet setWithObject:@"id_number"]; -// 5. Then our fetch request may return this managed object (or another managed -// object with idnumber = 10). -// -// NOTE: If multiple managed objects follow the same uniquing criteria only one -// of them will be set with our MTLModel's values. -+ (NSSet *)propertyKeysForManagedObjectUniquing; - -// Specifies how to convert the given property key to a managed object -// attribute. If reversible, the transformer will also be used to convert the -// managed object attribute back to the property. -// -// If the receiver implements a `+EntityAttributeTransformer` method, -// MTLManagedObjectAdapter will use the result of that method instead. -// -// Returns a value transformer, or nil if no transformation should be performed. -+ (NSValueTransformer *)entityAttributeTransformerForKey:(NSString *)key; - -// Specifies the MTLModel subclasses that should be deserialized to the -// receiver's property keys when a property key corresponds to an entity -// relationship. -// -// In other words, the dictionary returned by this method is used to decode -// managed object relationships into MTLModels (or NSArrays or NSSets thereof) -// set on the receiver. -// -// If a property key is omitted from the returned dictionary, but present in -// +managedObjectKeysByPropertyKey, and the receiver's +managedObjectEntity has -// a relationship at the corresponding key, an exception will be thrown during -// deserialization. -// -// Subclasses overriding this method should combine their values with those of -// `super`. -// -// Returns a dictionary mapping property keys to the Class objects that should -// be used. -+ (NSDictionary *)relationshipModelClassesByPropertyKey; - -// Overridden to deserialize a different class instead of the receiver, based on -// information in the provided object. -// -// This is mostly useful for class clusters, where the abstract base class would -// be passed into +[MTLManagedObjectAdapter -// modelOfClass:fromManagedObject:error:], but a subclass should be instantiated -// instead. -// -// managedObject - The object that will be deserialized. -// -// Returns the class that should be instantiated (which may be the receiver), or -// nil to abort parsing (e.g., if the data is invalid). -+ (Class)classForDeserializingManagedObject:(NSManagedObject *)managedObject; - -// Overriden when merging the value of the given key on the receiver with the -// value of the same key from the given `NSManagedObject` requires custom -// handling. -// -// By default, this method is not implemented, and precedence will be given to -// the value of the receiving model implicitly. -// -// When implemented, this method is called when an existing `NSManagedObject` -// is found for the receiving model, before updating the `NSManagedObject`'s -// properties. -// -// When implementing, you should use `+managedObjectKeysByPropertyKey` to map -// the given `key` to the appropriate `NSManagedObject` property. -- (void)mergeValueForKey:(NSString *)key fromManagedObject:(NSManagedObject *)managedObject; - -// Overriden when merging values on the receiver with the given -// `NSManagedObject` requires custom handling. -// -// By default, this method is not implemented, and precedence will be given to -// the values of the receiving model implicitly. -// -// When implemented, this method is called when an existing `NSManagedObject` -// is found for the receiving model, before updating the `NSManagedObject`'s -// properties. -// -// When implementing, you should use `+managedObjectKeysByPropertyKey` to map -// the given `key` to the appropriate `NSManagedObject` property. -// -// If you have also implemented `mergeValueForKey:fromManagedObject:` you have -// to make sure to call `mergeValueForKey:fromManagedObject:` from this method -// when appropriate. -- (void)mergeValuesForKeysFromManagedObject:(NSManagedObject *)managedObject; - -@end - -// The domain for errors originating from MTLManagedObjectAdapter. -extern NSString * const MTLManagedObjectAdapterErrorDomain; - -// +classForDeserializingManagedObject: returned nil for the given object. -extern const NSInteger MTLManagedObjectAdapterErrorNoClassFound; - -// An NSManagedObject failed to initialize. -extern const NSInteger MTLManagedObjectAdapterErrorInitializationFailed; - -// The managed object key specified by +managedObjectKeysByPropertyKey does not -// exist in the NSEntityDescription. -extern const NSInteger MTLManagedObjectAdapterErrorInvalidManagedObjectKey; - -// The managed object property specified has a type that isn't supported by -// MTLManagedObjectAdapter. -extern const NSInteger MTLManagedObjectAdapterErrorUnsupportedManagedObjectPropertyType; - -// The fetch request to find an existing managed object based on -// `+propertyKeysForManagedObjectUniquing` failed. -extern const NSInteger MTLManagedObjectAdapterErrorUniqueFetchRequestFailed; - -// A MTLModel property cannot be serialized to or deserialized from an -// NSManagedObject relationship. -// -// For a to-one relationship, this means that the property does not contain -// a MTLModel, or the MTLModel does not conform to . -// -// For a to-many relationship, this means that the property does not contain an -// NSArray or NSSet of MTLModel instances. -extern const NSInteger MTLManagedObjectAdapterErrorUnsupportedRelationshipClass; - -// The model's implementation of +managedObjectKeysByPropertyKey included a key -// which does not actually exist in +propertyKeys. -extern const NSInteger MTLManagedObjectAdapterErrorInvalidManagedObjectMapping; - -// Converts a MTLModel object to and from an NSManagedObject. -@interface MTLManagedObjectAdapter : NSObject - -// Attempts to deserialize an NSManagedObject into a MTLModel object. -// -// modelClass - The MTLModel subclass to return. This class must conform to -// . This argument must not be nil. -// managedObject - The managed object to deserialize. If this argument is nil, -// the method returns nil. -// error - If not NULL, this may be set to an error that occurs during -// deserialization or initializing an instance of `modelClass`. -// -// Returns an instance of `modelClass` upon success, or nil if an error -// occurred. -+ (id)modelOfClass:(Class)modelClass fromManagedObject:(NSManagedObject *)managedObject error:(NSError **)error; - -// Serializes a MTLModel into an NSManagedObject. -// -// model - The model object to serialize. This argument must not be nil. -// context - The context into which to insert the created managed object. This -// argument must not be nil. -// error - If not NULL, this may be set to an error that occurs during -// serialization or insertion. -+ (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context error:(NSError **)error; - -@end diff --git a/Pods/Mantle/Mantle/MTLManagedObjectAdapter.m b/Pods/Mantle/Mantle/MTLManagedObjectAdapter.m deleted file mode 100644 index 84235c1..0000000 --- a/Pods/Mantle/Mantle/MTLManagedObjectAdapter.m +++ /dev/null @@ -1,645 +0,0 @@ -// -// MTLManagedObjectAdapter.m -// Mantle -// -// Created by Justin Spahr-Summers on 2013-03-29. -// Copyright (c) 2013 GitHub. All rights reserved. -// - -#import "MTLManagedObjectAdapter.h" -#import "EXTScope.h" -#import "MTLModel.h" -#import "MTLReflection.h" -#import "NSArray+MTLManipulationAdditions.h" - -NSString * const MTLManagedObjectAdapterErrorDomain = @"MTLManagedObjectAdapterErrorDomain"; -const NSInteger MTLManagedObjectAdapterErrorNoClassFound = 2; -const NSInteger MTLManagedObjectAdapterErrorInitializationFailed = 3; -const NSInteger MTLManagedObjectAdapterErrorInvalidManagedObjectKey = 4; -const NSInteger MTLManagedObjectAdapterErrorUnsupportedManagedObjectPropertyType = 5; -const NSInteger MTLManagedObjectAdapterErrorUnsupportedRelationshipClass = 6; -const NSInteger MTLManagedObjectAdapterErrorUniqueFetchRequestFailed = 7; -const NSInteger MTLManagedObjectAdapterErrorInvalidManagedObjectMapping = 8; - -// Performs the given block in the context's queue, if it has one. -static id performInContext(NSManagedObjectContext *context, id (^block)(void)) { - if (context.concurrencyType == NSConfinementConcurrencyType) { - return block(); - } - - __block id result = nil; - [context performBlockAndWait:^{ - result = block(); - }]; - - return result; -} - -@interface MTLManagedObjectAdapter () - -// The MTLModel subclass being serialized or deserialized. -@property (nonatomic, strong, readonly) Class modelClass; - -// A cached copy of the return value of +managedObjectKeysByPropertyKey. -@property (nonatomic, copy, readonly) NSDictionary *managedObjectKeysByPropertyKey; - -// A cached copy of the return value of +relationshipModelClassesByPropertyKey. -@property (nonatomic, copy, readonly) NSDictionary *relationshipModelClassesByPropertyKey; - -// Initializes the receiver to serialize or deserialize a MTLModel of the given -// class. -- (id)initWithModelClass:(Class)modelClass; - -// Invoked from +modelOfClass:fromManagedObject:processedObjects:error: after -// the receiver's properties have been initialized. -- (id)modelFromManagedObject:(NSManagedObject *)managedObject processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error; - -// Performs the actual work of deserialization. This method is also invoked when -// processing relationships, to create a new adapter (if needed) to handle them. -// -// `processedObjects` is a dictionary mapping NSManagedObjects to the MTLModels -// that have been created so far. It should remain alive for the full process -// of deserializing the top-level managed object. -+ (id)modelOfClass:(Class)modelClass fromManagedObject:(NSManagedObject *)managedObject processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error; - -// Invoked from -// +managedObjectFromModel:insertingIntoContext:processedObjects:error: after -// the receiver's properties have been initialized. -- (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error; - -// Performs the actual work of serialization. This method is also invoked when -// processing relationships, to create a new adapter (if needed) to handle them. -// -// `processedObjects` is a dictionary mapping MTLModels to the NSManagedObjects -// that have been created so far. It should remain alive for the full process -// of serializing the top-level MTLModel. -+ (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error; - -// Looks up the NSValueTransformer that should be used for any attribute that -// corresponds the given property key. -// -// key - The property key to transform from or to. This argument must not be nil. -// -// Returns a transformer to use, or nil to not transform the property. -- (NSValueTransformer *)entityAttributeTransformerForKey:(NSString *)key; - -// Looks up the managed object key that corresponds to the given key. -// -// key - The property key to retrieve the corresponding managed object key for. -// This argument must not be nil. -// -// Returns a key to use, or nil to omit the property from managed object -// serialization. -- (NSString *)managedObjectKeyForKey:(NSString *)key; - -// Looks at propertyKeysForManagedObjectUniquing and forms an NSPredicate -// using the uniquing keys and the provided model. -- (NSPredicate *)uniquingPredicateForModel:(MTLModel *)model; - -@end - -@implementation MTLManagedObjectAdapter - -#pragma mark Lifecycle - -- (id)init { - NSAssert(NO, @"%@ should not be initialized using -init", self.class); - return nil; -} - -- (id)initWithModelClass:(Class)modelClass { - NSParameterAssert(modelClass != nil); - - self = [super init]; - if (self == nil) return nil; - - _modelClass = modelClass; - _managedObjectKeysByPropertyKey = [[modelClass managedObjectKeysByPropertyKey] copy]; - - if ([modelClass respondsToSelector:@selector(relationshipModelClassesByPropertyKey)]) { - _relationshipModelClassesByPropertyKey = [[modelClass relationshipModelClassesByPropertyKey] copy]; - } - - return self; -} - -#pragma mark Serialization - -- (id)modelFromManagedObject:(NSManagedObject *)managedObject processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error { - NSParameterAssert(managedObject != nil); - NSParameterAssert(processedObjects != nil); - - NSEntityDescription *entity = managedObject.entity; - NSAssert(entity != nil, @"%@ returned a nil +entity", managedObject); - - NSManagedObjectContext *context = managedObject.managedObjectContext; - - NSDictionary *managedObjectProperties = entity.propertiesByName; - MTLModel *model = [[self.modelClass alloc] init]; - - // Pre-emptively consider this object processed, so that we don't get into - // any cycles when processing its relationships. - CFDictionaryAddValue(processedObjects, (__bridge void *)managedObject, (__bridge void *)model); - - BOOL (^setValueForKey)(NSString *, id) = ^(NSString *key, id value) { - // Mark this as being autoreleased, because validateValue may return - // a new object to be stored in this variable (and we don't want ARC to - // double-free or leak the old or new values). - __autoreleasing id replaceableValue = value; - if (![model validateValue:&replaceableValue forKey:key error:error]) return NO; - - [model setValue:replaceableValue forKey:key]; - return YES; - }; - - for (NSString *propertyKey in [self.modelClass propertyKeys]) { - NSString *managedObjectKey = [self managedObjectKeyForKey:propertyKey]; - if (managedObjectKey == nil) continue; - - BOOL (^deserializeAttribute)(NSAttributeDescription *) = ^(NSAttributeDescription *attributeDescription) { - id value = performInContext(context, ^{ - return [managedObject valueForKey:managedObjectKey]; - }); - - NSValueTransformer *attributeTransformer = [self entityAttributeTransformerForKey:propertyKey]; - if (attributeTransformer != nil) value = [attributeTransformer reverseTransformedValue:value]; - - return setValueForKey(propertyKey, value); - }; - - BOOL (^deserializeRelationship)(NSRelationshipDescription *) = ^(NSRelationshipDescription *relationshipDescription) { - Class nestedClass = self.relationshipModelClassesByPropertyKey[propertyKey]; - if (nestedClass == nil) { - [NSException raise:NSInvalidArgumentException format:@"No class specified for decoding relationship at key \"%@\" in managed object %@", managedObjectKey, managedObject]; - } - - if ([relationshipDescription isToMany]) { - id models = performInContext(context, ^ id { - id relationshipCollection = [managedObject valueForKey:managedObjectKey]; - NSMutableArray *models = [NSMutableArray arrayWithCapacity:[relationshipCollection count]]; - - for (NSManagedObject *nestedObject in relationshipCollection) { - MTLModel *model = [self.class modelOfClass:nestedClass fromManagedObject:nestedObject processedObjects:processedObjects error:error]; - if (model == nil) return nil; - - [models addObject:model]; - } - - return models; - }); - - if (models == nil) return NO; - if (![relationshipDescription isOrdered]) models = [NSSet setWithArray:models]; - - return setValueForKey(propertyKey, models); - } else { - NSManagedObject *nestedObject = performInContext(context, ^{ - return [managedObject valueForKey:managedObjectKey]; - }); - - if (nestedObject == nil) return YES; - - MTLModel *model = [self.class modelOfClass:nestedClass fromManagedObject:nestedObject processedObjects:processedObjects error:error]; - if (model == nil) return NO; - - return setValueForKey(propertyKey, model); - } - }; - - BOOL (^deserializeProperty)(NSPropertyDescription *) = ^(NSPropertyDescription *propertyDescription) { - if (propertyDescription == nil) { - if (error != NULL) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"No property by name \"%@\" exists on the entity.", @""), managedObjectKey]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not deserialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason, - }; - - *error = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorInvalidManagedObjectKey userInfo:userInfo]; - } - - return NO; - } - - // Jump through some hoops to avoid referencing classes directly. - NSString *propertyClassName = NSStringFromClass(propertyDescription.class); - if ([propertyClassName isEqual:@"NSAttributeDescription"]) { - return deserializeAttribute((id)propertyDescription); - } else if ([propertyClassName isEqual:@"NSRelationshipDescription"]) { - return deserializeRelationship((id)propertyDescription); - } else { - if (error != NULL) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Property descriptions of class %@ are unsupported.", @""), propertyClassName]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not deserialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason, - }; - - *error = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorUnsupportedManagedObjectPropertyType userInfo:userInfo]; - } - - return NO; - } - }; - - if (!deserializeProperty(managedObjectProperties[managedObjectKey])) return nil; - } - - return model; -} - -+ (id)modelOfClass:(Class)modelClass fromManagedObject:(NSManagedObject *)managedObject error:(NSError **)error { - NSSet *propertyKeys = [modelClass propertyKeys]; - - for (NSString *mappedPropertyKey in [modelClass managedObjectKeysByPropertyKey]) { - if ([propertyKeys containsObject:mappedPropertyKey]) continue; - - if (error != NULL) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid entity attribute mapping", nil), - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"%1$@ could not be parsed because its entity attribute mapping contains illegal property keys.", nil), modelClass] - }; - - *error = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorInvalidManagedObjectMapping userInfo:userInfo]; - } - - return nil; - } - - CFMutableDictionaryRef processedObjects = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (processedObjects == NULL) return nil; - - @onExit { - CFRelease(processedObjects); - }; - - return [self modelOfClass:modelClass fromManagedObject:managedObject processedObjects:processedObjects error:error]; -} - -+ (id)modelOfClass:(Class)modelClass fromManagedObject:(NSManagedObject *)managedObject processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error { - NSParameterAssert(modelClass != nil); - NSParameterAssert(processedObjects != nil); - - if (managedObject == nil) return nil; - - const void *existingModel = CFDictionaryGetValue(processedObjects, (__bridge void *)managedObject); - if (existingModel != NULL) { - return (__bridge id)existingModel; - } - - if ([modelClass respondsToSelector:@selector(classForDeserializingManagedObject:)]) { - modelClass = [modelClass classForDeserializingManagedObject:managedObject]; - if (modelClass == nil) { - if (error != NULL) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not deserialize managed object", @""), - NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"No model class could be found to deserialize the object.", @"") - }; - - *error = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorNoClassFound userInfo:userInfo]; - } - - return nil; - } - } - - MTLManagedObjectAdapter *adapter = [[self alloc] initWithModelClass:modelClass]; - return [adapter modelFromManagedObject:managedObject processedObjects:processedObjects error:error]; -} - -- (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error { - NSParameterAssert(model != nil); - NSParameterAssert(context != nil); - NSParameterAssert(processedObjects != nil); - - NSString *entityName = [model.class managedObjectEntityName]; - NSAssert(entityName != nil, @"%@ returned a nil +managedObjectEntityName", model.class); - - Class entityDescriptionClass = NSClassFromString(@"NSEntityDescription"); - NSAssert(entityDescriptionClass != nil, @"CoreData.framework must be linked to use MTLManagedObjectAdapter"); - - Class fetchRequestClass = NSClassFromString(@"NSFetchRequest"); - NSAssert(fetchRequestClass != nil, @"CoreData.framework must be linked to use MTLManagedObjectAdapter"); - - // If a uniquing predicate is provided, perform a fetch request to guarantee a unique managed object. - __block NSManagedObject *managedObject = nil; - NSPredicate *uniquingPredicate = [self uniquingPredicateForModel:model]; - - if (uniquingPredicate != nil) { - __block NSError *fetchRequestError = nil; - __block BOOL encountedError = NO; - managedObject = performInContext(context, ^ id { - NSFetchRequest *fetchRequest = [[fetchRequestClass alloc] init]; - fetchRequest.entity = [entityDescriptionClass entityForName:entityName inManagedObjectContext:context]; - fetchRequest.predicate = uniquingPredicate; - fetchRequest.returnsObjectsAsFaults = NO; - fetchRequest.fetchLimit = 1; - - NSArray *results = [context executeFetchRequest:fetchRequest error:&fetchRequestError]; - - if (results == nil) { - encountedError = YES; - if (error != NULL) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Failed to fetch a managed object for uniqing predicate \"%@\".", @""), uniquingPredicate]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason, - }; - - fetchRequestError = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorUniqueFetchRequestFailed userInfo:userInfo]; - } - - return nil; - } - - return results.mtl_firstObject; - }); - - if (encountedError && error != NULL) { - *error = fetchRequestError; - return nil; - } - } - - if (managedObject == nil) { - managedObject = [entityDescriptionClass insertNewObjectForEntityForName:entityName inManagedObjectContext:context]; - } else { - // Our CoreData store already has data for this model, we need to merge - [self mergeValuesOfModel:model forKeysFromManagedObject:managedObject]; - } - - if (managedObject == nil) { - if (error != NULL) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Failed to initialize a managed object from entity named \"%@\".", @""), entityName]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason, - }; - - *error = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorInitializationFailed userInfo:userInfo]; - } - - return nil; - } - - // Assign all errors to this variable to work around a memory problem. - // - // See https://github.com/github/Mantle/pull/120 for more context. - __block NSError *tmpError; - - // Pre-emptively consider this object processed, so that we don't get into - // any cycles when processing its relationships. - CFDictionaryAddValue(processedObjects, (__bridge void *)model, (__bridge void *)managedObject); - - NSDictionary *dictionaryValue = model.dictionaryValue; - NSDictionary *managedObjectProperties = managedObject.entity.propertiesByName; - - [dictionaryValue enumerateKeysAndObjectsUsingBlock:^(NSString *propertyKey, id value, BOOL *stop) { - NSString *managedObjectKey = [self managedObjectKeyForKey:propertyKey]; - if (managedObjectKey == nil) return; - if ([value isEqual:NSNull.null]) value = nil; - - BOOL (^serializeAttribute)(NSAttributeDescription *) = ^(NSAttributeDescription *attributeDescription) { - // Mark this as being autoreleased, because validateValue may return - // a new object to be stored in this variable (and we don't want ARC to - // double-free or leak the old or new values). - __autoreleasing id transformedValue = value; - - NSValueTransformer *attributeTransformer = [self entityAttributeTransformerForKey:propertyKey]; - if (attributeTransformer != nil) transformedValue = [attributeTransformer transformedValue:transformedValue]; - - if (![managedObject validateValue:&transformedValue forKey:managedObjectKey error:&tmpError]) return NO; - [managedObject setValue:transformedValue forKey:managedObjectKey]; - - return YES; - }; - - NSManagedObject * (^objectForRelationshipFromModel)(id) = ^ id (id model) { - if (![model isKindOfClass:MTLModel.class] || ![model conformsToProtocol:@protocol(MTLManagedObjectSerializing)]) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Property of class %@ cannot be encoded into an NSManagedObject.", @""), [model class]]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason - }; - - tmpError = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorUnsupportedRelationshipClass userInfo:userInfo]; - - return nil; - } - - return [self.class managedObjectFromModel:model insertingIntoContext:context processedObjects:processedObjects error:&tmpError]; - }; - - BOOL (^serializeRelationship)(NSRelationshipDescription *) = ^(NSRelationshipDescription *relationshipDescription) { - if (value == nil) return YES; - - if ([relationshipDescription isToMany]) { - if (![value conformsToProtocol:@protocol(NSFastEnumeration)]) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Property of class %@ cannot be encoded into a to-many relationship.", @""), [value class]]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason - }; - - tmpError = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorUnsupportedRelationshipClass userInfo:userInfo]; - - return NO; - } - - id relationshipCollection; - if ([relationshipDescription isOrdered]) { - relationshipCollection = [NSMutableOrderedSet orderedSet]; - } else { - relationshipCollection = [NSMutableSet set]; - } - - for (MTLModel *model in value) { - NSManagedObject *nestedObject = objectForRelationshipFromModel(model); - if (nestedObject == nil) return NO; - - [relationshipCollection addObject:nestedObject]; - } - - [managedObject setValue:relationshipCollection forKey:managedObjectKey]; - } else { - NSManagedObject *nestedObject = objectForRelationshipFromModel(value); - if (nestedObject == nil) return NO; - - [managedObject setValue:nestedObject forKey:managedObjectKey]; - } - - return YES; - }; - - BOOL (^serializeProperty)(NSPropertyDescription *) = ^(NSPropertyDescription *propertyDescription) { - if (propertyDescription == nil) { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"No property by name \"%@\" exists on the entity.", @""), managedObjectKey]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason - }; - - tmpError = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorInvalidManagedObjectKey userInfo:userInfo]; - - return NO; - } - - // Jump through some hoops to avoid referencing classes directly. - NSString *propertyClassName = NSStringFromClass(propertyDescription.class); - if ([propertyClassName isEqual:@"NSAttributeDescription"]) { - return serializeAttribute((id)propertyDescription); - } else if ([propertyClassName isEqual:@"NSRelationshipDescription"]) { - return serializeRelationship((id)propertyDescription); - } else { - NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Property descriptions of class %@ are unsupported.", @""), propertyClassName]; - - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedString(@"Could not serialize managed object", @""), - NSLocalizedFailureReasonErrorKey: failureReason - }; - - tmpError = [NSError errorWithDomain:MTLManagedObjectAdapterErrorDomain code:MTLManagedObjectAdapterErrorUnsupportedManagedObjectPropertyType userInfo:userInfo]; - - return NO; - } - }; - - if (!serializeProperty(managedObjectProperties[managedObjectKey])) { - performInContext(context, ^ id { - [context deleteObject:managedObject]; - return nil; - }); - - managedObject = nil; - *stop = YES; - } - }]; - - if (managedObject != nil && ![managedObject validateForInsert:&tmpError]) { - managedObject = performInContext(context, ^ id { - [context deleteObject:managedObject]; - return nil; - }); - } - - if (error != NULL) { - *error = tmpError; - } - - return managedObject; -} - -+ (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context error:(NSError **)error { - CFDictionaryKeyCallBacks keyCallbacks = kCFTypeDictionaryKeyCallBacks; - - // Compare MTLModel keys using pointer equality, not -isEqual:. - keyCallbacks.equal = NULL; - - CFMutableDictionaryRef processedObjects = CFDictionaryCreateMutable(NULL, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks); - if (processedObjects == NULL) return nil; - - @onExit { - CFRelease(processedObjects); - }; - - return [self managedObjectFromModel:model insertingIntoContext:context processedObjects:processedObjects error:error]; -} - -+ (id)managedObjectFromModel:(MTLModel *)model insertingIntoContext:(NSManagedObjectContext *)context processedObjects:(CFMutableDictionaryRef)processedObjects error:(NSError **)error { - NSParameterAssert(model != nil); - NSParameterAssert(context != nil); - NSParameterAssert(processedObjects != nil); - - const void *existingManagedObject = CFDictionaryGetValue(processedObjects, (__bridge void *)model); - if (existingManagedObject != NULL) { - return (__bridge id)existingManagedObject; - } - - MTLManagedObjectAdapter *adapter = [[self alloc] initWithModelClass:model.class]; - return [adapter managedObjectFromModel:model insertingIntoContext:context processedObjects:processedObjects error:error]; -} - -- (NSValueTransformer *)entityAttributeTransformerForKey:(NSString *)key { - NSParameterAssert(key != nil); - - SEL selector = MTLSelectorWithKeyPattern(key, "EntityAttributeTransformer"); - if ([self.modelClass respondsToSelector:selector]) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self.modelClass methodSignatureForSelector:selector]]; - invocation.target = self.modelClass; - invocation.selector = selector; - [invocation invoke]; - - __unsafe_unretained id result = nil; - [invocation getReturnValue:&result]; - return result; - } - - if ([self.modelClass respondsToSelector:@selector(entityAttributeTransformerForKey:)]) { - return [self.modelClass entityAttributeTransformerForKey:key]; - } - - return nil; -} - -- (NSString *)managedObjectKeyForKey:(NSString *)key { - NSParameterAssert(key != nil); - - id managedObjectKey = self.managedObjectKeysByPropertyKey[key]; - if ([managedObjectKey isEqual:NSNull.null]) return nil; - - if (managedObjectKey == nil) { - return key; - } else { - return managedObjectKey; - } -} - -- (void)mergeValueOfModel:(MTLModel *)model forKey:(NSString *)key fromManagedObject:(NSManagedObject *)managedObject { - [model mergeValueForKey:key fromManagedObject:managedObject]; -} - -- (void)mergeValuesOfModel:(MTLModel *)model forKeysFromManagedObject:(NSManagedObject *)managedObject { - if ([model respondsToSelector:@selector(mergeValuesForKeysFromManagedObject:)]) { - [model mergeValuesForKeysFromManagedObject:managedObject]; - } else if ([model respondsToSelector:@selector(mergeValueForKey:fromManagedObject:)]) { - [[model.class managedObjectKeysByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *managedObjectKey, BOOL *stop) { - [self mergeValueOfModel:model forKey:key fromManagedObject:managedObject]; - }]; - } -} - -- (NSPredicate *)uniquingPredicateForModel:(MTLModel *)model { - if (![self.modelClass respondsToSelector:@selector(propertyKeysForManagedObjectUniquing)]) return nil; - - NSSet *propertyKeys = [self.modelClass propertyKeysForManagedObjectUniquing]; - - if (propertyKeys == nil) return nil; - - NSAssert(propertyKeys.count > 0, @"+propertyKeysForManagedObjectUniquing must not be empty."); - - NSMutableArray *subpredicates = [NSMutableArray array]; - for (NSString *propertyKey in propertyKeys) { - NSString *managedObjectKey = [self managedObjectKeyForKey:propertyKey]; - - NSAssert(managedObjectKey != nil, @"%@ must map to a managed object key.", propertyKey); - - id transformedValue = [model valueForKeyPath:propertyKey]; - - NSValueTransformer *attributeTransformer = [self entityAttributeTransformerForKey:propertyKey]; - if (attributeTransformer != nil) transformedValue = [attributeTransformer transformedValue:transformedValue]; - - NSPredicate *subpredicate = [NSPredicate predicateWithFormat:@"%K == %@", managedObjectKey, transformedValue]; - [subpredicates addObject:subpredicate]; - } - - return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates]; -} - -@end diff --git a/Pods/Mantle/Mantle/MTLModel+NSCoding.h b/Pods/Mantle/Mantle/MTLModel+NSCoding.h index 94b8f7b..86e140a 100644 --- a/Pods/Mantle/Mantle/MTLModel+NSCoding.h +++ b/Pods/Mantle/Mantle/MTLModel+NSCoding.h @@ -8,121 +8,121 @@ #import "MTLModel.h" -// Defines how a MTLModel property key should be encoded into an archive. -// -// MTLModelEncodingBehaviorExcluded - The property should never be encoded. -// MTLModelEncodingBehaviorUnconditional - The property should always be -// encoded. -// MTLModelEncodingBehaviorConditional - The object should be encoded only -// if unconditionally encoded elsewhere. -// This should only be used for object -// properties. +/// Defines how a MTLModel property key should be encoded into an archive. +/// +/// MTLModelEncodingBehaviorExcluded - The property should never be encoded. +/// MTLModelEncodingBehaviorUnconditional - The property should always be +/// encoded. +/// MTLModelEncodingBehaviorConditional - The object should be encoded only +/// if unconditionally encoded elsewhere. +/// This should only be used for object +/// properties. typedef enum : NSUInteger { MTLModelEncodingBehaviorExcluded = 0, MTLModelEncodingBehaviorUnconditional, MTLModelEncodingBehaviorConditional, } MTLModelEncodingBehavior; -// Implements default archiving and unarchiving behaviors for MTLModel. +/// Implements default archiving and unarchiving behaviors for MTLModel. @interface MTLModel (NSCoding) -// Initializes the receiver from an archive. -// -// This will decode the original +modelVersion of the archived object, then -// invoke -decodeValueForKey:withCoder:modelVersion: for each of the receiver's -// +propertyKeys. -// -// Returns an initialized model object, or nil if a decoding error occurred. +/// Initializes the receiver from an archive. +/// +/// This will decode the original +modelVersion of the archived object, then +/// invoke -decodeValueForKey:withCoder:modelVersion: for each of the receiver's +/// +propertyKeys. +/// +/// Returns an initialized model object, or nil if a decoding error occurred. - (id)initWithCoder:(NSCoder *)coder; -// Archives the receiver using the given coder. -// -// This will encode the receiver's +modelVersion, then the receiver's properties -// according to the behaviors specified in +encodingBehaviorsByPropertyKey. +/// Archives the receiver using the given coder. +/// +/// This will encode the receiver's +modelVersion, then the receiver's properties +/// according to the behaviors specified in +encodingBehaviorsByPropertyKey. - (void)encodeWithCoder:(NSCoder *)coder; -// Determines how the +propertyKeys of the class are encoded into an archive. -// The values of this dictionary should be boxed MTLModelEncodingBehavior -// values. -// -// Any keys not present in the dictionary will be excluded from the archive. -// -// Subclasses overriding this method should combine their values with those of -// `super`. -// -// Returns a dictionary mapping the receiver's +propertyKeys to default encoding -// behaviors. If a property is an object with `weak` semantics, the default -// behavior is MTLModelEncodingBehaviorConditional; otherwise, the default is -// MTLModelEncodingBehaviorUnconditional. +/// Determines how the +propertyKeys of the class are encoded into an archive. +/// The values of this dictionary should be boxed MTLModelEncodingBehavior +/// values. +/// +/// Any keys not present in the dictionary will be excluded from the archive. +/// +/// Subclasses overriding this method should combine their values with those of +/// `super`. +/// +/// Returns a dictionary mapping the receiver's +propertyKeys to default encoding +/// behaviors. If a property is an object with `weak` semantics, the default +/// behavior is MTLModelEncodingBehaviorConditional; otherwise, the default is +/// MTLModelEncodingBehaviorUnconditional. + (NSDictionary *)encodingBehaviorsByPropertyKey; -// Determines the classes that are allowed to be decoded for each of the -// receiver's properties when using . The values of this -// dictionary should be NSArrays of Class objects. -// -// If any encodable keys (as determined by +encodingBehaviorsByPropertyKey) are -// not present in the dictionary, an exception will be thrown during secure -// encoding or decoding. -// -// Subclasses overriding this method should combine their values with those of -// `super`. -// -// Returns a dictionary mapping the receiver's encodable keys (as determined by -// +encodingBehaviorsByPropertyKey) to default allowed classes, based on the -// type that each property is declared as. If type of an encodable property -// cannot be determined (e.g., it is declared as `id`), it will be omitted from -// the dictionary, and subclasses must provide a valid value to prevent an -// exception being thrown during encoding/decoding. +/// Determines the classes that are allowed to be decoded for each of the +/// receiver's properties when using . The values of this +/// dictionary should be NSArrays of Class objects. +/// +/// If any encodable keys (as determined by +encodingBehaviorsByPropertyKey) are +/// not present in the dictionary, an exception will be thrown during secure +/// encoding or decoding. +/// +/// Subclasses overriding this method should combine their values with those of +/// `super`. +/// +/// Returns a dictionary mapping the receiver's encodable keys (as determined by +/// +encodingBehaviorsByPropertyKey) to default allowed classes, based on the +/// type that each property is declared as. If type of an encodable property +/// cannot be determined (e.g., it is declared as `id`), it will be omitted from +/// the dictionary, and subclasses must provide a valid value to prevent an +/// exception being thrown during encoding/decoding. + (NSDictionary *)allowedSecureCodingClassesByPropertyKey; -// Decodes the value of the given property key from an archive. -// -// By default, this method looks for a `-decodeWithCoder:modelVersion:` -// method on the receiver, and invokes it if found. -// -// If the custom method is not implemented and `coder` does not require secure -// coding, `-[NSCoder decodeObjectForKey:]` will be invoked with the given -// `key`. -// -// If the custom method is not implemented and `coder` requires secure coding, -// `-[NSCoder decodeObjectOfClasses:forKey:]` will be invoked with the -// information from +allowedSecureCodingClassesByPropertyKey and the given `key`. The -// receiver must conform to for this to work correctly. -// -// key - The property key to decode the value for. This argument cannot -// be nil. -// coder - The NSCoder representing the archive being decoded. This -// argument cannot be nil. -// modelVersion - The version of the original model object that was encoded. -// -// Returns the decoded and boxed value, or nil if the key was not present. +/// Decodes the value of the given property key from an archive. +/// +/// By default, this method looks for a `-decodeWithCoder:modelVersion:` +/// method on the receiver, and invokes it if found. +/// +/// If the custom method is not implemented and `coder` does not require secure +/// coding, `-[NSCoder decodeObjectForKey:]` will be invoked with the given +/// `key`. +/// +/// If the custom method is not implemented and `coder` requires secure coding, +/// `-[NSCoder decodeObjectOfClasses:forKey:]` will be invoked with the +/// information from +allowedSecureCodingClassesByPropertyKey and the given `key`. The +/// receiver must conform to for this to work correctly. +/// +/// key - The property key to decode the value for. This argument cannot +/// be nil. +/// coder - The NSCoder representing the archive being decoded. This +/// argument cannot be nil. +/// modelVersion - The version of the original model object that was encoded. +/// +/// Returns the decoded and boxed value, or nil if the key was not present. - (id)decodeValueForKey:(NSString *)key withCoder:(NSCoder *)coder modelVersion:(NSUInteger)modelVersion; -// The version of this MTLModel subclass. -// -// This version number is saved in archives so that later model changes can be -// made backwards-compatible with old versions. -// -// Subclasses should override this method to return a higher version number -// whenever a breaking change is made to the model. -// -// Returns 0. +/// The version of this MTLModel subclass. +/// +/// This version number is saved in archives so that later model changes can be +/// made backwards-compatible with old versions. +/// +/// Subclasses should override this method to return a higher version number +/// whenever a breaking change is made to the model. +/// +/// Returns 0. + (NSUInteger)modelVersion; @end -// This method must be overridden to support archives created by older versions -// of Mantle (before the `MTLModel+NSCoding` interface existed). +/// This method must be overridden to support archives created by older versions +/// of Mantle (before the `MTLModel+NSCoding` interface existed). @interface MTLModel (OldArchiveSupport) -// Converts an archived external representation to a dictionary suitable for -// passing to -initWithDictionary:. -// -// externalRepresentation - The decoded external representation of the receiver. -// fromVersion - The model version at the time the external -// representation was encoded. -// -// Returns nil by default, indicating that conversion failed. +/// Converts an archived external representation to a dictionary suitable for +/// passing to -initWithDictionary:. +/// +/// externalRepresentation - The decoded external representation of the receiver. +/// fromVersion - The model version at the time the external +/// representation was encoded. +/// +/// Returns nil by default, indicating that conversion failed. + (NSDictionary *)dictionaryValueFromArchivedExternalRepresentation:(NSDictionary *)externalRepresentation version:(NSUInteger)fromVersion; @end diff --git a/Pods/Mantle/Mantle/MTLModel+NSCoding.m b/Pods/Mantle/Mantle/MTLModel+NSCoding.m index 852f5ae..79a3b57 100644 --- a/Pods/Mantle/Mantle/MTLModel+NSCoding.m +++ b/Pods/Mantle/Mantle/MTLModel+NSCoding.m @@ -10,7 +10,6 @@ #import "EXTRuntimeExtensions.h" #import "EXTScope.h" #import "MTLReflection.h" -#import // Used in archives to store the modelVersion of the archived instance. static NSString * const MTLModelVersionKey = @"MTLModelVersion"; diff --git a/Pods/Mantle/Mantle/MTLModel.h b/Pods/Mantle/Mantle/MTLModel.h index 65da40d..96042b4 100644 --- a/Pods/Mantle/Mantle/MTLModel.h +++ b/Pods/Mantle/Mantle/MTLModel.h @@ -8,118 +8,172 @@ #import -// An abstract base class for model objects, using reflection to provide -// sensible default behaviors. -// -// The default implementations of , -hash, and -isEqual: make use of -// the +propertyKeys method. -@interface MTLModel : NSObject +/// Defines a property's storage behavior, which affects how it will be copied, +/// compared, and persisted. +/// +/// MTLPropertyStorageNone - This property is not included in -description, +/// -hash, or anything else. +/// MTLPropertyStorageTransitory - This property is included in one-off +/// operations like -copy and -dictionaryValue but +/// does not affect -isEqual: or -hash. +/// It may disappear at any time. +/// MTLPropertyStoragePermanent - The property is included in serialization +/// (like `NSCoding`) and equality, since it can +/// be expected to stick around. +typedef enum : NSUInteger { + MTLPropertyStorageNone, + MTLPropertyStorageTransitory, + MTLPropertyStoragePermanent, +} MTLPropertyStorage; -// Returns a new instance of the receiver initialized using -// -initWithDictionary:error:. +/// This protocol defines the minimal interface that classes need to implement to +/// interact with Mantle adapters. +/// +/// It is intended for scenarios where inheriting from MTLModel is not feasible. +/// However, clients are encouraged to subclass the MTLModel class if they can. +/// +/// Clients that wish to implement their own adapters should target classes +/// conforming to this protocol rather than subclasses of MTLModel to ensure +/// maximum compatibility. +@protocol MTLModel + +/// Initializes a new instance of the receiver using key-value coding, setting +/// the keys and values in the given dictionary. +/// +/// dictionaryValue - Property keys and values to set on the instance. Any NSNull +/// values will be converted to nil before being used. KVC +/// validation methods will automatically be invoked for all of +/// the properties given. +/// error - If not NULL, this may be set to any error that occurs +/// (like a KVC validation error). +/// +/// Returns an initialized model object, or nil if validation failed. + (instancetype)modelWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; -// Initializes the receiver with default values. -// -// This is the designated initializer for this class. -- (instancetype)init; - -// Initializes the receiver using key-value coding, setting the keys and values -// in the given dictionary. -// -// Subclass implementations may override this method, calling the super -// implementation, in order to perform further processing and initialization -// after deserialization. -// -// dictionaryValue - Property keys and values to set on the receiver. Any NSNull -// values will be converted to nil before being used. KVC -// validation methods will automatically be invoked for all of -// the properties given. If nil, this method is equivalent to -// -init. -// error - If not NULL, this may be set to any error that occurs -// (like a KVC validation error). -// -// Returns an initialized model object, or nil if validation failed. -- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; - -// Returns the keys for all @property declarations, except for `readonly` -// properties without ivars, or properties on MTLModel itself. -+ (NSSet *)propertyKeys; - -// A dictionary representing the properties of the receiver. -// -// The default implementation combines the values corresponding to all -// +propertyKeys into a dictionary, with any nil values represented by NSNull. -// -// This property must never be nil. +/// A dictionary representing the properties of the receiver. +/// +/// Combines the values corresponding to all +propertyKeys into a dictionary, +/// with any nil values represented by NSNull. +/// +/// This property must never be nil. @property (nonatomic, copy, readonly) NSDictionary *dictionaryValue; -// Merges the value of the given key on the receiver with the value of the same -// key from the given model object, giving precedence to the other model object. -// -// By default, this method looks for a `-mergeFromModel:` method on the -// receiver, and invokes it if found. If not found, and `model` is not nil, the -// value for the given key is taken from `model`. -- (void)mergeValueForKey:(NSString *)key fromModel:(MTLModel *)model; +/// Initializes the receiver using key-value coding, setting the keys and values +/// in the given dictionary. +/// +/// Subclass implementations may override this method, calling the super +/// implementation, in order to perform further processing and initialization +/// after deserialization. +/// +/// dictionaryValue - Property keys and values to set on the receiver. Any NSNull +/// values will be converted to nil before being used. KVC +/// validation methods will automatically be invoked for all of +/// the properties given. If nil, this method is equivalent to +/// -init. +/// error - If not NULL, this may be set to any error that occurs +/// (like a KVC validation error). +/// +/// Returns an initialized model object, or nil if validation failed. +- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; -// Merges the values of the given model object into the receiver, using -// -mergeValueForKey:fromModel: for each key in +propertyKeys. -// -// `model` must be an instance of the receiver's class or a subclass thereof. -- (void)mergeValuesForKeysFromModel:(MTLModel *)model; +/// Merges the value of the given key on the receiver with the value of the same +/// key from the given model object, giving precedence to the other model object. +- (void)mergeValueForKey:(NSString *)key fromModel:(id)model; -// Compares the receiver with another object for equality. -// -// The default implementation is equivalent to comparing both models' -// -dictionaryValue. -// -// Note that this may lead to infinite loops if the receiver holds a circular -// reference to another MTLModel and both use the default behavior. -// It is recommended to override -isEqual: in this scenario. -- (BOOL)isEqual:(id)object; +/// Returns the keys for all @property declarations, except for `readonly` +/// properties without ivars, or properties on MTLModel itself. ++ (NSSet *)propertyKeys; -// A string that describes the contents of the receiver. -// -// The default implementation is based on the receiver's class and its -// -dictionaryValue. -// -// Note that this may lead to infinite loops if the receiver holds a circular -// reference to another MTLModel and both use the default behavior. -// It is recommended to override -description in this scenario. -- (NSString *)description; - -@end - -// Implements validation logic for MTLModel. -@interface MTLModel (Validation) - -// Validates the model. -// -// The default implementation simply invokes -validateValue:forKey:error: with -// all +propertyKeys and their current value. If -validateValue:forKey:error: -// returns a new value, the property is set to that new value. -// -// error - If not NULL, this may be set to any error that occurs during -// validation -// -// Returns YES if the model is valid, or NO if the validation failed. +/// Validates the model. +/// +/// error - If not NULL, this may be set to any error that occurs during +/// validation +/// +/// Returns YES if the model is valid, or NO if the validation failed. - (BOOL)validate:(NSError **)error; @end -@interface MTLModel (Unavailable) +/// An abstract base class for model objects, using reflection to provide +/// sensible default behaviors. +/// +/// The default implementations of , -hash, and -isEqual: make use of +/// the +propertyKeys method. +@interface MTLModel : NSObject -+ (instancetype)modelWithDictionary:(NSDictionary *)dictionaryValue __attribute__((deprecated("Replaced by +modelWithDictionary:error:"))); -- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue __attribute__((deprecated("Replaced by -initWithDictionary:error:"))); +/// Initializes the receiver using key-value coding, setting the keys and values +/// in the given dictionary. +/// +/// dictionaryValue - Property keys and values to set on the receiver. Any NSNull +/// values will be converted to nil before being used. KVC +/// validation methods will automatically be invoked for all of +/// the properties given. If nil, this method is equivalent to +/// -init. +/// error - If not NULL, this may be set to any error that occurs +/// (like a KVC validation error). +/// +/// Returns an initialized model object, or nil if validation failed. +- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; -+ (instancetype)modelWithExternalRepresentation:(NSDictionary *)externalRepresentation __attribute__((deprecated("Replaced by -[MTLJSONAdapter initWithJSONDictionary:modelClass:]"))); -- (instancetype)initWithExternalRepresentation:(NSDictionary *)externalRepresentation __attribute__((deprecated("Replaced by -[MTLJSONAdapter initWithJSONDictionary:modelClass:]"))); +/// Initializes the receiver with default values. +/// +/// This is the designated initializer for this class. +- (instancetype)init; -@property (nonatomic, copy, readonly) NSDictionary *externalRepresentation __attribute__((deprecated("Replaced by MTLJSONAdapter.JSONDictionary"))); +/// By default, this method looks for a `-mergeFromModel:` method on the +/// receiver, and invokes it if found. If not found, and `model` is not nil, the +/// value for the given key is taken from `model`. +- (void)mergeValueForKey:(NSString *)key fromModel:(id)model; -+ (NSDictionary *)externalRepresentationKeyPathsByPropertyKey __attribute__((deprecated("Replaced by +JSONKeyPathsByPropertyKey in "))); -+ (NSValueTransformer *)transformerForKey:(NSString *)key __attribute__((deprecated("Replaced by +JSONTransformerForKey: in "))); +/// Merges the values of the given model object into the receiver, using +/// -mergeValueForKey:fromModel: for each key in +propertyKeys. +/// +/// `model` must be an instance of the receiver's class or a subclass thereof. +- (void)mergeValuesForKeysFromModel:(id)model; -+ (NSDictionary *)migrateExternalRepresentation:(NSDictionary *)externalRepresentation fromVersion:(NSUInteger)fromVersion __attribute__((deprecated("Replaced by -decodeValueForKey:withCoder:modelVersion:"))); +/// The storage behavior of a given key. +/// +/// The default implementation returns MTLPropertyStorageNone for properties that +/// are readonly and not backed by an instance variable and +/// MTLPropertyStoragePermanent otherwise. +/// +/// Subclasses can use this method to prevent MTLModel from resolving circular +/// references by returning MTLPropertyStorageTransitory. +/// +/// Returns the storage behavior for a given key on the receiver. ++ (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey; + +/// Compares the receiver with another object for equality. +/// +/// The default implementation is equivalent to comparing all properties of both +/// models for which +storageBehaviorForPropertyWithKey: returns +/// MTLPropertyStoragePermanent. +/// +/// Returns YES if the two models are considered equal, NO otherwise. +- (BOOL)isEqual:(id)object; + +/// A string that describes the contents of the receiver. +/// +/// The default implementation is based on the receiver's class and all its +/// properties for which +storageBehaviorForPropertyWithKey: returns +/// MTLPropertyStoragePermanent. +- (NSString *)description; + +@end + +/// Implements validation logic for MTLModel. +@interface MTLModel (Validation) + +/// Validates the model. +/// +/// The default implementation simply invokes -validateValue:forKey:error: with +/// all +propertyKeys and their current value. If -validateValue:forKey:error: +/// returns a new value, the property is set to that new value. +/// +/// error - If not NULL, this may be set to any error that occurs during +/// validation +/// +/// Returns YES if the model is valid, or NO if the validation failed. +- (BOOL)validate:(NSError **)error; @end diff --git a/Pods/Mantle/Mantle/MTLModel.m b/Pods/Mantle/Mantle/MTLModel.m index 2ef60fe..5e3f5df 100644 --- a/Pods/Mantle/Mantle/MTLModel.m +++ b/Pods/Mantle/Mantle/MTLModel.m @@ -13,14 +13,17 @@ #import "MTLReflection.h" #import -// This coupling is needed for backwards compatibility in MTLModel's deprecated -// methods. -#import "MTLJSONAdapter.h" -#import "MTLModel+NSCoding.h" - // Used to cache the reflection performed in +propertyKeys. static void *MTLModelCachedPropertyKeysKey = &MTLModelCachedPropertyKeysKey; +// Associated in +generateAndCachePropertyKeys with a set of all transitory +// property keys. +static void *MTLModelCachedTransitoryPropertyKeysKey = &MTLModelCachedTransitoryPropertyKeysKey; + +// Associated in +generateAndCachePropertyKeys with a set of all permanent +// property keys. +static void *MTLModelCachedPermanentPropertyKeysKey = &MTLModelCachedPermanentPropertyKeysKey; + // Validates a value for an object and sets it if necessary. // // obj - The object for which the value is being validated. This value @@ -67,6 +70,18 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp @interface MTLModel () +// Inspects all properties of returned by +propertyKeys using +// +storageBehaviorForPropertyWithKey and caches the results. ++ (void)generateAndCacheStorageBehaviors; + +// Returns a set of all property keys for which +// +storageBehaviorForPropertyWithKey returned MTLPropertyStorageTransitory. ++ (NSSet *)transitoryPropertyKeys; + +// Returns a set of all property keys for which +// +storageBehaviorForPropertyWithKey returned MTLPropertyStoragePermanent. ++ (NSSet *)permanentPropertyKeys; + // Enumerates all properties of the receiver's class hierarchy, starting at the // receiver, and continuing up until (but not including) MTLModel. // @@ -80,6 +95,31 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp #pragma mark Lifecycle ++ (void)generateAndCacheStorageBehaviors { + NSMutableSet *transitoryKeys = [NSMutableSet set]; + NSMutableSet *permanentKeys = [NSMutableSet set]; + + for (NSString *propertyKey in self.propertyKeys) { + switch ([self storageBehaviorForPropertyWithKey:propertyKey]) { + case MTLPropertyStorageNone: + break; + + case MTLPropertyStorageTransitory: + [transitoryKeys addObject:propertyKey]; + break; + + case MTLPropertyStoragePermanent: + [permanentKeys addObject:propertyKey]; + break; + } + } + + // It doesn't really matter if we replace another thread's work, since we do + // it atomically and the result should be the same. + objc_setAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey, transitoryKeys, OBJC_ASSOCIATION_COPY); + objc_setAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey, permanentKeys, OBJC_ASSOCIATION_COPY); +} + + (instancetype)modelWithDictionary:(NSDictionary *)dictionary error:(NSError **)error { return [[self alloc] initWithDictionary:dictionary error:error]; } @@ -98,7 +138,7 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp // a new object to be stored in this variable (and we don't want ARC to // double-free or leak the old or new values). __autoreleasing id value = [dictionary objectForKey:key]; - + if ([value isEqual:NSNull.null]) value = nil; BOOL success = MTLValidateAndSetValue(self, key, value, YES, error); @@ -139,15 +179,11 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp NSMutableSet *keys = [NSMutableSet set]; [self enumeratePropertiesUsingBlock:^(objc_property_t property, BOOL *stop) { - mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); - @onExit { - free(attributes); - }; - - if (attributes->readonly && attributes->ivar == NULL) return; - NSString *key = @(property_getName(property)); - [keys addObject:key]; + + if ([self storageBehaviorForPropertyWithKey:key] != MTLPropertyStorageNone) { + [keys addObject:key]; + } }]; // It doesn't really matter if we replace another thread's work, since we do @@ -157,13 +193,54 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp return keys; } ++ (NSSet *)transitoryPropertyKeys { + NSSet *transitoryPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey); + + if (transitoryPropertyKeys == nil) { + [self generateAndCacheStorageBehaviors]; + transitoryPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedTransitoryPropertyKeysKey); + } + + return transitoryPropertyKeys; +} + ++ (NSSet *)permanentPropertyKeys { + NSSet *permanentPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey); + + if (permanentPropertyKeys == nil) { + [self generateAndCacheStorageBehaviors]; + permanentPropertyKeys = objc_getAssociatedObject(self, MTLModelCachedPermanentPropertyKeysKey); + } + + return permanentPropertyKeys; +} + - (NSDictionary *)dictionaryValue { - return [self dictionaryWithValuesForKeys:self.class.propertyKeys.allObjects]; + NSSet *keys = [self.class.transitoryPropertyKeys setByAddingObjectsFromSet:self.class.permanentPropertyKeys]; + + return [self dictionaryWithValuesForKeys:keys.allObjects]; +} + ++ (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey { + objc_property_t property = class_getProperty(self.class, propertyKey.UTF8String); + + if (property == NULL) return MTLPropertyStorageNone; + + mtl_propertyAttributes *attributes = mtl_copyPropertyAttributes(property); + @onExit { + free(attributes); + }; + + if (attributes->readonly && attributes->ivar == NULL) { + return MTLPropertyStorageNone; + } else { + return MTLPropertyStoragePermanent; + } } #pragma mark Merging -- (void)mergeValueForKey:(NSString *)key fromModel:(MTLModel *)model { +- (void)mergeValueForKey:(NSString *)key fromModel:(NSObject *)model { NSParameterAssert(key != nil); SEL selector = MTLSelectorWithCapitalizedKeyPattern("merge", key, "FromModel:"); @@ -183,8 +260,9 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp [invocation invoke]; } -- (void)mergeValuesForKeysFromModel:(MTLModel *)model { +- (void)mergeValuesForKeysFromModel:(id)model { NSSet *propertyKeys = model.class.propertyKeys; + for (NSString *key in self.class.propertyKeys) { if (![propertyKeys containsObject:key]) continue; @@ -214,13 +292,15 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp #pragma mark NSObject - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p> %@", self.class, self, self.dictionaryValue]; + NSDictionary *permanentProperties = [self dictionaryWithValuesForKeys:self.class.permanentPropertyKeys.allObjects]; + + return [NSString stringWithFormat:@"<%@: %p> %@", self.class, self, permanentProperties]; } - (NSUInteger)hash { NSUInteger value = 0; - for (NSString *key in self.class.propertyKeys) { + for (NSString *key in self.class.permanentPropertyKeys) { value ^= [[self valueForKey:key] hash]; } @@ -231,7 +311,7 @@ static BOOL MTLValidateAndSetValue(id obj, NSString *key, id value, BOOL forceUp if (self == model) return YES; if (![model isMemberOfClass:self.class]) return NO; - for (NSString *key in self.class.propertyKeys) { + for (NSString *key in self.class.permanentPropertyKeys) { id selfValue = [self valueForKey:key]; id modelValue = [model valueForKey:key]; diff --git a/Pods/Mantle/Mantle/MTLReflection.h b/Pods/Mantle/Mantle/MTLReflection.h index f4c100e..52c920b 100644 --- a/Pods/Mantle/Mantle/MTLReflection.h +++ b/Pods/Mantle/Mantle/MTLReflection.h @@ -8,24 +8,24 @@ #import -// Creates a selector from a key and a constant string. -// -// key - The key to insert into the generated selector. This key should be in -// its natural case. -// suffix - A string to append to the key as part of the selector. -// -// Returns a selector, or NULL if the input strings cannot form a valid -// selector. +/// Creates a selector from a key and a constant string. +/// +/// key - The key to insert into the generated selector. This key should be in +/// its natural case. +/// suffix - A string to append to the key as part of the selector. +/// +/// Returns a selector, or NULL if the input strings cannot form a valid +/// selector. SEL MTLSelectorWithKeyPattern(NSString *key, const char *suffix) __attribute__((pure, nonnull(1, 2))); -// Creates a selector from a key and a constant prefix and suffix. -// -// prefix - A string to prepend to the key as part of the selector. -// key - The key to insert into the generated selector. This key should be in -// its natural case, and will have its first letter capitalized when -// inserted. -// suffix - A string to append to the key as part of the selector. -// -// Returns a selector, or NULL if the input strings cannot form a valid -// selector. +/// Creates a selector from a key and a constant prefix and suffix. +/// +/// prefix - A string to prepend to the key as part of the selector. +/// key - The key to insert into the generated selector. This key should be in +/// its natural case, and will have its first letter capitalized when +/// inserted. +/// suffix - A string to append to the key as part of the selector. +/// +/// Returns a selector, or NULL if the input strings cannot form a valid +/// selector. SEL MTLSelectorWithCapitalizedKeyPattern(const char *prefix, NSString *key, const char *suffix) __attribute__((pure, nonnull(1, 2, 3))); diff --git a/Pods/Mantle/Mantle/MTLTransformerErrorHandling.h b/Pods/Mantle/Mantle/MTLTransformerErrorHandling.h new file mode 100644 index 0000000..2726d91 --- /dev/null +++ b/Pods/Mantle/Mantle/MTLTransformerErrorHandling.h @@ -0,0 +1,66 @@ +// +// MTLTransformerErrorHandling.h +// Mantle +// +// Created by Robert Böhnke on 10/6/13. +// Copyright (c) 2013 GitHub. All rights reserved. +// + +#import + +/// The domain for errors originating from the MTLTransformerErrorHandling +/// protocol. +/// +/// Transformers conforming to this protocol are expected to use this error +/// domain if the transformation fails. +extern NSString * const MTLTransformerErrorHandlingErrorDomain; + +/// Used to indicate that the input value was illegal. +/// +/// Transformers conforming to this protocol are expected to use this error code +/// if the transformation fails due to an invalid input value. +extern const NSInteger MTLTransformerErrorHandlingErrorInvalidInput; + +/// Associated with the invalid input value. +/// +/// Transformers conforming to this protocol are expected to associate this key +/// with the invalid input in the userInfo dictionary. +extern NSString * const MTLTransformerErrorHandlingInputValueErrorKey; + +/// This protocol can be implemented by NSValueTransformer subclasses to +/// communicate errors that occur during transformation. +@protocol MTLTransformerErrorHandling +@required + +/// Transforms a value, returning any error that occurred during transformation. +/// +/// value - The value to transform. +/// success - If not NULL, this will be set to a boolean indicating whether the +/// transformation was successful. +/// error - If not NULL, this may be set to an error that occurs during +/// transforming the value. +/// +/// Returns the result of the transformation which may be nil. Clients should +/// inspect the success parameter to decide how to proceed with the result. +- (id)transformedValue:(id)value success:(BOOL *)success error:(NSError **)error; + +@optional + +/// Reverse-transforms a value, returning any error that occurred during +/// transformation. +/// +/// Transformers conforming to this protocol are expected to implemented this +/// method if they support reverse transformation. +/// +/// value - The value to transform. +/// success - If not NULL, this will be set to a boolean indicating whether the +/// transformation was successful. +/// error - If not NULL, this may be set to an error that occurs during +/// transforming the value. +/// +/// Returns the result of the reverse transformation which may be nil. Clients +/// should inspect the success parameter to decide how to proceed with the +/// result. +- (id)reverseTransformedValue:(id)value success:(BOOL *)success error:(NSError **)error; + +@end diff --git a/Pods/Mantle/Mantle/MTLTransformerErrorHandling.m b/Pods/Mantle/Mantle/MTLTransformerErrorHandling.m new file mode 100644 index 0000000..962e2c0 --- /dev/null +++ b/Pods/Mantle/Mantle/MTLTransformerErrorHandling.m @@ -0,0 +1,15 @@ +// +// MTLTransformerErrorHandling.h +// Mantle +// +// Created by Robert Böhnke on 10/6/13. +// Copyright (c) 2013 GitHub. All rights reserved. +// + +#import "MTLTransformerErrorHandling.h" + +NSString * const MTLTransformerErrorHandlingErrorDomain = @"MTLTransformerErrorHandlingErrorDomain"; + +const NSInteger MTLTransformerErrorHandlingErrorInvalidInput = 1; + +NSString * const MTLTransformerErrorHandlingInputValueErrorKey = @"MTLTransformerErrorHandlingInputValueErrorKey"; diff --git a/Pods/Mantle/Mantle/MTLValueTransformer.h b/Pods/Mantle/Mantle/MTLValueTransformer.h index 231b59f..5deda94 100644 --- a/Pods/Mantle/Mantle/MTLValueTransformer.h +++ b/Pods/Mantle/Mantle/MTLValueTransformer.h @@ -8,22 +8,45 @@ #import -typedef id (^MTLValueTransformerBlock)(id); +#import "MTLTransformerErrorHandling.h" -// -// A value transformer supporting block-based transformation. -// -@interface MTLValueTransformer : NSValueTransformer +/// A block that represents a transformation. +/// +/// value - The value to transform. +/// success - The block must set this parameter to indicate whether the +/// transformation was successful. +/// MTLValueTransformer will always call this block with *success +/// initialized to YES. +/// error - If not NULL, this may be set to an error that occurs during +/// transforming the value. +/// +/// Returns the result of the transformation, which may be nil. +typedef id (^MTLValueTransformerBlock)(id value, BOOL *success, NSError **error); -// Returns a transformer which transforms values using the given block. Reverse -// transformations will not be allowed. -+ (instancetype)transformerWithBlock:(MTLValueTransformerBlock)transformationBlock; +/// +/// A value transformer supporting block-based transformation. +/// +@interface MTLValueTransformer : NSValueTransformer -// Returns a transformer which transforms values using the given block, for -// forward or reverse transformations. -+ (instancetype)reversibleTransformerWithBlock:(MTLValueTransformerBlock)transformationBlock; +/// Returns a transformer which transforms values using the given block. Reverse +/// transformations will not be allowed. ++ (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)transformation; -// Returns a transformer which transforms values using the given blocks. -+ (instancetype)reversibleTransformerWithForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock; +/// Returns a transformer which transforms values using the given block, for +/// forward or reverse transformations. ++ (instancetype)transformerUsingReversibleBlock:(MTLValueTransformerBlock)transformation; + +/// Returns a transformer which transforms values using the given blocks. ++ (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardTransformation reverseBlock:(MTLValueTransformerBlock)reverseTransformation; + +@end + +@interface MTLValueTransformer (Deprecated) + ++ (NSValueTransformer *)transformerWithBlock:(id (^)(id))transformationBlock __attribute__((deprecated("Replaced by +transformerUsingForwardBlock:"))); + ++ (NSValueTransformer *)reversibleTransformerWithBlock:(id (^)(id))transformationBlock __attribute__((deprecated("Replaced by +transformerUsingReversibleBlock:"))); + ++ (NSValueTransformer *)reversibleTransformerWithForwardBlock:(id (^)(id))forwardBlock reverseBlock:(id (^)(id))reverseBlock __attribute__((deprecated("Replaced by +transformerUsingForwardBlock:reverseBlock:"))); @end diff --git a/Pods/Mantle/Mantle/MTLValueTransformer.m b/Pods/Mantle/Mantle/MTLValueTransformer.m index 5400d45..701627b 100644 --- a/Pods/Mantle/Mantle/MTLValueTransformer.m +++ b/Pods/Mantle/Mantle/MTLValueTransformer.m @@ -26,15 +26,15 @@ #pragma mark Lifecycle -+ (instancetype)transformerWithBlock:(MTLValueTransformerBlock)transformationBlock { - return [[self alloc] initWithForwardBlock:transformationBlock reverseBlock:nil]; ++ (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardBlock { + return [[self alloc] initWithForwardBlock:forwardBlock reverseBlock:nil]; } -+ (instancetype)reversibleTransformerWithBlock:(MTLValueTransformerBlock)transformationBlock { - return [self reversibleTransformerWithForwardBlock:transformationBlock reverseBlock:transformationBlock]; ++ (instancetype)transformerUsingReversibleBlock:(MTLValueTransformerBlock)reversibleBlock { + return [self transformerUsingForwardBlock:reversibleBlock reverseBlock:reversibleBlock]; } -+ (instancetype)reversibleTransformerWithForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock { ++ (instancetype)transformerUsingForwardBlock:(MTLValueTransformerBlock)forwardBlock reverseBlock:(MTLValueTransformerBlock)reverseBlock { return [[MTLReversibleValueTransformer alloc] initWithForwardBlock:forwardBlock reverseBlock:reverseBlock]; } @@ -57,11 +57,26 @@ } + (Class)transformedValueClass { - return [NSObject class]; + return NSObject.class; } - (id)transformedValue:(id)value { - return self.forwardBlock(value); + NSError *error = nil; + BOOL success = YES; + + return self.forwardBlock(value, &success, &error); +} + +- (id)transformedValue:(id)value success:(BOOL *)outerSuccess error:(NSError **)outerError { + NSError *error = nil; + BOOL success = YES; + + id transformedValue = self.forwardBlock(value, &success, &error); + + if (outerSuccess != NULL) *outerSuccess = success; + if (outerError != NULL) *outerError = error; + + return transformedValue; } @end @@ -82,7 +97,54 @@ } - (id)reverseTransformedValue:(id)value { - return self.reverseBlock(value); + NSError *error = nil; + BOOL success = YES; + + return self.reverseBlock(value, &success, &error); +} + +- (id)reverseTransformedValue:(id)value success:(BOOL *)outerSuccess error:(NSError **)outerError { + NSError *error = nil; + BOOL success = YES; + + id transformedValue = self.reverseBlock(value, &success, &error); + + if (outerSuccess != NULL) *outerSuccess = success; + if (outerError != NULL) *outerError = error; + + return transformedValue; } @end + + +@implementation MTLValueTransformer (Deprecated) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + ++ (instancetype)transformerWithBlock:(id (^)(id))transformationBlock { + return [self transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { + return transformationBlock(value); + }]; +} + ++ (instancetype)reversibleTransformerWithBlock:(id (^)(id))transformationBlock { + return [self transformerUsingReversibleBlock:^(id value, BOOL *success, NSError **error) { + return transformationBlock(value); + }]; +} + ++ (instancetype)reversibleTransformerWithForwardBlock:(id (^)(id))forwardBlock reverseBlock:(id (^)(id))reverseBlock { + return [self + transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { + return forwardBlock(value); + } + reverseBlock:^(id value, BOOL *success, NSError **error) { + return reverseBlock(value); + }]; +} + +#pragma clang diagnostic pop + +@end diff --git a/Pods/Mantle/Mantle/Mantle.h b/Pods/Mantle/Mantle/Mantle.h index 86950a0..102b7ad 100644 --- a/Pods/Mantle/Mantle/Mantle.h +++ b/Pods/Mantle/Mantle/Mantle.h @@ -6,13 +6,22 @@ // Copyright (c) 2012 GitHub. All rights reserved. // +#import + +//! Project version number for Mantle. +FOUNDATION_EXPORT double MantleVersionNumber; + +//! Project version string for Mantle. +FOUNDATION_EXPORT const unsigned char MantleVersionString[]; + #import -#import #import #import #import +#import #import #import +#import #import #import #import diff --git a/Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.h b/Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.h index fd7347c..b8c2b56 100644 --- a/Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.h +++ b/Pods/Mantle/Mantle/NSArray+MTLManipulationAdditions.h @@ -10,19 +10,19 @@ @interface NSArray (MTLManipulationAdditions) -// The first object in the array or nil if the array is empty. -// Forwards to `firstObject` which has been first declared in iOS7, but works with iOS4/10.6. +/// The first object in the array or nil if the array is empty. +/// Forwards to `firstObject` which has been first declared in iOS7, but works with iOS4/10.6. @property (nonatomic, readonly, strong) id mtl_firstObject; -// Returns a new array without all instances of the given object. +/// Returns a new array without all instances of the given object. - (NSArray *)mtl_arrayByRemovingObject:(id)object; -// Returns a new array without the first object. If the array is empty, it -// returns the empty array. +/// Returns a new array without the first object. If the array is empty, it +/// returns the empty array. - (NSArray *)mtl_arrayByRemovingFirstObject; -// Returns a new array without the last object. If the array is empty, it -// returns the empty array. +/// Returns a new array without the last object. If the array is empty, it +/// returns the empty array. - (NSArray *)mtl_arrayByRemovingLastObject; @end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h b/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h new file mode 100644 index 0000000..eb70151 --- /dev/null +++ b/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.h @@ -0,0 +1,27 @@ +// +// NSDictionary+MTLJSONKeyPath.h +// Mantle +// +// Created by Robert Böhnke on 19/03/14. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +#import + +@interface NSDictionary (MTLJSONKeyPath) + +/// Looks up the value of a key path in the receiver. +/// +/// JSONKeyPath - The key path that should be resolved. Every element along this +/// key path needs to be an instance of NSDictionary for the +/// resolving to be successful. +/// success - If not NULL, this will be set to a boolean indicating whether +/// the key path was resolved successfully. +/// error - If not NULL, this may be set to an error that occurs during +/// resolving the value. +/// +/// Returns the value for the key path which may be nil. Clients should inspect +/// the success parameter to decide how to proceed with the result. +- (id)mtl_valueForJSONKeyPath:(NSString *)JSONKeyPath success:(BOOL *)success error:(NSError **)error; + +@end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.m b/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.m new file mode 100644 index 0000000..03ee2ad --- /dev/null +++ b/Pods/Mantle/Mantle/NSDictionary+MTLJSONKeyPath.m @@ -0,0 +1,47 @@ +// +// NSDictionary+MTLJSONKeyPath.m +// Mantle +// +// Created by Robert Böhnke on 19/03/14. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +#import "NSDictionary+MTLJSONKeyPath.h" + +#import "MTLJSONAdapter.h" + +@implementation NSDictionary (MTLJSONKeyPath) + +- (id)mtl_valueForJSONKeyPath:(NSString *)JSONKeyPath success:(BOOL *)success error:(NSError **)error { + NSArray *components = [JSONKeyPath componentsSeparatedByString:@"."]; + + id result = self; + for (NSString *component in components) { + // Check the result before resolving the key path component to not + // affect the last value of the path. + if (result == nil || result == NSNull.null) break; + + if (![result isKindOfClass:NSDictionary.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid JSON dictionary", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"JSON key path %1$@ could not resolved because an incompatible JSON dictionary was supplied: \"%2$@\"", @""), JSONKeyPath, self] + }; + + *error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorInvalidJSONDictionary userInfo:userInfo]; + } + + if (success != NULL) *success = NO; + + return nil; + } + + result = result[component]; + } + + if (success != NULL) *success = YES; + + return result; +} + +@end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h b/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h index 83254d3..6126293 100644 --- a/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h +++ b/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.h @@ -10,16 +10,22 @@ @interface NSDictionary (MTLManipulationAdditions) -// Merges the keys and values from the given dictionary into the receiver. If -// both the receiver and `dictionary` have a given key, the value from -// `dictionary` is used. -// -// Returns a new dictionary containing the entries of the receiver combined with -// those of `dictionary`. +/// Merges the keys and values from the given dictionary into the receiver. If +/// both the receiver and `dictionary` have a given key, the value from +/// `dictionary` is used. +/// +/// Returns a new dictionary containing the entries of the receiver combined with +/// those of `dictionary`. - (NSDictionary *)mtl_dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary; -// Creates a new dictionary with all the entries for the given keys removed from -// the receiver. -- (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys; +/// Creates a new dictionary with all the entries for the given keys removed from +/// the receiver. +- (NSDictionary *)mtl_dictionaryByRemovingValuesForKeys:(NSArray *)keys; + +@end + +@interface NSDictionary (MTLManipulationAdditions_Deprecated) + +- (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys __attribute__((deprecated("Replaced by -mtl_dictionaryByRemovingValuesForKeys:"))); @end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.m b/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.m index 0ed5746..a7a1d7a 100644 --- a/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.m +++ b/Pods/Mantle/Mantle/NSDictionary+MTLManipulationAdditions.m @@ -16,10 +16,23 @@ return result; } -- (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys { +- (NSDictionary *)mtl_dictionaryByRemovingValuesForKeys:(NSArray *)keys { NSMutableDictionary *result = [self mutableCopy]; - [result removeObjectsForKeys:keys.allObjects]; + [result removeObjectsForKeys:keys]; return result; } @end + +@implementation NSDictionary (MTLManipulationAdditions_Deprecated) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + +- (NSDictionary *)mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys { + return [self mtl_dictionaryByRemovingValuesForKeys:keys.allObjects]; +} + +#pragma clang diagnostic pop + +@end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.h b/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.h new file mode 100644 index 0000000..0071c89 --- /dev/null +++ b/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.h @@ -0,0 +1,21 @@ +// +// NSDictionary+MTLMappingAdditions.h +// Mantle +// +// Created by Robert Böhnke on 10/31/13. +// Copyright (c) 2013 GitHub. All rights reserved. +// + +#import + +@interface NSDictionary (MTLMappingAdditions) + +/// Creates an identity mapping for serialization. +/// +/// class - A subclass of MTLModel. +/// +/// Returns a dictionary that maps all properties of the given class to +/// themselves. ++ (NSDictionary *)mtl_identityPropertyMapWithModel:(Class)class; + +@end diff --git a/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.m b/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.m new file mode 100644 index 0000000..6ed8ffc --- /dev/null +++ b/Pods/Mantle/Mantle/NSDictionary+MTLMappingAdditions.m @@ -0,0 +1,23 @@ +// +// NSDictionary+MTLMappingAdditions.m +// Mantle +// +// Created by Robert Böhnke on 10/31/13. +// Copyright (c) 2013 GitHub. All rights reserved. +// + +#import "MTLModel.h" + +#import "NSDictionary+MTLMappingAdditions.h" + +@implementation NSDictionary (MTLMappingAdditions) + ++ (NSDictionary *)mtl_identityPropertyMapWithModel:(Class)class { + NSCParameterAssert([class isSubclassOfClass:MTLModel.class]); + + NSArray *propertyKeys = [class propertyKeys].allObjects; + + return [NSDictionary dictionaryWithObjects:propertyKeys forKeys:propertyKeys]; +} + +@end diff --git a/Pods/Mantle/Mantle/NSError+MTLModelException.h b/Pods/Mantle/Mantle/NSError+MTLModelException.h index f7c1e9e..3c82818 100644 --- a/Pods/Mantle/Mantle/NSError+MTLModelException.h +++ b/Pods/Mantle/Mantle/NSError+MTLModelException.h @@ -10,14 +10,14 @@ @interface NSError (MTLModelException) -// Creates a new error for an exception that occured during updating an -// MTLModel. -// -// exception - The exception that was thrown while updating the model. -// This argument must not be nil. -// -// Returns an error that takes its localized description and failure reason -// from the exception. +/// Creates a new error for an exception that occured during updating an +/// MTLModel. +/// +/// exception - The exception that was thrown while updating the model. +/// This argument must not be nil. +/// +/// Returns an error that takes its localized description and failure reason +/// from the exception. + (instancetype)mtl_modelErrorWithException:(NSException *)exception; @end diff --git a/Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.h b/Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.h index 4f7c03e..0ca13e6 100644 --- a/Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.h +++ b/Pods/Mantle/Mantle/NSObject+MTLComparisonAdditions.h @@ -11,5 +11,5 @@ #import -// Returns whether both objects are identical or equal via -isEqual: +/// Returns whether both objects are identical or equal via -isEqual: BOOL MTLEqualObjects(id obj1, id obj2); diff --git a/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h b/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h index eefceec..ca29b98 100644 --- a/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h +++ b/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.h @@ -10,12 +10,12 @@ @interface NSValueTransformer (MTLInversionAdditions) -// Flips the direction of the receiver's transformation, such that -// -transformedValue: will become -reverseTransformedValue:, and vice-versa. -// -// The receiver must allow reverse transformation. -// -// Returns an inverted transformer. +/// Flips the direction of the receiver's transformation, such that +/// -transformedValue: will become -reverseTransformedValue:, and vice-versa. +/// +/// The receiver must allow reverse transformation. +/// +/// Returns an inverted transformer. - (NSValueTransformer *)mtl_invertedTransformer; @end diff --git a/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.m b/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.m index 71fe4b0..2e536d6 100644 --- a/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.m +++ b/Pods/Mantle/Mantle/NSValueTransformer+MTLInversionAdditions.m @@ -7,6 +7,7 @@ // #import "NSValueTransformer+MTLInversionAdditions.h" +#import "MTLTransformerErrorHandling.h" #import "MTLValueTransformer.h" @implementation NSValueTransformer (MTLInversionAdditions) @@ -14,11 +15,23 @@ - (NSValueTransformer *)mtl_invertedTransformer { NSParameterAssert(self.class.allowsReverseTransformation); - return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(id value) { - return [self reverseTransformedValue:value]; - } reverseBlock:^(id value) { - return [self transformedValue:value]; - }]; + if ([self conformsToProtocol:@protocol(MTLTransformerErrorHandling)]) { + NSParameterAssert([self respondsToSelector:@selector(reverseTransformedValue:success:error:)]); + + id errorHandlingSelf = (id)self; + + return [MTLValueTransformer transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { + return [errorHandlingSelf reverseTransformedValue:value success:success error:error]; + } reverseBlock:^(id value, BOOL *success, NSError **error) { + return [errorHandlingSelf transformedValue:value success:success error:error]; + }]; + } else { + return [MTLValueTransformer transformerUsingForwardBlock:^(id value, BOOL *success, NSError **error) { + return [self reverseTransformedValue:value]; + } reverseBlock:^(id value, BOOL *success, NSError **error) { + return [self transformedValue:value]; + }]; + } } @end diff --git a/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h b/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h index 78a6b19..5369bf5 100644 --- a/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h +++ b/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h @@ -8,77 +8,72 @@ #import -// The name for a value transformer that converts strings into URLs and back. +#import "MTLTransformerErrorHandling.h" + +/// The name for a value transformer that converts strings into URLs and back. extern NSString * const MTLURLValueTransformerName; -// Ensure an NSNumber is backed by __NSCFBoolean/CFBooleanRef -// -// NSJSONSerialization, and likely other serialization libraries, ordinarily -// serialize NSNumbers as numbers, and thus booleans would be serialized as -// 0/1. The exception is when the NSNumber is backed by __NSCFBoolean, which, -// though very much an implementation detail, is detected and serialized as a -// proper boolean. +/// Ensure an NSNumber is backed by __NSCFBoolean/CFBooleanRef +/// +/// NSJSONSerialization, and likely other serialization libraries, ordinarily +/// serialize NSNumbers as numbers, and thus booleans would be serialized as +/// 0/1. The exception is when the NSNumber is backed by __NSCFBoolean, which, +/// though very much an implementation detail, is detected and serialized as a +/// proper boolean. extern NSString * const MTLBooleanValueTransformerName; @interface NSValueTransformer (MTLPredefinedTransformerAdditions) -// Creates a reversible transformer to convert a JSON dictionary into a MTLModel -// object, and vice-versa. -// -// modelClass - The MTLModel subclass to attempt to parse from the JSON. This -// class must conform to . This argument must -// not be nil. -// -// Returns a reversible transformer which uses MTLJSONAdapter for transforming -// values back and forth. -+ (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass; +/// An optionally reversible transformer which applies the given transformer to +/// each element of an array. +/// +/// transformer - The transformer to apply to each element. If the transformer +/// is reversible, the transformer returned by this method will be +/// reversible. This argument must not be nil. +/// +/// Returns a transformer which applies a transformation to each element of an +/// array. ++ (NSValueTransformer *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer; -// Creates a reversible transformer to convert an array of JSON dictionaries -// into an array of MTLModel objects, and vice-versa. -// -// modelClass - The MTLModel subclass to attempt to parse from each JSON -// dictionary. This class must conform to . -// This argument must not be nil. -// -// Returns a reversible transformer which uses MTLJSONAdapter for transforming -// array elements back and forth. -+ (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass; +/// A reversible value transformer to transform between the keys and objects of a +/// dictionary. +/// +/// dictionary - The dictionary whose keys and values should be +/// transformed between. This argument must not be nil. +/// defaultValue - The result to fall back to, in case no key matching the +/// input value was found during a forward transformation. +/// reverseDefaultValue - The result to fall back to, in case no value matching +/// the input value was found during a reverse +/// transformation. +/// +/// Can for example be used for transforming between enum values and their string +/// representation. +/// +/// NSValueTransformer *valueTransformer = [NSValueTransformer mtl_valueMappingTransformerWithDictionary:@{ +/// @"foo": @(EnumDataTypeFoo), +/// @"bar": @(EnumDataTypeBar), +/// } defaultValue: @(EnumDataTypeUndefined) reverseDefaultValue: @"undefined"]; +/// +/// Returns a transformer which will map from keys to objects for forward +/// transformations, and from objects to keys for reverse transformations. ++ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue; -// A reversible value transformer to transform between the keys and objects of a -// dictionary. -// -// dictionary - The dictionary whose keys and values should be -// transformed between. This argument must not be nil. -// defaultValue - The result to fall back to, in case no key matching the -// input value was found during a forward transformation. -// reverseDefaultValue - The result to fall back to, in case no value matching -// the input value was found during a reverse -// transformation. -// -// Can for example be used for transforming between enum values and their string -// representation. -// -// NSValueTransformer *valueTransformer = [NSValueTransformer mtl_valueMappingTransformerWithDictionary:@{ -// @"foo": @(EnumDataTypeFoo), -// @"bar": @(EnumDataTypeBar), -// } defaultValue: @(EnumDataTypeUndefined) reverseDefaultValue: @"undefined"]; -// -// Returns a transformer that will map from keys to values in dictionary -// for forward transformation, and from values to keys for reverse -// transformations. If no matching key or value can be found, the respective -// default value is returned. -+ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue; +/// Returns a value transformer created by calling +/// `+mtl_valueMappingTransformerWithDictionary:defaultValue:reverseDefaultValue:` +/// with a default value of `nil` and a reverse default value of `nil`. ++ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary; -// Returns a value transformer created by calling -// `+mtl_valueMappingTransformerWithDictionary:defaultValue:reverseDefaultValue:` -// with a default value of `nil` and a reverse default value of `nil`. -+ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary; - -@end - -@interface NSValueTransformer (UnavailableMTLPredefinedTransformerAdditions) - -+ (NSValueTransformer *)mtl_externalRepresentationTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +mtl_JSONDictionaryTransformerWithModelClass:"))); -+ (NSValueTransformer *)mtl_externalRepresentationArrayTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +mtl_JSONArrayTransformerWithModelClass:"))); +/// A value transformer that errors if the transformed value are not of the given +/// class. +/// +/// class - The expected class. This argument must not be nil. +/// +/// Returns a transformer which will return an error if the transformed in value +/// is not a member of class. Otherwise, the value is simply passed through. ++ (NSValueTransformer *)mtl_validatingTransformerForClass:(Class)class; + ++ (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[MTLJSONAdapter dictionaryTransformerWithModelClass:]"))); + ++ (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[MTLJSONAdapter arrayTransformerWithModelClass:]"))); @end diff --git a/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m b/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m index 10622a0..407998d 100644 --- a/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m +++ b/Pods/Mantle/Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m @@ -21,20 +21,79 @@ NSString * const MTLBooleanValueTransformerName = @"MTLBooleanValueTransformerNa + (void)load { @autoreleasepool { MTLValueTransformer *URLValueTransformer = [MTLValueTransformer - reversibleTransformerWithForwardBlock:^ id (NSString *str) { - if (![str isKindOfClass:NSString.class]) return nil; - return [NSURL URLWithString:str]; + transformerUsingForwardBlock:^ id (NSString *str, BOOL *success, NSError **error) { + if (str == nil) return nil; + + if (![str isKindOfClass:NSString.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert string to URL", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSString, got: %@.", @""), str], + MTLTransformerErrorHandlingInputValueErrorKey : str + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSURL *result = [NSURL URLWithString:str]; + + if (result == nil) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert string to URL", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Input URL string %@ was malformed", @""), str], + MTLTransformerErrorHandlingInputValueErrorKey : str + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + return result; } - reverseBlock:^ id (NSURL *URL) { - if (![URL isKindOfClass:NSURL.class]) return nil; + reverseBlock:^ id (NSURL *URL, BOOL *success, NSError **error) { + if (URL == nil) return nil; + + if (![URL isKindOfClass:NSURL.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert URL to string", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSURL, got: %@.", @""), URL], + MTLTransformerErrorHandlingInputValueErrorKey : URL + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } return URL.absoluteString; }]; - + [NSValueTransformer setValueTransformer:URLValueTransformer forName:MTLURLValueTransformerName]; MTLValueTransformer *booleanValueTransformer = [MTLValueTransformer - reversibleTransformerWithBlock:^ id (NSNumber *boolean) { - if (![boolean isKindOfClass:NSNumber.class]) return nil; + transformerUsingReversibleBlock:^ id (NSNumber *boolean, BOOL *success, NSError **error) { + if (boolean == nil) return nil; + + if (![boolean isKindOfClass:NSNumber.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert number to boolean-backed number or vice-versa", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSNumber, got: %@.", @""), boolean], + MTLTransformerErrorHandlingInputValueErrorKey : boolean + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } return (NSNumber *)(boolean.boolValue ? kCFBooleanTrue : kCFBooleanFalse); }]; @@ -44,98 +103,189 @@ NSString * const MTLBooleanValueTransformerName = @"MTLBooleanValueTransformerNa #pragma mark Customizable Transformers -+ (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass { - NSParameterAssert([modelClass isSubclassOfClass:MTLModel.class]); - NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]); - - return [MTLValueTransformer - reversibleTransformerWithForwardBlock:^ id (id JSONDictionary) { - if (JSONDictionary == nil) return nil; - - NSAssert([JSONDictionary isKindOfClass:NSDictionary.class], @"Expected a dictionary, got: %@", JSONDictionary); - - return [MTLJSONAdapter modelOfClass:modelClass fromJSONDictionary:JSONDictionary error:NULL]; ++ (NSValueTransformer *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer { + NSParameterAssert(transformer != nil); + + id (^forwardBlock)(NSArray *values, BOOL *success, NSError **error) = ^ id (NSArray *values, BOOL *success, NSError **error) { + if (values == nil) return nil; + + if (![values isKindOfClass:NSArray.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform non-array type", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), values], + MTLTransformerErrorHandlingInputValueErrorKey: values + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; } - reverseBlock:^ id (id model) { - if (model == nil) return nil; + + NSMutableArray *transformedValues = [NSMutableArray arrayWithCapacity:values.count]; + NSInteger index = -1; + for (id value in values) { + index++; + if (value == NSNull.null) { + [transformedValues addObject:NSNull.null]; + continue; + } + + id transformedValue = nil; + if ([transformer conformsToProtocol:@protocol(MTLTransformerErrorHandling)]) { + NSError *underlyingError = nil; + transformedValue = [(id)transformer transformedValue:value success:success error:&underlyingError]; + + if (*success == NO) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Could not transform value at index %d", @""), index], + NSUnderlyingErrorKey: underlyingError, + MTLTransformerErrorHandlingInputValueErrorKey: values + }; - NSAssert([model isKindOfClass:MTLModel.class], @"Expected a MTLModel object, got %@", model); - NSAssert([model conformsToProtocol:@protocol(MTLJSONSerializing)], @"Expected a model object conforming to , got %@", model); + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + return nil; + } + } else { + transformedValue = [transformer transformedValue:value]; + } + + if (transformedValue == nil) continue; + + [transformedValues addObject:transformedValue]; + } + + return transformedValues; + }; + + id (^reverseBlock)(NSArray *values, BOOL *success, NSError **error) = nil; + if (transformer.class.allowsReverseTransformation) { + reverseBlock = ^ id (NSArray *values, BOOL *success, NSError **error) { + if (values == nil) return nil; + + if (![values isKindOfClass:NSArray.class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform non-array type", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), values], + MTLTransformerErrorHandlingInputValueErrorKey: values + }; - return [MTLJSONAdapter JSONDictionaryFromModel:model]; - }]; -} + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + NSMutableArray *transformedValues = [NSMutableArray arrayWithCapacity:values.count]; + NSInteger index = -1; + for (id value in values) { + index++; + if (value == NSNull.null) { + [transformedValues addObject:NSNull.null]; -+ (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass { - NSValueTransformer *dictionaryTransformer = [self mtl_JSONDictionaryTransformerWithModelClass:modelClass]; - - return [MTLValueTransformer - reversibleTransformerWithForwardBlock:^ id (NSArray *dictionaries) { - if (dictionaries == nil) return nil; - - NSAssert([dictionaries isKindOfClass:NSArray.class], @"Expected an array of dictionaries, got: %@", dictionaries); - - NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count]; - for (id JSONDictionary in dictionaries) { - if (JSONDictionary == NSNull.null) { - [models addObject:NSNull.null]; continue; } - - NSAssert([JSONDictionary isKindOfClass:NSDictionary.class], @"Expected a dictionary or an NSNull, got: %@", JSONDictionary); - - id model = [dictionaryTransformer transformedValue:JSONDictionary]; - if (model == nil) continue; - - [models addObject:model]; - } - - return models; - } - reverseBlock:^ id (NSArray *models) { - if (models == nil) return nil; - - NSAssert([models isKindOfClass:NSArray.class], @"Expected an array of MTLModels, got: %@", models); - - NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count]; - for (id model in models) { - if (model == NSNull.null) { - [dictionaries addObject:NSNull.null]; - continue; + + id transformedValue = nil; + if ([transformer respondsToSelector:@selector(reverseTransformedValue:success:error:)]) { + NSError *underlyingError = nil; + transformedValue = [(id)transformer reverseTransformedValue:value success:success error:&underlyingError]; + + if (*success == NO) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform array", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Could not transform value at index %d", @""), index], + NSUnderlyingErrorKey: underlyingError, + MTLTransformerErrorHandlingInputValueErrorKey: values + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + return nil; + } + } else { + transformedValue = [transformer reverseTransformedValue:value]; } - - NSAssert([model isKindOfClass:MTLModel.class], @"Expected an MTLModel or an NSNull, got: %@", model); - - NSDictionary *dict = [dictionaryTransformer reverseTransformedValue:model]; - if (dict == nil) continue; - - [dictionaries addObject:dict]; + + if (transformedValue == nil) continue; + + [transformedValues addObject:transformedValue]; } - - return dictionaries; - }]; + + return transformedValues; + }; + } + if (reverseBlock != nil) { + return [MTLValueTransformer transformerUsingForwardBlock:forwardBlock reverseBlock:reverseBlock]; + } else { + return [MTLValueTransformer transformerUsingForwardBlock:forwardBlock]; + } } -+ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary { - return [self mtl_valueMappingTransformerWithDictionary:dictionary defaultValue:nil reverseDefaultValue:nil]; ++ (NSValueTransformer *)mtl_validatingTransformerForClass:(Class)class { + NSParameterAssert(class != nil); + + return [MTLValueTransformer transformerUsingForwardBlock:^ id (id value, BOOL *success, NSError **error) { + if (value != nil && ![value isKindOfClass:class]) { + if (error != NULL) { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Value did not match expected type", @""), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to be of class %2$@", @""), value, class], + MTLTransformerErrorHandlingInputValueErrorKey : value + }; + + *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo]; + } + *success = NO; + return nil; + } + + return value; + }]; } + (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue { NSParameterAssert(dictionary != nil); NSParameterAssert(dictionary.count == [[NSSet setWithArray:dictionary.allValues] count]); - return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(id key) { - return dictionary[key ?: NSNull.null] ?: defaultValue; - } reverseBlock:^(id object) { - __block id result = nil; - [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id anObject, BOOL *stop) { - if ([object isEqual:anObject]) { - result = key; - *stop = YES; + return [MTLValueTransformer + transformerUsingForwardBlock:^ id (id key, BOOL *success, NSError **error) { + return dictionary[key ?: NSNull.null] ?: defaultValue; } - }]; - return result ?: reverseDefaultValue; - }]; + reverseBlock:^ id (id value, BOOL *success, NSError **error) { + __block id result = nil; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id anObject, BOOL *stop) { + if ([value isEqual:anObject]) { + result = key; + *stop = YES; + } + }]; + + return result ?: reverseDefaultValue; + }]; } ++ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary { + return [self mtl_valueMappingTransformerWithDictionary:dictionary defaultValue:nil reverseDefaultValue:nil]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + ++ (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass { + return [MTLJSONAdapter dictionaryTransformerWithModelClass:modelClass]; +} + ++ (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass { + return [MTLJSONAdapter arrayTransformerWithModelClass:modelClass]; +} + +#pragma clang diagnostic pop + @end diff --git a/Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.m b/Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.m index ab1a8bc..6a034b0 100644 --- a/Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.m +++ b/Pods/Mantle/Mantle/extobjc/EXTRuntimeExtensions.m @@ -9,6 +9,8 @@ #import "EXTRuntimeExtensions.h" +#import + mtl_propertyAttributes *mtl_copyPropertyAttributes (objc_property_t property) { const char * const attrString = property_getAttributes(property); if (!attrString) { diff --git a/Pods/Mantle/README.md b/Pods/Mantle/README.md index 22ce9eb..3a1c6fb 100644 --- a/Pods/Mantle/README.md +++ b/Pods/Mantle/README.md @@ -1,4 +1,4 @@ -# Mantle +# Mantle [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) Mantle makes it easy to write a simple model layer for your Cocoa or Cocoa Touch application. @@ -209,6 +209,8 @@ typedef enum : NSUInteger { return @{ @"URL": @"url", @"HTMLURL": @"html_url", + @"number": @"number", + @"state": @"state", @"reporterLogin": @"user.login", @"assignee": @"assignee", @"updatedAt": @"updated_at" @@ -298,8 +300,7 @@ NSDictionary *JSONDictionary = [MTLJSONAdapter JSONDictionaryFromModel:user]; ### `+JSONKeyPathsByPropertyKey` The dictionary returned by this method specifies how your model object's -properties map to the keys in the JSON representation. Properties that map to -`NSNull` will not be present in the JSON representation, for example: +properties map to the keys in the JSON representation, for example: ```objc @@ -317,8 +318,8 @@ properties map to the keys in the JSON representation. Properties that map to + (NSDictionary *)JSONKeyPathsByPropertyKey { return @{ - @"createdAt": @"created_at", - @"meUser": NSNull.null + @"name": @"name", + @"createdAt": @"created_at" }; } @@ -337,8 +338,7 @@ properties map to the keys in the JSON representation. Properties that map to In this example, the `XYUser` class declares four properties that Mantle handles in different ways: -- `name` is implicitly mapped to a key of the same name in the JSON - representation. +- `name` is mapped to a key of the same name in the JSON representation. - `createdAt` is converted to its snake case equivalent. - `meUser` is not serialized into JSON. - `helper` is initialized exactly once after JSON deserialization. @@ -346,6 +346,9 @@ handles in different ways: Use `-[NSDictionary mtl_dictionaryByAddingEntriesFromDictionary:]` if your model's superclass also implements `MTLJSONSerializing` to merge their mappings. +If you'd like to map all properties of a Model class to themselves, you can use +the `+[NSDictionary mtl_identityPropertyMapWithModel:]` helper method. + When deserializing JSON using `+[MTLJSONAdapter modelOfClass:fromJSONDictionary:error:]`, JSON keys that don't correspond to a property name or have an explicit mapping are ignored: @@ -492,7 +495,7 @@ To add Mantle to your application: application. If you would prefer to use [CocoaPods](http://cocoapods.org), there are some -[Mantle podspecs](https://github.com/CocoaPods/Specs/tree/master/Mantle) that +[Mantle podspecs](https://github.com/CocoaPods/Specs/tree/master/Specs/Mantle) that have been generously contributed by third parties. If you’re instead developing Mantle on its own, use the `Mantle.xcworkspace` file. @@ -505,7 +508,3 @@ Mantle is released under the MIT license. See ## More Info Have a question? Please [open an issue](https://github.com/Mantle/Mantle/issues/new)! - -Mantle also has a chat room on [Slack](https://slack.com/). If you'd like -to join, just [provide your email address](https://github.com/Mantle/Mantle/pull/357) -and we'll happily send you an invite! diff --git a/Pods/OHHTTPStubs/LICENSE b/Pods/OHHTTPStubs/LICENSE deleted file mode 100644 index a83928d..0000000 --- a/Pods/OHHTTPStubs/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -- MIT LICENSE - - -Copyright (c) 2012 Olivier Halligon - -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. \ No newline at end of file diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m deleted file mode 100644 index fa7b6a9..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m +++ /dev/null @@ -1,70 +0,0 @@ -// -// NSURLSessionConfiguration+OHHTTPStubs.m -// OHHTTPStubs -// -// Created by Olivier Halligon on 06/10/13. -// Copyright (c) 2013 AliSoftware. All rights reserved. -// - -#import - -#if defined(__IPHONE_7_0) || defined(__MAC_10_9) - -#import -#import "OHHTTPStubs.h" - - -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! This helper is used to swizzle NSURLSessionConfiguration constructor methods - defaultSessionConfiguration and ephemeralSessionConfiguration to insert the private - OHHTTPStubsProtocol into their protocolClasses array so that OHHTTPStubs is automagically - supported when you create a new NSURLSession based on one of there configurations. - */ - -typedef NSURLSessionConfiguration*(*SessionConfigConstructor)(id,SEL); -static SessionConfigConstructor orig_defaultSessionConfiguration; -static SessionConfigConstructor orig_ephemeralSessionConfiguration; - -static SessionConfigConstructor OHHTTPStubsSwizzle(SEL selector, SessionConfigConstructor newImpl) -{ - Class cls = NSURLSessionConfiguration.class; - Class metaClass = object_getClass(cls); - - Method origMethod = class_getClassMethod(cls, selector); - SessionConfigConstructor origImpl = (SessionConfigConstructor)method_getImplementation(origMethod); - if (!class_addMethod(metaClass, selector, (IMP)newImpl, method_getTypeEncoding(origMethod))) - { - method_setImplementation(origMethod, (IMP)newImpl); - } - return origImpl; -} - -static NSURLSessionConfiguration* OHHTTPStubs_defaultSessionConfiguration(id self, SEL _cmd) -{ - NSURLSessionConfiguration* config = orig_defaultSessionConfiguration(self,_cmd); // call original method - [OHHTTPStubs setEnabled:YES forSessionConfiguration:config]; //OHHTTPStubsAddProtocolClassToNSURLSessionConfiguration(config); - return config; -} - -static NSURLSessionConfiguration* OHHTTPStubs_ephemeralSessionConfiguration(id self, SEL _cmd) -{ - NSURLSessionConfiguration* config = orig_ephemeralSessionConfiguration(self,_cmd); // call original method - [OHHTTPStubs setEnabled:YES forSessionConfiguration:config]; //OHHTTPStubsAddProtocolClassToNSURLSessionConfiguration(config); - return config; -} - -@interface NSURLSessionConfiguration(OHHTTPStubsSupport) @end -@implementation NSURLSessionConfiguration(OHHTTPStubsSupport) -+(void)load -{ - orig_defaultSessionConfiguration = OHHTTPStubsSwizzle(@selector(defaultSessionConfiguration), - OHHTTPStubs_defaultSessionConfiguration); - orig_ephemeralSessionConfiguration = OHHTTPStubsSwizzle(@selector(ephemeralSessionConfiguration), - OHHTTPStubs_ephemeralSessionConfiguration); -} -@end - -#endif - - diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h deleted file mode 100644 index acdcf30..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h +++ /dev/null @@ -1,120 +0,0 @@ -/*********************************************************************************** - * - * Copyright (c) 2012 Olivier Halligon - * - * 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. - * - ***********************************************************************************/ - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Imports - -#import -#import "OHHTTPStubsResponse.h" - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Types - -typedef BOOL(^OHHTTPStubsTestBlock)(NSURLRequest* request); -typedef OHHTTPStubsResponse*(^OHHTTPStubsResponseBlock)(NSURLRequest* request); - -@protocol OHHTTPStubsDescriptor -/*! Arbitrary name that you can set and get to describe your stub. Use it as your own convenience. */ -@property(nonatomic, strong) NSString* name; -@end - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Interface - -/*! Stubs Manager. Use this class to add and remove stubs and stub your network requests. */ -@interface OHHTTPStubs : NSObject - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Adding & Removing stubs - -/*! Dedicated method to add a stub - @param testBlock Block that should return `YES` if the request passed as parameter should be stubbed with the response block, - and `NO` if it should hit the real world (or be managed by another stub). - @param responseBlock Block that will return the `OHHTTPStubsResponse` (response to use for stubbing) corresponding to the given request - @return a stub descriptor that uniquely identifies the stub and can be later used to remove it with `removeStub:`. - @note The returned stub descriptor is retained (`__strong` reference) by `OHHTTPStubs` until it is removed - (with one of the `removeStub:`/`removeLastStub`/`removeAllStubs` methods); it is thus recommended to - keep it in a `__weak` storage (and not `__strong`) in your app code, to let the stub descriptor be destroyed - and let the variable go back to `nil` automatically when the stub is removed. - */ -+(id)stubRequestsPassingTest:(OHHTTPStubsTestBlock)testBlock - withStubResponse:(OHHTTPStubsResponseBlock)responseBlock; - -/*! Remove a stub from the list of stubs - @param stubDesc the stub descriptor that has been returned when adding the stub using `stubRequestsPassingTest:withStubResponse:` - @return `YES` if the stub has been successfully removed, `NO` if the parameter was not a valid stub identifier - */ -+(BOOL)removeStub:(id)stubDesc; - -/*! Remove the last added stub from the stubs list */ -+(void)removeLastStub; - -/*! Remove all the stubs from the stubs list. */ -+(void)removeAllStubs; - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Disabling & Re-Enabling stubs - -/*! Enable or disable the stubs - @param enabled if `YES`, enables the stubs. If `NO`, disable all the stubs and let all the requests hit the real world. - @note OHHTTPStubs are enabled by default, so there is no need to call this method with `YES` for stubs to work, - except if you explicitely disabled the stubs before. - @note This only affects requests that are further made using `NSURLConnection` or using `[NSURLSession sharedSession]`. - This does not affect requests sent on an `NSURLSession` created using an `NSURLSessionConfiguration`. - */ -+(void)setEnabled:(BOOL)enabled; - -#if defined(__IPHONE_7_0) || defined(__MAC_10_9) -/*! - @param enabled If `YES`, enables the stubs for this `NSURLSessionConfiguration`. - If `NO`, disable the stubs and let all the requests hit the real world - @param sessionConfig The NSURLSessionConfiguration on which to enabled/disable the stubs - @note OHHTTPStubs are enabled by default on newly created `defaultSessionConfiguration` and `ephemeralSessionConfiguration`, - so there is no need to call this method with `YES` for stubs to work. You generally only use this if you want to - disable `OHTTPStubs` per `NSURLSession` by calling it before building the `NSURLSession` with the `NSURLSessionConfiguration`. - @note Important: As usual according to the way `NSURLSessionConfiguration` works, you must set this property - *before* creating the `NSURLSession`. Once the `NSURLSession` object is created, they use a deep copy of - the `NSURLSessionConfiguration` object used to create them, so changing the configuration later does not - affect already created sessions. - */ -+ (void)setEnabled:(BOOL)enabled forSessionConfiguration:(NSURLSessionConfiguration *)sessionConfig; -#endif - -#pragma mark - Debug Methods - -/*! List all the installed stubs - @return An array of `id` objects currently installed. Useful for debug. - */ -+(NSArray*)allStubs; - -/*! Setup a block to be called each time a stub is triggered. - - Useful if you want to log all your requests being stubbed for example and see which stub was used to respond to each request. - @param block The block to call each time a request is being stubbed by OHHTTPStubs. Set it to `nil` to do nothing. Defaults is `nil`. - */ -+(void)onStubActivation:( void(^)(NSURLRequest* request, id stub) )block; - -@end - diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m deleted file mode 100644 index 47c94ee..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m +++ /dev/null @@ -1,535 +0,0 @@ -/*********************************************************************************** - * - * Copyright (c) 2012 Olivier Halligon - * - * 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. - * - ***********************************************************************************/ - -#if ! __has_feature(objc_arc) -#error This file is expected to be compiled with ARC turned ON -#endif - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Imports - -#import "OHHTTPStubs.h" - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Types & Constants - -@interface OHHTTPStubsProtocol : NSURLProtocol @end - -static NSTimeInterval const kSlotTime = 0.25; // Must be >0. We will send a chunk of the data from the stream each 'slotTime' seconds - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Private Interfaces - -@interface OHHTTPStubs() -+ (instancetype)sharedInstance; -@property(atomic, copy) NSMutableArray* stubDescriptors; -@property(atomic, copy) void (^onStubActivationBlock)(NSURLRequest*, id); -@end - -@interface OHHTTPStubsDescriptor : NSObject -@property(atomic, copy) OHHTTPStubsTestBlock testBlock; -@property(atomic, copy) OHHTTPStubsResponseBlock responseBlock; -@end - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - OHHTTPStubsDescriptor Implementation - -@implementation OHHTTPStubsDescriptor - -@synthesize name = _name; - -+(instancetype)stubDescriptorWithTestBlock:(OHHTTPStubsTestBlock)testBlock - responseBlock:(OHHTTPStubsResponseBlock)responseBlock -{ - OHHTTPStubsDescriptor* stub = [OHHTTPStubsDescriptor new]; - stub.testBlock = testBlock; - stub.responseBlock = responseBlock; - return stub; -} - --(NSString*)description -{ - return [NSString stringWithFormat:@"<%@ %p : %@>", self.class, self, self.name]; -} - -@end - - - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - OHHTTPStubs Implementation - -@implementation OHHTTPStubs - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Singleton methods - -+ (instancetype)sharedInstance -{ - static OHHTTPStubs *sharedInstance = nil; - - static dispatch_once_t predicate; - dispatch_once(&predicate, ^{ - sharedInstance = [[self alloc] init]; - }); - - return sharedInstance; -} - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Setup & Teardown - -+ (void)initialize -{ - if (self == [OHHTTPStubs class]) - { - [self setEnabled:YES]; - } -} -- (id)init -{ - self = [super init]; - if (self) - { - _stubDescriptors = [NSMutableArray array]; - } - return self; -} - -- (void)dealloc -{ - [self.class setEnabled:NO]; -} - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Public class methods - -#pragma mark > Adding & Removing stubs - -+(id)stubRequestsPassingTest:(OHHTTPStubsTestBlock)testBlock - withStubResponse:(OHHTTPStubsResponseBlock)responseBlock -{ - OHHTTPStubsDescriptor* stub = [OHHTTPStubsDescriptor stubDescriptorWithTestBlock:testBlock - responseBlock:responseBlock]; - [OHHTTPStubs.sharedInstance addStub:stub]; - return stub; -} - -+(BOOL)removeStub:(id)stubDesc -{ - return [OHHTTPStubs.sharedInstance removeStub:stubDesc]; -} -+(void)removeLastStub -{ - [OHHTTPStubs.sharedInstance removeLastStub]; -} -+(void)removeAllStubs -{ - [OHHTTPStubs.sharedInstance removeAllStubs]; -} - -#pragma mark > Disabling & Re-Enabling stubs - -+(void)setEnabled:(BOOL)enable -{ - static BOOL currentEnabledState = NO; - if (enable && !currentEnabledState) - { - [NSURLProtocol registerClass:OHHTTPStubsProtocol.class]; - } - else if (!enable && currentEnabledState) - { - [NSURLProtocol unregisterClass:OHHTTPStubsProtocol.class]; - } - currentEnabledState = enable; -} - -#if defined(__IPHONE_7_0) || defined(__MAC_10_9) -+ (void)setEnabled:(BOOL)enable forSessionConfiguration:(NSURLSessionConfiguration*)sessionConfig -{ - // Runtime check to make sure the API is available on this version - if ( [sessionConfig respondsToSelector:@selector(protocolClasses)] - && [sessionConfig respondsToSelector:@selector(setProtocolClasses:)]) - { - NSMutableArray * urlProtocolClasses = [NSMutableArray arrayWithArray:sessionConfig.protocolClasses]; - Class protoCls = OHHTTPStubsProtocol.class; - if (enable && ![urlProtocolClasses containsObject:protoCls]) - { - [urlProtocolClasses insertObject:protoCls atIndex:0]; - } - else if (!enable && [urlProtocolClasses containsObject:protoCls]) - { - [urlProtocolClasses removeObject:protoCls]; - } - sessionConfig.protocolClasses = urlProtocolClasses; - } - else - { - NSLog(@"[OHHTTPStubs] %@ is only available when running on iOS7+/OSX9+. " - @"Use conditions like 'if ([NSURLSessionConfiguration class])' to only call " - @"this method if the user is running iOS7+/OSX9+.", NSStringFromSelector(_cmd)); - } -} -#endif - -#pragma mark > Debug Methods - -+(NSArray*)allStubs -{ - return [OHHTTPStubs.sharedInstance stubDescriptors]; -} - -+(void)onStubActivation:( void(^)(NSURLRequest* request, id stub) )block -{ - [OHHTTPStubs.sharedInstance setOnStubActivationBlock:block]; -} - - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Private instance methods - --(void)addStub:(OHHTTPStubsDescriptor*)stubDesc -{ - @synchronized(_stubDescriptors) - { - [_stubDescriptors addObject:stubDesc]; - } -} - --(BOOL)removeStub:(id)stubDesc -{ - BOOL handlerFound = NO; - @synchronized(_stubDescriptors) - { - handlerFound = [_stubDescriptors containsObject:stubDesc]; - [_stubDescriptors removeObject:stubDesc]; - } - return handlerFound; -} - --(void)removeLastStub -{ - @synchronized(_stubDescriptors) - { - [_stubDescriptors removeLastObject]; - } -} - --(void)removeAllStubs -{ - @synchronized(_stubDescriptors) - { - [_stubDescriptors removeAllObjects]; - } -} - -- (OHHTTPStubsDescriptor*)firstStubPassingTestForRequest:(NSURLRequest*)request -{ - OHHTTPStubsDescriptor* foundStub = nil; - @synchronized(_stubDescriptors) - { - for(OHHTTPStubsDescriptor* stub in _stubDescriptors.reverseObjectEnumerator) - { - if (stub.testBlock(request)) - { - foundStub = stub; - break; - } - } - } - return foundStub; -} - -@end - - - - - - - - - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Private Protocol Class - -@interface OHHTTPStubsProtocol() -@property(assign) BOOL stopped; -@property(strong) OHHTTPStubsDescriptor* stub; -@end - -@implementation OHHTTPStubsProtocol - -+ (BOOL)canInitWithRequest:(NSURLRequest *)request -{ - return ([OHHTTPStubs.sharedInstance firstStubPassingTestForRequest:request] != nil); -} - -- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)response client:(id)client -{ - // Make super sure that we never use a cached response. - OHHTTPStubsProtocol* proto = [super initWithRequest:request cachedResponse:nil client:client]; - proto.stub = [OHHTTPStubs.sharedInstance firstStubPassingTestForRequest:request]; - return proto; -} - -+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request -{ - return request; -} - -- (NSCachedURLResponse *)cachedResponse -{ - return nil; -} - -- (void)startLoading -{ - NSURLRequest* request = self.request; - id client = self.client; - - if (!self.stub) - { - NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"It seems like the stub has been removed BEFORE the response had time to be sent.", - NSLocalizedFailureReasonErrorKey, - @"For more info, see https://github.com/AliSoftware/OHHTTPStubs/wiki/OHHTTPStubs-and-asynchronous-tests", - NSLocalizedRecoverySuggestionErrorKey, - request.URL, // Stop right here if request.URL is nil - NSURLErrorFailingURLErrorKey, - nil]; - NSError* error = [NSError errorWithDomain:@"OHHTTPStubs" code:500 userInfo:userInfo]; - [client URLProtocol:self didFailWithError:error]; - return; - } - - OHHTTPStubsResponse* responseStub = self.stub.responseBlock(request); - - if (OHHTTPStubs.sharedInstance.onStubActivationBlock) - { - OHHTTPStubs.sharedInstance.onStubActivationBlock(request, self.stub); - } - - if (responseStub.error == nil) - { - NSHTTPURLResponse* urlResponse = [[NSHTTPURLResponse alloc] initWithURL:request.URL - statusCode:responseStub.statusCode - HTTPVersion:@"HTTP/1.1" - headerFields:responseStub.httpHeaders]; - - // Cookies handling - if (request.HTTPShouldHandleCookies && request.URL) - { - NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseStub.httpHeaders forURL:request.URL]; - if (cookies) - { - [NSHTTPCookieStorage.sharedHTTPCookieStorage setCookies:cookies forURL:request.URL mainDocumentURL:request.mainDocumentURL]; - } - } - - - NSString* redirectLocation = (responseStub.httpHeaders)[@"Location"]; - NSURL* redirectLocationURL; - if (redirectLocation) - { - redirectLocationURL = [NSURL URLWithString:redirectLocation]; - } - else - { - redirectLocationURL = nil; - } - if (((responseStub.statusCode >= 300) && (responseStub.statusCode < 400)) && redirectLocationURL) - { - NSURLRequest* redirectRequest = [NSURLRequest requestWithURL:redirectLocationURL]; - execute_after(responseStub.requestTime, ^{ - if (!self.stopped) - { - [client URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:urlResponse]; - } - }); - } - else - { - execute_after(responseStub.requestTime,^{ - if (!self.stopped) - { - [client URLProtocol:self didReceiveResponse:urlResponse cacheStoragePolicy:NSURLCacheStorageNotAllowed]; - if(responseStub.inputStream.streamStatus == NSStreamStatusNotOpen) - { - [responseStub.inputStream open]; - } - [self streamDataForClient:client - withStubResponse:responseStub - completion:^(NSError * error) - { - [responseStub.inputStream close]; - if (error==nil) - { - [client URLProtocolDidFinishLoading:self]; - } - else - { - [client URLProtocol:self didFailWithError:responseStub.error]; - } - }]; - } - }); - } - } else { - // Send the canned error - execute_after(responseStub.responseTime, ^{ - if (!self.stopped) - { - [client URLProtocol:self didFailWithError:responseStub.error]; - } - }); - } -} - -- (void)stopLoading -{ - self.stopped = YES; -} - -typedef struct { - NSTimeInterval slotTime; - double chunkSizePerSlot; - double cumulativeChunkSize; -} OHHTTPStubsStreamTimingInfo; - -- (void)streamDataForClient:(id)client - withStubResponse:(OHHTTPStubsResponse*)stubResponse - completion:(void(^)(NSError * error))completion -{ - if (stubResponse.inputStream.hasBytesAvailable && !self.stopped) - { - // Compute timing data once and for all for this stub - - OHHTTPStubsStreamTimingInfo timingInfo = { - .slotTime = kSlotTime, // Must be >0. We will send a chunk of data from the stream each 'slotTime' seconds - .cumulativeChunkSize = 0 - }; - - if(stubResponse.responseTime < 0) - { - // Bytes send each 'slotTime' seconds = Speed in KB/s * 1000 * slotTime in seconds - timingInfo.chunkSizePerSlot = (fabs(stubResponse.responseTime) * 1000) * timingInfo.slotTime; - } - else if (stubResponse.responseTime < kSlotTime) // includes case when responseTime == 0 - { - // We want to send the whole data quicker than the slotTime, so send it all in one chunk. - timingInfo.chunkSizePerSlot = stubResponse.dataSize; - timingInfo.slotTime = stubResponse.responseTime; - } - else - { - // Bytes send each 'slotTime' seconds = (Whole size in bytes / response time) * slotTime = speed in bps * slotTime in seconds - timingInfo.chunkSizePerSlot = ((stubResponse.dataSize/stubResponse.responseTime) * timingInfo.slotTime); - } - - [self streamDataForClient:client - fromStream:stubResponse.inputStream - timingInfo:timingInfo - completion:completion]; - } - else - { - if (completion) - { - completion(nil); - } - } -} - -- (void) streamDataForClient:(id)client - fromStream:(NSInputStream*)inputStream - timingInfo:(OHHTTPStubsStreamTimingInfo)timingInfo - completion:(void(^)(NSError * error))completion -{ - NSParameterAssert(timingInfo.chunkSizePerSlot > 0); - - if (inputStream.hasBytesAvailable && !self.stopped) - { - // This is needed in case we computed a non-integer chunkSizePerSlot, to avoid cumulative errors - double cumulativeChunkSizeAfterRead = timingInfo.cumulativeChunkSize + timingInfo.chunkSizePerSlot; - NSUInteger chunkSizeToRead = floor(cumulativeChunkSizeAfterRead) - floor(timingInfo.cumulativeChunkSize); - timingInfo.cumulativeChunkSize = cumulativeChunkSizeAfterRead; - - if (chunkSizeToRead == 0) - { - // Nothing to read at this pass, but probably later - execute_after(timingInfo.slotTime, ^{ - [self streamDataForClient:client fromStream:inputStream - timingInfo:timingInfo completion:completion]; - }); - } else { - uint8_t* buffer = (uint8_t*)malloc(sizeof(uint8_t)*chunkSizeToRead); - NSInteger bytesRead = [inputStream read:buffer maxLength:chunkSizeToRead]; - if (bytesRead > 0) - { - NSData * data = [NSData dataWithBytes:buffer length:bytesRead]; - // Wait for 'slotTime' seconds before sending the chunk. - // If bytesRead < chunkSizePerSlot (because we are near the EOF), adjust slotTime proportionally to the bytes remaining - execute_after(((double)bytesRead / (double)chunkSizeToRead) * timingInfo.slotTime, ^{ - [client URLProtocol:self didLoadData:data]; - [self streamDataForClient:client fromStream:inputStream - timingInfo:timingInfo completion:completion]; - }); - } - else - { - if (completion) - { - // Note: We may also arrive here with no error if we were just at the end of the stream (EOF) - // In that case, hasBytesAvailable did return YES (because at the limit of OEF) but nothing were read (because EOF) - // But then in that case inputStream.streamError will be nil so that's cool, we won't return an error anyway - completion(inputStream.streamError); - } - } - free(buffer); - } - } - else - { - if (completion) - { - completion(nil); - } - } -} - -///////////////////////////////////////////// -// Delayed execution utility methods -///////////////////////////////////////////// - -static void execute_after(NSTimeInterval delayInSeconds, dispatch_block_t block) -{ - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); - dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block); -} - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h deleted file mode 100644 index 40c01a4..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// OHHTTPStubsResponse+HTTPMessage.h -// OHHTTPStubs -// -// Created by Olivier Halligon on 01/09/13. -// Copyright (c) 2013 AliSoftware. All rights reserved. -// - -#import "OHHTTPStubsResponse.h" - -@interface OHHTTPStubsResponse (HTTPMessage) - -/*! @name Building a response from HTTP Message data */ - -// TODO: Try to implement it using NSInputStream someday? - -/*! Builds a response given a message data as returned by `curl -is [url]`, that is containing both the headers and the body. - This method will split the headers and the body and build a OHHTTPStubsReponse accordingly - @param responseData The NSData containing the whole HTTP response, including the headers and the body - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - */ -+(instancetype)responseWithHTTPMessageData:(NSData*)responseData; - -/*! Builds a response given the name of a `"*.response"` file containing both the headers and the body. - The response file is expected to be in the specified bundle (or the application bundle if nil). - This method will split the headers and the body and build a OHHTTPStubsReponse accordingly - @param responseName The name of the `"*.response"` file (without extension) containing the whole HTTP response (including the headers and the body) - @param bundleOrNil The bundle in which the `"*.response"` file is located. If `nil`, the `[NSBundle bundleForClass:self.class]` will be used. - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - */ -+(instancetype)responseNamed:(NSString*)responseName - inBundle:(NSBundle*)bundleOrNil; - - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m deleted file mode 100644 index 03d0e7a..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// OHHTTPStubsResponse+HTTPMessage.m -// OHHTTPStubs -// -// Created by Olivier Halligon on 01/09/13. -// Copyright (c) 2013 AliSoftware. All rights reserved. -// - -#import "OHHTTPStubsResponse+HTTPMessage.h" - -@implementation OHHTTPStubsResponse (HTTPMessage) - -#pragma mark Building response from HTTP Message Data (dump from "curl -is") - -+(instancetype)responseWithHTTPMessageData:(NSData*)responseData; -{ - NSData *data = [NSData data]; - NSInteger statusCode = 200; - NSDictionary *headers = @{}; - - CFHTTPMessageRef httpMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE); - if (httpMessage) - { - CFHTTPMessageAppendBytes(httpMessage, responseData.bytes, responseData.length); - - data = responseData; // By default - - if (CFHTTPMessageIsHeaderComplete(httpMessage)) - { - statusCode = (NSInteger)CFHTTPMessageGetResponseStatusCode(httpMessage); - headers = (__bridge_transfer NSDictionary *)CFHTTPMessageCopyAllHeaderFields(httpMessage); - data = (__bridge_transfer NSData *)CFHTTPMessageCopyBody(httpMessage); - } - CFRelease(httpMessage); - } - - return [self responseWithData:data - statusCode:(int)statusCode - headers:headers]; -} - -+(instancetype)responseNamed:(NSString*)responseName - inBundle:(NSBundle*)responsesBundle -{ - NSURL *responseURL = [responsesBundle?:[NSBundle bundleForClass:self.class] URLForResource:responseName - withExtension:@"response"]; - - NSData *responseData = [NSData dataWithContentsOfURL:responseURL]; - NSAssert(responseData, @"Could not find HTTP response named '%@' in bundle '%@'", responseName, responsesBundle); - - return [self responseWithHTTPMessageData:responseData]; -} - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h deleted file mode 100644 index 1934c10..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// OHHTTPStubsResponse+JSON.h -// OHHTTPStubs -// -// Created by Olivier Halligon on 01/09/13. -// Copyright (c) 2013 AliSoftware. All rights reserved. -// - -#import "OHHTTPStubsResponse.h" - -@interface OHHTTPStubsResponse (JSON) - -/*! Builds a response given a JSON object for the response body, status code, and headers. - @param jsonObject Object representing the response body. - Typically a `NSDictionary`; may be any object accepted by `+[NSJSONSerialization dataWithJSONObject:options:error:]` - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - If a "Content-Type" header is not included, "Content-Type: application/json" will be added. - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - - @note This method typically calls responseWithData:statusCode:headers: passing the serialized JSON object as the data parameter and adding the Content-Type header if necessary. - */ -+ (instancetype)responseWithJSONObject:(id)jsonObject - statusCode:(int)statusCode - headers:(NSDictionary *)httpHeaders; - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m deleted file mode 100644 index aebcb99..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// OHHTTPStubsResponse+JSON.m -// OHHTTPStubs -// -// Created by Olivier Halligon on 01/09/13. -// Copyright (c) 2013 AliSoftware. All rights reserved. -// - -#import "OHHTTPStubsResponse+JSON.h" - -@implementation OHHTTPStubsResponse (JSON) - -/*! @name Building a response from JSON objects */ - -+ (instancetype)responseWithJSONObject:(id)jsonObject - statusCode:(int)statusCode - headers:(NSDictionary *)httpHeaders -{ - if (!httpHeaders[@"Content-Type"]) - { - NSMutableDictionary* mutableHeaders = [NSMutableDictionary dictionaryWithDictionary:httpHeaders]; - mutableHeaders[@"Content-Type"] = @"application/json"; - httpHeaders = [NSDictionary dictionaryWithDictionary:mutableHeaders]; // make immutable again - } - - return [self responseWithData:[NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:nil] - statusCode:statusCode - headers:httpHeaders]; -} - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h deleted file mode 100644 index 95c85f8..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h +++ /dev/null @@ -1,219 +0,0 @@ -/*********************************************************************************** - * - * Copyright (c) 2012 Olivier Halligon - * - * 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. - * - ***********************************************************************************/ - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Imports - -#import - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Defines & Constants - -// Standard download speeds. -extern const double -OHHTTPStubsDownloadSpeedGPRS, -OHHTTPStubsDownloadSpeedEDGE, -OHHTTPStubsDownloadSpeed3G, -OHHTTPStubsDownloadSpeed3GPlus, -OHHTTPStubsDownloadSpeedWifi; - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Interface - -/*! Stubs Response. This describes a stubbed response to be returned by the URL Loading System, including its - HTTP headers, body, statusCode and response time. */ -@interface OHHTTPStubsResponse : NSObject - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Properties - -@property(nonatomic, strong) NSDictionary* httpHeaders; -@property(nonatomic, assign) int statusCode; -@property(nonatomic, strong) NSInputStream* inputStream; -@property(nonatomic, assign) unsigned long long dataSize; -@property(nonatomic, assign) NSTimeInterval requestTime; //!< Defaults to 0.0 -//! @note if responseTime<0, it is interpreted as a download speed in KBps ( -200 => 200KB/s ) -@property(nonatomic, assign) NSTimeInterval responseTime; -@property(nonatomic, strong) NSError* error; - - - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Commodity Constructors -/*! @name Commodity */ - -/* -------------------------------------------------------------------------- */ -#pragma mark > Building response from NSData - -/*! Builds a response given raw data. - @note Internally calls `-initWithInputStream:dataSize:statusCode:headers:` with and inputStream build from the NSData. - - @param data The raw data to return in the response - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - */ -+(instancetype)responseWithData:(NSData*)data - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders; - - -/* -------------------------------------------------------------------------- */ -#pragma mark > Building response from a file - -/*! Useful macro to build a path given a file name and a bundle. - @param fileName The name of the file to get the path to, including file extension - @param bundleOrNil The bundle in which the file is located. If nil, the application bundle (`[NSBundle bundleForClass:self.class]`) is used - @return The path of the given file in the given bundle - */ -#define OHPathForFileInBundle(fileName,bundleOrNil) ({ \ - [(bundleOrNil?:[NSBundle bundleForClass:self.class]) pathForResource:[fileName stringByDeletingPathExtension] ofType:[fileName pathExtension]]; \ -}) - -/*! Useful macro to build a path to a file in the Documents's directory in the app sandbox, used by iTunes File Sharing for example. - @param fileName The name of the file to get the path to, including file extension - @return The path of the file in the Documents directory in your App Sandbox - */ -#define OHPathForFileInDocumentsDir(fileName) ({ \ - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); \ - NSString *basePath = (paths.count > 0) ? [paths objectAtIndex:0] : nil; \ - [basePath stringByAppendingPathComponent:fileName]; \ -}) - -/*! Useful macro to build an NSBundle located in the application's resources simply from its name - @param bundleBasename The base name, without extension (extension is assumed to be ".bundle"). - @return The NSBundle object representing the bundle with the given basename located in your application's resources. - */ -#define OHResourceBundle(bundleBasename) ({ \ - [NSBundle bundleWithPath:[[NSBundle bundleForClass:self.class] pathForResource:bundleBasename ofType:@"bundle"]]; \ -}) - - -/*! Builds a response given a file path, the status code and headers. - @param filePath The file path that contains the response body to return. - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - @note It is encouraged to use the `OHPathForFileInBundle(fileName, bundleOrNil)` and `OHResourceBundle(bundleBasename)` macros - to easily build a path to a file located in the app bundle or any arbitrary bundle. - Likewise, you may use the `OHPathForFileInDocumentsDir(fileName)` macro to build a path to a file located in - the Documents directory of your application' sandbox. - */ -+(instancetype)responseWithFileAtPath:(NSString *)filePath - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders; - -/* -------------------------------------------------------------------------- */ -#pragma mark > Building an error response - -/*! Builds a response that corresponds to the given error - @param error The error to use in the stubbed response. - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - @note For example you could use an error like `[NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil]` - */ -+(instancetype)responseWithError:(NSError*)error; - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Commotidy Setters - -/*! Set the `responseTime` of the `OHHTTPStubsResponse` and return `self`. Useful for chaining method calls. - - _Usage example:_ -
return [[OHHTTPStubsReponse responseWithData:data statusCode:200 headers:nil] responseTime:5.0];
- - @param responseTime If positive, the amount of time used to send the entire response. - If negative, the rate in KB/s at which to send the response data. - Useful to simulate slow networks for example. You may use the OHHTTPStubsDownloadSpeed* constants here. - @return `self` (= the same `OHHTTPStubsResponse` that was the target of this method). Useful for chaining method calls. - */ --(instancetype)responseTime:(NSTimeInterval)responseTime; - -/*! Set both the `requestTime` and the `responseTime` of the `OHHTTPStubsResponse` at once. Useful for chaining method calls. - - _Usage example:_ -
return [[OHHTTPStubsReponse responseWithData:data statusCode:200 headers:nil]
-               requestTime:1.0 responseTime:5.0];
- - @param requestTime The time to wait before the response begins to send. This value must be greater than or equal to zero. - @param responseTime If positive, the amount of time used to send the entire response. - If negative, the rate in KB/s at which to send the response data. - Useful to simulate slow networks for example. You may use the OHHTTPStubsDownloadSpeed* constants here. - @return `self` (= the same `OHHTTPStubsResponse` that was the target of this method). Useful for chaining method calls. - */ --(instancetype)requestTime:(NSTimeInterval)requestTime responseTime:(NSTimeInterval)responseTime; - - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Initializers -/*! @name Initializers */ - -/*! Designed initializer. Initialize a response with the given input stream, dataSize, statusCode and headers. - @param inputStream The input stream that will provide the data to return in the response - @param dataSize The size of the data in the stream. - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - @note You will probably never need to call this method yourself. Prefer the other initializers (that will call this method eventually) - */ --(instancetype)initWithInputStream:(NSInputStream*)inputStream - dataSize:(unsigned long long)dataSize - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders; - - -/*! Initialize a response with a given file path, statusCode and headers. - @param filePath The file path of the data to return in the response - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - @note This method simply builds the NSInputStream, compute the file size, and then call `-initWithInputStream:dataSize:statusCode:headers:` - */ --(instancetype)initWithFileAtPath:(NSString*)filePath - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders; - - -/*! Initialize a response with the given data, statusCode and headers. - @param data The raw data to return in the response - @param statusCode The HTTP Status Code to use in the response - @param httpHeaders The HTTP Headers to return in the response - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - */ --(instancetype)initWithData:(NSData*)data - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders; - - -/*! Designed initializer. Initialize a response with the given error. - @param error The error to use in the stubbed response. - @return An `OHHTTPStubsResponse` describing the corresponding response to return by the stub - @note For example you could use an error like `[NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil]` - */ --(instancetype)initWithError:(NSError*)error; - -@end diff --git a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m b/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m deleted file mode 100644 index 69d846a..0000000 --- a/Pods/OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m +++ /dev/null @@ -1,187 +0,0 @@ -/*********************************************************************************** - * - * Copyright (c) 2012 Olivier Halligon - * - * 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. - * - ***********************************************************************************/ - -#if ! __has_feature(objc_arc) -#error This file is expected to be compiled with ARC turned ON -#endif - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Imports - -#import "OHHTTPStubsResponse.h" - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Defines & Constants - -const double OHHTTPStubsDownloadSpeedGPRS =- 56 / 8; // kbps -> KB/s -const double OHHTTPStubsDownloadSpeedEDGE =- 128 / 8; // kbps -> KB/s -const double OHHTTPStubsDownloadSpeed3G =- 3200 / 8; // kbps -> KB/s -const double OHHTTPStubsDownloadSpeed3GPlus =- 7200 / 8; // kbps -> KB/s -const double OHHTTPStubsDownloadSpeedWifi =- 12000 / 8; // kbps -> KB/s - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Implementation - -@implementation OHHTTPStubsResponse - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Commodity Constructors - - -#pragma mark > Building response from NSData - -+(instancetype)responseWithData:(NSData*)data - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders -{ - OHHTTPStubsResponse* response = [[self alloc] initWithData:data - statusCode:statusCode - headers:httpHeaders]; - return response; -} - - -#pragma mark > Building response from a file - -+(instancetype)responseWithFileAtPath:(NSString *)filePath - statusCode:(int)statusCode - headers:(NSDictionary *)httpHeaders -{ - OHHTTPStubsResponse* response = [[self alloc] initWithFileAtPath:filePath - statusCode:statusCode - headers:httpHeaders]; - return response; -} - - -#pragma mark > Building an error response - -+(instancetype)responseWithError:(NSError*)error -{ - OHHTTPStubsResponse* response = [[self alloc] initWithError:error]; - return response; -} - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Commotidy Setters - --(instancetype)responseTime:(NSTimeInterval)responseTime -{ - _responseTime = responseTime; - return self; -} - --(instancetype)requestTime:(NSTimeInterval)requestTime responseTime:(NSTimeInterval)responseTime -{ - _requestTime = requestTime; - _responseTime = responseTime; - return self; -} - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Initializers - --(instancetype)initWithInputStream:(NSInputStream*)inputStream - dataSize:(unsigned long long)dataSize - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders -{ - self = [super init]; - if (self) - { - _inputStream = inputStream; - _dataSize = dataSize; - _statusCode = statusCode; - NSMutableDictionary * headers = [NSMutableDictionary dictionaryWithDictionary:httpHeaders]; - static NSString *const ContentLengthHeader = @"Content-Length"; - if (!headers[ContentLengthHeader]) - { - headers[ContentLengthHeader] = [NSString stringWithFormat:@"%llu",_dataSize]; - } - _httpHeaders = [NSDictionary dictionaryWithDictionary:headers]; - } - return self; -} - --(instancetype)initWithFileAtPath:(NSString*)filePath - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders -{ - NSInputStream* inputStream; - if (filePath) - { - inputStream = [NSInputStream inputStreamWithFileAtPath:filePath]; - } - else - { - NSLog(@"%s: nil file path. Returning empty data", __PRETTY_FUNCTION__); - inputStream = [NSInputStream inputStreamWithData:[NSData data]]; - } - - NSDictionary* attributes = [NSFileManager.defaultManager attributesOfItemAtPath:filePath error:nil]; - unsigned long long fileSize = [[attributes valueForKey:NSFileSize] unsignedLongLongValue]; - self = [self initWithInputStream:inputStream - dataSize:fileSize - statusCode:statusCode - headers:httpHeaders]; - return self; -} - --(instancetype)initWithData:(NSData*)data - statusCode:(int)statusCode - headers:(NSDictionary*)httpHeaders -{ - NSInputStream* inputStream = [NSInputStream inputStreamWithData:data?:[NSData data]]; - self = [self initWithInputStream:inputStream - dataSize:data.length - statusCode:statusCode - headers:httpHeaders]; - return self; -} - --(instancetype)initWithError:(NSError*)error -{ - self = [super init]; - if (self) { - _error = error; - } - return self; -} - --(NSString*)debugDescription -{ - return [NSString stringWithFormat:@"<%@ %p requestTime:%f responseTime:%f status:%d dataSize:%llu>", - self.class, self, self.requestTime, self.responseTime, self.statusCode, self.dataSize]; -} - -//////////////////////////////////////////////////////////////////////////////// -#pragma mark - Accessors - --(void)setRequestTime:(NSTimeInterval)requestTime -{ - NSAssert(requestTime >= 0, @"Invalid Request Time (%f) for OHHTTPStubResponse. Request time must be greater than or equal to zero",requestTime); - _requestTime = requestTime; -} - -@end diff --git a/Pods/OHHTTPStubs/README.md b/Pods/OHHTTPStubs/README.md deleted file mode 100644 index b0e85e2..0000000 --- a/Pods/OHHTTPStubs/README.md +++ /dev/null @@ -1,123 +0,0 @@ -OHHTTPStubs -=========== - -[![Version](http://cocoapod-badges.herokuapp.com/v/OHHTTPStubs/badge.png)](http://cocoadocs.org/docsets/OHHTTPStubs) -[![Platform](http://cocoapod-badges.herokuapp.com/p/OHHTTPStubs/badge.png)](http://cocoadocs.org/docsets/OHHTTPStubs) -[![Build Status](https://travis-ci.org/AliSoftware/OHHTTPStubs.png?branch=master)](https://travis-ci.org/AliSoftware/OHHTTPStubs) - -`OHHTTPStubs` is a library designed to stub your network requests very easily. It can help you: - -* test your apps with **fake network data** (stubbed from file) and **simulate slow networks**, to check your application behavior in bad network conditions -* write **Unit Tests** that use fake network data from your fixtures. - -It works with `NSURLConnection`, new iOS7/OSX.9's `NSURLSession`, `AFNetworking` (both 1.x and 2.x), or any networking framework that use Cocoa's URL Loading System. - -[![Donate](http://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TRTU3UEWEHV92 "Donate") - ----- - -# Documentation & Usage Examples - -`OHHTTPStubs` headers are fully documented using Appledoc-like / Headerdoc-like comments in the header files. You can also [read the **online documentation** here](http://cocoadocs.org/docsets/OHHTTPStubs) -[![Version](http://cocoapod-badges.herokuapp.com/v/OHHTTPStubs/badge.png)](http://cocoadocs.org/docsets/OHHTTPStubs) - -> Unfortunately macro documentation does not appear in the documentation generated by appledoc, so don't hesitate to take a look into `OHHTTPStubsResponse.h`, `OHHTTPStubsResponse+JSON.h` and `OHHTTPStubsResponse+HTTPMessage.h` too. - -### Basic usage example - - [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { - return [request.URL.host isEqualToString:@"mywebservice.com"]; - } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { - // Stub it with our "wsresponse.json" stub file - NSString* fixture = OHPathForFileInBundle(@"wsresponse.json",nil); - return [OHHTTPStubsResponse responseWithFileAtPath:fixture - statusCode:200 headers:@{@"Content-Type":@"text/json"}]; - }]; - -### [More examples](https://github.com/AliSoftware/OHHTTPStubs/wiki/Usage-Examples) - -For a lot more examples, see the dedicated "[Usage Examples](https://github.com/AliSoftware/OHHTTPStubs/wiki/Usage-Examples)" wiki page. - -### [Help Topics](https://github.com/AliSoftware/OHHTTPStubs/wiki) - -The wiki also contain [some articles that can help you get started](https://github.com/AliSoftware/OHHTTPStubs/wiki) with (and troubleshoot if needed) `OHHTTPStubs`. - -# Compatibility - -`OHHTTPStubs` is compatible with **iOS 5.0+** and **OSX 10.7+**. - -`OHHTTPStubs` also works with iOS7's and OSX 10.9's `NSURLSession` mechanism. - -# Special Considerations - -## Using OHHTTPStubs in your Unit Tests - -`OHHTTPStubs` is ideal to write Unit Tests that normally would perform network requests. But if you use it in your Unit Tests, don't forget to: - -* remove any stubs you installed after each test — to avoid those stubs to still be installed when executing the next Test Case — by calling `[OHHTTPStubs removeAllStubs]` in you `tearDown` method. [see this wiki page for more info](https://github.com/AliSoftware/OHHTTPStubs/wiki/Remove-stubs-after-each-test) -* be sure to wait until the request has received its response before doing your assertions and letting the test case to finish (like for any asynchronous test). [see this wiki page for more info](https://github.com/AliSoftware/OHHTTPStubs/wiki/OHHTTPStubs-and-asynchronous-tests) - -### XCTestExpectation & Xcode 5 - -To help you with asynchronous tests, you should use the `XCTestExpectation` class. - -This class is available in Xcode 6, but if you still compile with Xcode 5, you can **use the `XCTestExpectation` subspec provided by `OHHTTPStubs`** that adds a custom implementation of this `XCTestExpectation` class that **allows you to use it with Xcode 5 too**. - -``` -pod 'OHHTTPStubs/XCTestExpectation' -``` - -## Automatic loading - -In general, `OHHTTPStubs` is automatically enabled by default, both for: - -* requests made using `NSURLConnection` or `[NSURLSession sharedSession]`; -* requests made using a `NSURLSession` created using a `[NSURLSessionConfiguration defaultSessionConfiguration]` or `[NSURLSessionConfiguration ephemeralSessionConfiguration]` configuration (using `[NSURLSession sessionWithConfiguration:…]`-like methods). - -If you need to disable (and re-enable) `OHHTTPStubs` globally or per session, you can use: - -* `[OHHTTPStubs setEnabled:]` for `NSURLConnection`/`[NSURLSession sharedSession]`-based requests -* `[OHHTTPStubs setEnabled:forSessionConfiguration:]` for requests sent on a session created using `[NSURLSession sessionWithConfiguration:...]`. Note that you have to call this before creating the `NSURLSession` as the `NSURLSessionConfiguration` is deep-copied on the creation of the `NSURLSession` instance and cannot be modified afterwards. - -_In practice, there is no need to ever explicitly call `setEnabled:` or `setEnabled:forSessionConfiguration:` using `YES`, as this is the default._ - -## Known limitations - -* `OHHTTPStubs` **can't work on background sessions** (sessions created using `[NSURLSessionConfiguration backgroundSessionConfiguration]`) because background sessions don't allow the use of custom `NSURLProtocols` and are handled by the iOS Operating System itself. -* `OHHTTPStubs` don't simulate data upload. The `NSURLProtocolClient` `@protocol` does not provide a way to signal the delegate that data has been **sent** (only that some has been loaded), so any data in the `HTTPBody` or `HTTPBodyStream` of an `NSURLRequest`, or data provided to `-[NSURLSession uploadTaskWithRequest:fromData:];` will be ignored, and more importantly, the `-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:` delegate method will never be called when you stub the request using `OHHTTPStubs`. - -_As far as I know, there's nothing we can do about those two limitations. Please let me know if you know a solution that would make that possible anyway._ - - -# Installing in your projects - -**The recommanded way to use `OHHTTPStubs` is via [CocoaPods](http://cocoapods.org/)**. -Simply add `pod 'OHHTTPStubs'` to your `Podfile` then run `pod install` and you are ready to use it. - -_Note: `OHHTTPStubs` requires iOS5 minimum._ - -> **Warning: Be careful anyway to include `OHHTTPStubs` only in your test targets, or only use it in `#if DEBUG` portions, if you don't want your stubs to still be included in your release for the AppStore!** - -In case you don't want to use CocoaPods (but you should!!!), the `OHHTTPStubs` project is provided as a Xcode project that generates a static library, so simply add its xcodeproj to your workspace and link your app against the `libOHHTTPStubs.a` library. See [here](https://github.com/AliSoftware/OHHTTPStubs/wiki/Detailed-Library-Integration-instructions) for detailed instructions. - - ---- - -### About OHHTTPStubs own Unit Tests - -If you want to be able to run `OHHTTPStubs`' Unit Tests, be sure you cloned the [`AFNetworking`](https://github.com/AFNetworking/AFNetworking/) submodule (by using the `--recursive` option when cloning your repo, or using `git submodule init` and `git submodule update`) as it is used by some of `OHHTTPStubs` unit tests. - -This submodule is only useful for `OHHTTPStubs`' own Unit Tests, that are testing its usage with `AFNetworking`: **you don't need the submodule to use `OHHTTPStubs`** and `OHHTTPStubs` has no dependency on `AFNetworking` itself. - -**Every contribution to add more unit tests is welcome!** - - - -# License and Credits - -This project and library has been created by Olivier Halligon (@aligatr on Twitter) and is under the MIT License. - -It has been inspired by [this article from InfiniteLoop.dk](http://www.infinite-loop.dk/blog/2011/09/using-nsurlprotocol-for-injecting-test-data/). -I would also like to thank to @kcharwood for its contribution, and everyone who contributed to this project on GitHub. - -If you want to support the development of this library, feel free to [![Donate](http://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TRTU3UEWEHV92 "Donate"). Thanks to all contributors so far! diff --git a/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h new file mode 100644 index 0000000..bcf7399 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.h @@ -0,0 +1,221 @@ +// +// NSArray+ObjectiveSugar.h +// Objective Sugar +// +// Created by Marin Usalj on 5/7/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +// For an overview see http://cocoadocs.org/docsets/ObjectiveSugar/ + +@interface NSArray (ObjectiveSugar) + +/** + The first item in the array, or nil. + + @return The first item in the array, or nil. + */ + +- (id) first; + +/** + The last item in the array, or nil. + + @return The last item in the array, or nil. + */ + +- (id) last; + + +/** + A random element in the array, or nil. + + @return A random element in the array, or nil. + */ + +- (id) sample; + + +/** + Allow subscripting to fetch elements within the specified range + + @param An NSValue wrapping an NSRange struct or an NSString with valid range components. If it is an NSString, it will be parsed to an NSRange. eg. @"1..3" specifying the range from 1 to 3. @"1...3" specifying the range from 1 to 2 (exclude the end value 3). Other strinig which contains two int values (@"1,3") will be parsed as range's location and length. + + @return An array with all the elements within the specified range + */ +- (id)objectForKeyedSubscript:(id )key; + + +/** + A simpler alias for `enumerateObjectsUsingBlock` + + @param A block with the object in its arguments. + */ + +- (void)each:(void (^)(id object))block; + +/** + A simpler alias for `enumerateObjectsUsingBlock` which also passes in an index + + @param A block with the object in its arguments. + */ + +- (void)eachWithIndex:(void (^)(id object, NSUInteger index))block; + +/** + An alias for `containsObject` + + @param An object that the array may or may not contain. + */ + +- (BOOL)includes:(id)object; + +/** + Take the first `numberOfElements` out of the array, or the maximum amount of + elements if it is less. + + @param Number of elements to take from array + @return An array of elements + */ + +- (NSArray *)take:(NSUInteger)numberOfElements; + +/** + Passes elements to the `block` until the block returns NO, + then stops iterating and returns an array of all prior elements. + + @param A block that returns YES/NO + @return An array of elements + */ +- (NSArray *)takeWhile:(BOOL (^)(id object))block; + +/** + Iterate through the current array running the block on each object and + returning an array of the changed objects. + + @param A block that passes in each object and returns a modified object + @return An array of modified elements + */ + +- (NSArray *)map:(id (^)(id object))block; + +/** + Iterate through current array asking whether to keep each element. + + @param A block that returns YES/NO for whether the object should stay + @return An array of elements selected + */ + +- (NSArray *)select:(BOOL (^)(id object))block; + +/** + Iterate through current array returning the first element meeting a criteria. + + @param A block that returns YES/NO + @return The first matching element + */ + +- (id)detect:(BOOL (^)(id object))block; + + +/** + Alias for `detect`. Iterate through current array returning the first element + meeting a criteria. + + @param A block that returns YES/NO + @return The first matching element + */ + +- (id)find:(BOOL (^)(id object))block; + +/** + Iterate through current array asking whether to remove each element. + + @param A block that returns YES/NO for whether the object should be removed + @return An array of elements not rejected + */ + +- (NSArray *)reject:(BOOL (^)(id object))block; + +/** + Recurse through self checking for NSArrays and extract all elements into one single array + + @return An array of all held arrays merged + */ + +- (NSArray *)flatten; + +/** + Alias for `componentsJoinedByString` with a default of no seperator + + @return A string of all objects joined with an empty string + */ + +- (NSString *)join; + +/** + Alias for `componentsJoinedByString` + + @return A string of all objects joined with the `seperator` string + */ + +- (NSString *)join:(NSString *)separator; + +/** + Run the default comparator on each object in the array + + @return A sorted copy of the array + */ +- (NSArray *)sort; + +/** + Sorts the array using the the default comparator on the given key + + @return A sorted copy of the array + */ +- (NSArray *)sortBy:(NSString*)key; + +/** + Alias for reverseObjectEnumerator.allObjects + + Returns a reversed array + */ +- (NSArray *)reverse; + +/** + Return all the objects that are in both self and `array`. + Alias for Ruby's & operator + + @return An array of objects common to both arrays + */ + +- (NSArray *)intersectionWithArray:(NSArray *)array; + +/** + Return all the objects that in both self and `array` combined. + Alias for Ruby's | operator + + @return An array of the two arrays combined + */ + +- (NSArray *)unionWithArray:(NSArray *)array; + +/** + Return all the objects in self that are not in `array`. + Alias for Ruby's - operator + + @return An array of the self without objects in `array` + */ + +- (NSArray *)relativeComplement:(NSArray *)array; + +/** + Return all the objects that are unique to each array individually + Alias for Ruby's ^ operator. Equivalent of a - b | b - a + + @return An array of elements which are in either of the arrays and not in their intersection. + */ + +- (NSArray *)symmetricDifference:(NSArray *)array; + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.m new file mode 100644 index 0000000..329326f --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSArray+ObjectiveSugar.m @@ -0,0 +1,203 @@ +// +// NSArray+ObjectiveSugar.m +// WidgetPush +// +// Created by Marin Usalj on 5/7/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#import "NSArray+ObjectiveSugar.h" +#import "NSMutableArray+ObjectiveSugar.h" +#import "NSString+ObjectiveSugar.h" + +@implementation NSArray (ObjectiveSugar) + +- (id)first { + if (self.count > 0) + return self[0]; + + return nil; +} + +- (id)last { + return [self lastObject]; +} + +- (id)sample { + if (self.count == 0) return nil; + + NSUInteger index = arc4random_uniform((u_int32_t)self.count); + return self[index]; +} + +- (id)objectForKeyedSubscript:(id )key { + NSRange range; + if ([(id)key isKindOfClass:[NSString class]]) { + NSString *keyString = (NSString *)key; + range = NSRangeFromString(keyString); + if ([keyString containsString:@"..."]) { + range = NSMakeRange(range.location, range.length - range.location); + } else if ([keyString containsString:@".."]) { + range = NSMakeRange(range.location, range.length - range.location + 1); + } + } else if ([(id)key isKindOfClass:[NSValue class]]) { + range = [((NSValue *)key) rangeValue]; + } else { + [NSException raise:NSInvalidArgumentException format:@"expected NSString or NSValue argument, got %@ instead", [(id)key class]]; + } + + return [self subarrayWithRange:range]; +} + + +- (void)each:(void (^)(id object))block { + [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + block(obj); + }]; +} + +- (void)eachWithIndex:(void (^)(id object, NSUInteger index))block { + [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + block(obj, idx); + }]; +} + +- (BOOL)includes:(id)object { + return [self containsObject:object]; +} + +- (NSArray *)take:(NSUInteger)numberOfElements { + numberOfElements = MIN(numberOfElements, [self count]); + NSMutableArray *array = [NSMutableArray arrayWithCapacity:numberOfElements]; + + for (NSUInteger i = 0; i < numberOfElements; i++) { + [array addObject:self[i]]; + } + + return array; +} + +- (NSArray *)takeWhile:(BOOL (^)(id object))block { + NSMutableArray *array = [NSMutableArray array]; + + for (id arrayObject in self) { + if (block(arrayObject)) + [array addObject:arrayObject]; + + else break; + } + + return array; +} + +- (NSArray *)map:(id (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + id newObject = block(object); + if (newObject) { + [array addObject:newObject]; + } + } + + return array; +} + +- (NSArray *)select:(BOOL (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + if (block(object)) { + [array addObject:object]; + } + } + + return array; +} + +- (id)detect:(BOOL (^)(id object))block { + + for (id object in self) { + if (block(object)) + return object; + } + + return nil; +} + +- (id)find:(BOOL (^)(id object))block { + return [self detect:block]; +} + +- (NSArray *)reject:(BOOL (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + if (block(object) == NO) { + [array addObject:object]; + } + } + + return array; +} + +- (NSArray *)flatten { + NSMutableArray *array = [NSMutableArray array]; + + for (id object in self) { + if ([object isKindOfClass:NSArray.class]) { + [array concat:[object flatten]]; + } else { + [array addObject:object]; + } + } + + return array; +} + +- (NSString *)join { + return [self componentsJoinedByString:@""]; +} + +- (NSString *)join:(NSString *)separator { + return [self componentsJoinedByString:separator]; +} + +- (NSArray *)sort { + return [self sortedArrayUsingSelector:@selector(compare:)]; +} + +- (NSArray *)sortBy:(NSString*)key; { + NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:YES]; + return [self sortedArrayUsingDescriptors:@[descriptor]]; +} + +- (NSArray *)reverse { + return self.reverseObjectEnumerator.allObjects; +} + +#pragma mark - Set operations + +- (NSArray *)intersectionWithArray:(NSArray *)array { + NSPredicate *intersectPredicate = [NSPredicate predicateWithFormat:@"SELF IN %@", array]; + return [self filteredArrayUsingPredicate:intersectPredicate]; +} + +- (NSArray *)unionWithArray:(NSArray *)array { + NSArray *complement = [self relativeComplement:array]; + return [complement arrayByAddingObjectsFromArray:array]; +} + +- (NSArray *)relativeComplement:(NSArray *)array { + NSPredicate *relativeComplementPredicate = [NSPredicate predicateWithFormat:@"NOT SELF IN %@", array]; + return [self filteredArrayUsingPredicate:relativeComplementPredicate]; +} + +- (NSArray *)symmetricDifference:(NSArray *)array { + NSArray *aSubtractB = [self relativeComplement:array]; + NSArray *bSubtractA = [array relativeComplement:self]; + return [aSubtractB unionWithArray:bSubtractA]; +} + +@end + diff --git a/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h new file mode 100644 index 0000000..1dce388 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.h @@ -0,0 +1,19 @@ +// +// NSDictionary+ObjectiveSugar.h +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import + +@interface NSDictionary (ObjectiveSugar) + +- (void)each:(void (^)(id key, id value))block; +- (void)eachKey:(void (^)(id key))block; +- (void)eachValue:(void (^)(id value))block; +- (NSArray *)map:(id (^)(id key, id value))block; +- (BOOL)hasKey:(id)key; + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.m new file mode 100644 index 0000000..96ddae7 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSDictionary+ObjectiveSugar.m @@ -0,0 +1,48 @@ +// +// NSDictionary+ObjectiveSugar.m +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import "NSDictionary+ObjectiveSugar.h" + +@implementation NSDictionary (Rubyfy) + +- (void)each:(void (^)(id k, id v))block { + [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + block(key, obj); + }]; +} + +- (void)eachKey:(void (^)(id k))block { + [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + block(key); + }]; +} + +- (void)eachValue:(void (^)(id v))block { + [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + block(obj); + }]; +} + +- (NSArray *)map:(id (^)(id key, id value))block { + NSMutableArray *array = [NSMutableArray array]; + + [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + id object = block(key, obj); + if (object) { + [array addObject:object]; + } + }]; + + return array; +} + +- (BOOL)hasKey:(id)key { + return !!self[key]; +} + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h new file mode 100644 index 0000000..bf4a991 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.h @@ -0,0 +1,44 @@ +// +// NSMutableArray+ObjectiveSugar.h +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import + +@interface NSMutableArray (ObjectiveSugar) + +- (void)push:(id)object; +- (id)pop; +- (NSArray *)pop:(NSUInteger)numberOfElements; +- (void)concat:(NSArray *)array; + +/** + method removes the first item of an array, and returns that item + Note: This method changes the length of an array! + + @return First array item or nil. + */ +- (id)shift; + + +/** + method removes N first items of an array, and returns that items + Note: This method changes the length of an array! + + @return Array of first N items or empty array. + */ +- (NSArray *)shift:(NSUInteger)numberOfElements; + +/** + Deletes every element of the array for which the given block evaluates to NO. + + @param A block that returns YES/NO + @return An array of elements + */ + +- (NSArray *)keepIf:(BOOL (^)(id object))block; + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.m new file mode 100644 index 0000000..9c5c4a3 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSMutableArray+ObjectiveSugar.m @@ -0,0 +1,64 @@ +// +// NSMutableArray+ObjectiveSugar.m +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import "NSMutableArray+ObjectiveSugar.h" +#import "NSArray+ObjectiveSugar.h" + +@implementation NSMutableArray (ObjectiveSugar) + +- (void)push:(id)object { + [self addObject:object]; +} + +- (id)pop { + id object = [self lastObject]; + [self removeLastObject]; + + return object; +} + +- (NSArray *)pop:(NSUInteger)numberOfElements { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:numberOfElements]; + + for (NSUInteger i = 0; i < numberOfElements; i++) + [array insertObject:[self pop] atIndex:0]; + + return array; +} + +- (void)concat:(NSArray *)array { + [self addObjectsFromArray:array]; +} + +- (id)shift { + NSArray *result = [self shift:1]; + return [result first]; +} + +- (NSArray *)shift:(NSUInteger)numberOfElements { + NSUInteger shiftLength = MIN(numberOfElements, [self count]); + + NSRange range = NSMakeRange(0, shiftLength); + NSArray *result = [self subarrayWithRange:range]; + [self removeObjectsInRange:range]; + + return result; +} + +- (NSArray *)keepIf:(BOOL (^)(id object))block { + for (NSUInteger i = 0; i < self.count; i++) { + id object = self[i]; + if (block(object) == NO) { + [self removeObject:object]; + } + } + + return self; +} + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h new file mode 100644 index 0000000..7885b3f --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.h @@ -0,0 +1,45 @@ +// +// NSNumber+Rubyfy.h +// Domainchy +// +// Created by Marin Usalj on 11/15/12. +// Copyright (c) 2012 mneorr.com | @mneorr | mneorr@gmail.com. All rights reserved. +// + +#import + +@interface NSNumber (ObjectiveSugar) + +- (void)times:(void(^)(void))block; +- (void)timesWithIndex:(void(^)(NSUInteger index))block; + +- (void)upto:(int)number do:(void(^)(NSInteger number))block; +- (void)downto:(int)number do:(void(^)(NSInteger number))block; + +// Numeric inflections +- (NSNumber *)seconds; +- (NSNumber *)minutes; +- (NSNumber *)hours; +- (NSNumber *)days; +- (NSNumber *)weeks; +- (NSNumber *)fortnights; +- (NSNumber *)months; +- (NSNumber *)years; + +// There are singular aliases for the above methods +- (NSNumber *)second; +- (NSNumber *)minute; +- (NSNumber *)hour; +- (NSNumber *)day; +- (NSNumber *)week; +- (NSNumber *)fortnight; +- (NSNumber *)month; +- (NSNumber *)year; + +- (NSDate *)ago; +- (NSDate *)ago:(NSDate *)time; +- (NSDate *)since:(NSDate *)time; +- (NSDate *)until:(NSDate *)time; +- (NSDate *)fromNow; + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.m new file mode 100644 index 0000000..ac4f0bb --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSNumber+ObjectiveSugar.m @@ -0,0 +1,117 @@ +// +// NSNumber+Rubyfy.m +// Domainchy +// +// Created by Marin Usalj on 11/15/12. +// Copyright (c) 2012 mneorr.com | @mneorr | mneorr@gmail.com. All rights reserved. +// + +#import "NSNumber+ObjectiveSugar.h" + +@implementation NSNumber (ObjectiveSugar) + +- (void)times:(void (^)(void))block { + for (int i = 0; i < self.integerValue; i++) + block(); +} + +- (void)timesWithIndex:(void (^)(NSUInteger))block { + for (int i = 0; i < self.unsignedIntegerValue; i++) + block(i); +} + +- (void)upto:(int)number do:(void (^)(NSInteger))block { + for (NSInteger i = self.integerValue; i <= number; i++) + block(i); +} + +- (void)downto:(int)number do:(void (^)(NSInteger))block { + for (NSInteger i = self.integerValue; i >= number; i--) + block(i); +} + +- (NSNumber *)second { + return self.seconds; +} + +- (NSNumber *)seconds { + return self; +} + +- (NSNumber *)minute { + return self.minutes; +} + +- (NSNumber *)minutes { + return @(self.floatValue * 60); +} + +- (NSNumber *)hour { + return self.hours; +} + +- (NSNumber *)hours { + return @(self.floatValue * [@60 minutes].integerValue); +} + +- (NSNumber *)day { + return self.days; +} + +- (NSNumber *)days { + return @(self.floatValue * [@24 hours].integerValue); +} + +- (NSNumber *)week { + return self.weeks; +} + +- (NSNumber *)weeks { + return @(self.floatValue * [@7 days].integerValue); +} + +- (NSNumber *)fortnight { + return self.fortnights; +} + +- (NSNumber *)fortnights { + return @(self.floatValue * [@2 weeks].integerValue); +} + +- (NSNumber *)month { + return self.months; +} + +- (NSNumber *)months { + return @(self.floatValue * [@30 days].integerValue); +} + +- (NSNumber *)year { + return self.years; +} + +- (NSNumber *)years { + return @(self.floatValue * [@(365.25) days].integerValue); +} + +- (NSDate *)ago { + return [self ago:[NSDate date]]; +} + +- (NSDate *)ago:(NSDate *)time { + return [NSDate dateWithTimeIntervalSince1970:([time timeIntervalSince1970] - self.floatValue)]; +} + +- (NSDate *)since:(NSDate *)time { + return [NSDate dateWithTimeIntervalSince1970:([time timeIntervalSince1970] + self.floatValue)]; +} + +- (NSDate *)until:(NSDate *)time { + return [self ago:time]; +} + +- (NSDate *)fromNow { + return [self since:[NSDate date]]; +} + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h new file mode 100644 index 0000000..25c2dbb --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.h @@ -0,0 +1,26 @@ +// +// NSSet+Accessors.h +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import + +@interface NSSet (Accessors) + +@property(readonly) id first; +@property(readonly) id last; +@property(readonly) id sample; + +- (void)each:(void (^)(id object))block; +- (void)eachWithIndex:(void (^)(id object, NSUInteger index))block; + +- (NSArray *)select:(BOOL (^)(id object))block; +- (NSArray *)reject:(BOOL (^)(id object))block; +- (NSArray *)map:(id (^)(id object))block; + +- (NSArray *)sort; + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.m new file mode 100644 index 0000000..fe8498d --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSSet+ObjectiveSugar.m @@ -0,0 +1,84 @@ +// +// NSSet+ObjectiveSugar.m +// SampleProject +// +// Created by Marin Usalj on 11/23/12. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import "NSSet+ObjectiveSugar.h" +#import "NSArray+ObjectiveSugar.h" + +@implementation NSSet (ObjectiveSugar) + +- (id)first { + NSArray *allObjects = self.allObjects; + + if (allObjects.count > 0) + return allObjects[0]; + return nil; +} + +- (id)last { + return self.allObjects.lastObject; +} + +- (id)sample { + return [self.allObjects sample]; +} + +- (void)each:(void (^)(id))block { + [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { + block(obj); + }]; +} + +- (void)eachWithIndex:(void (^)(id, int))block { + __block int counter = 0; + [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { + block(obj, counter); + counter ++; + }]; +} + +- (NSArray *)map:(id (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + id newObject = block(object); + [array addObject:newObject]; + } + + return array; +} + +- (NSArray *)select:(BOOL (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + if (block(object)) { + [array addObject:object]; + } + } + + return array; +} + +- (NSArray *)reject:(BOOL (^)(id object))block { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; + + for (id object in self) { + if (block(object) == NO) { + [array addObject:object]; + } + } + + return array; +} + +- (NSArray *)sort { + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES]; + return [self sortedArrayUsingDescriptors:@[sortDescriptor]]; +} + +@end diff --git a/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.h new file mode 100644 index 0000000..e0aa366 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.h @@ -0,0 +1,56 @@ +// +// NSString+ObjectiveSugar.h +// SampleProject +// +// Created by Neil on 05/12/2012. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import + +NSString *NSStringWithFormat(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); + +@interface NSString(ObjectiveSugar) + +/** + Returns an array containing substrings from the receiver that have been divided by a whitespace delimiter + + @return An array containing substrings that have been divided by a whitespace delimiter + */ +- (NSArray *)split; + + +/** + Returns an array containing substrings from the receiver that have been divided by a given delimiter + + @param delimiter The delimiter string + @return An array containing substrings that have been divided by delimiter + */ +- (NSArray *)split:(NSString *)delimiter; + + +/** + Returns a new string made by converting a snake_case_string to CamelCaseString + + @return A string made by converting a snake_case_string to CamelCaseString + */ +- (NSString *)camelCase; + + +/** + Returns a Boolean value that indicates whether a given string is a substring of the receiver + + @return YES if 'string' is a substring of the receiver, otherwise NO + */ +- (BOOL)containsString:(NSString *)string; + + +/** + Returns a new string made by removing whitespaces and newlines from both ends of the receiver + + @return A string without trailing or leading whitespaces and newlines + */ +- (NSString *)strip; + +@end + diff --git a/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.m b/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.m new file mode 100644 index 0000000..bf3f5db --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/NSString+ObjectiveSugar.m @@ -0,0 +1,61 @@ +// +// NSString+ObjectiveSugar.m +// SampleProject +// +// Created by Neil on 05/12/2012. +// Copyright (c) 2012 @mneorr | mneorr.com. All rights reserved. +// + +#import "NSString+ObjectiveSugar.h" +#import "NSArray+ObjectiveSugar.h" + +static NSString *const UNDERSCORE = @"_"; +static NSString *const SPACE = @" "; +static NSString *const EMPTY_STRING = @""; + +NSString *NSStringWithFormat(NSString *formatString, ...) { + va_list args; + va_start(args, formatString); + + NSString *string = [[NSString alloc] initWithFormat:formatString arguments:args]; + + va_end(args); + +#if defined(__has_feature) && __has_feature(objc_arc) + return string; +#else + return [string autorelease]; +#endif +} + + +@implementation NSString(Additions) + +- (NSArray *)split { + NSArray *result = [self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + return [result select:^BOOL(NSString *string) { + return string.length > 0; + }]; +} + +- (NSArray *)split:(NSString *)delimiter { + return [self componentsSeparatedByString:delimiter]; +} + +- (NSString *)camelCase { + NSString *spaced = [self stringByReplacingOccurrencesOfString:UNDERSCORE withString:SPACE]; + NSString *capitalized = [spaced capitalizedString]; + + return [capitalized stringByReplacingOccurrencesOfString:SPACE withString:EMPTY_STRING]; +} + +- (BOOL)containsString:(NSString *) string { + NSRange range = [self rangeOfString:string options:NSCaseInsensitiveSearch]; + return range.location != NSNotFound; +} + +- (NSString *)strip { + return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; +} + +@end diff --git a/Pods/ObjectiveSugar/Classes/ObjectiveSugar.h b/Pods/ObjectiveSugar/Classes/ObjectiveSugar.h new file mode 100644 index 0000000..e5bc2a6 --- /dev/null +++ b/Pods/ObjectiveSugar/Classes/ObjectiveSugar.h @@ -0,0 +1,11 @@ +// C SUGAR +#define unless(condition...) if(!(condition)) +#define until(condition...) while(!(condition)) + +// OBJC SUGAR +#import "NSNumber+ObjectiveSugar.h" +#import "NSArray+ObjectiveSugar.h" +#import "NSMutableArray+ObjectiveSugar.h" +#import "NSDictionary+ObjectiveSugar.h" +#import "NSSet+ObjectiveSugar.h" +#import "NSString+ObjectiveSugar.h" diff --git a/Pods/ObjectiveSugar/LICENSE b/Pods/ObjectiveSugar/LICENSE new file mode 100644 index 0000000..7789d6e --- /dev/null +++ b/Pods/ObjectiveSugar/LICENSE @@ -0,0 +1,7 @@ +Copyright © 2012 Marin Usalj, http://mneorr.com + +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. diff --git a/Pods/ObjectiveSugar/README.md b/Pods/ObjectiveSugar/README.md new file mode 100644 index 0000000..fcfd4b1 --- /dev/null +++ b/Pods/ObjectiveSugar/README.md @@ -0,0 +1,314 @@ +Write Objective C _like a boss_.
+You can get the idea in [this post](http://mneorr.com/adding-some-ruby-sugar-to-objectivec/). + +
+[![Build Status](https://travis-ci.org/mneorr/ObjectiveSugar.png?branch=master)](https://travis-ci.org/mneorr/ObjectiveSugar) +## Installation + +__Cocoapods__: `pod 'ObjectiveSugar'`
+__Manual__: Copy the __Classes__ folder in your project
+ +`#import ` + + +#### NSNumber additions + +``` objc +[@3 times:^{ + NSLog(@"Hello!"); +}]; +// Hello! +// Hello! +// Hello! + +[@3 timesWithIndex:^(NSUInteger index) { + NSLog(@"Another version with number: %d", index); +}]; +// Another version with number: 0 +// Another version with number: 1 +// Another version with number: 2 + + +[@1 upto:4 do:^(NSInteger numbah) { + NSLog(@"Current number.. %d", numbah); +}]; +// Current number.. 1 +// Current number.. 2 +// Current number.. 3 +// Current number.. 4 + +[@7 downto:4 do:^(NSInteger numbah) { + NSLog(@"Current number.. %d", numbah); +}]; +// Current number.. 7 +// Current number.. 6 +// Current number.. 5 +// Current number.. 4 + +NSDate *newYearsDay = [NSDate newYearsDate]; // let's pretend it's a new year +NSDate *firstOfDecember = [@(31).days since:newYearsDay]; +// 2012-12-01 00:00:00 +0000 + +NSDate *future = @(24).days.fromNow; +// 2012-12-25 20:49:05 +0000 + +NSDate *past = @(1).month.ago; +// 2012-11-01 20:50:28 +00:00 + +NSDate *christmas = [@(7).days until:newYearsDay]; +// 2012-12-25 00:00:00 +0000 + +``` + +#### NSArray / NSSet additions + +``` objc +// All of these methods return a modified copy of the array. +// They're not modifying the source array. + +NSArray *cars = @[@"Testarossa", @"F50", @"F458 Italia"]; // or NSSet + +[cars each:^(id object) { + NSLog(@"Car: %@", object); +}]; +// Car: Testarossa +// Car: F50 +// Car: F458 Italia + +[cars eachWithIndex:^(id object, NSUInteger index) { + NSLog(@"Car: %@ index: %i", object, index); +}]; +// Car: Testarossa index: 0 +// Car: F50 index: 1 +// Car: F458 Italia index: 2 + +cars.first; +// Testarossa +cars.last +// 458 Italia +cars.sample +// 458 Italia +cars.sample +// F50 + +[cars map:^id(id car){ + return @([[car substringToIndex:1] isEqualToString:@"F"]); +}]; +// NO, YES, YES + +NSArray *mixedData = @[ @1, @"Objective Sugar!", @"Github", @4, @"5"]; + +[mixedData select:^BOOL(id object) { + return ([object class] == [NSString class]); +}]; +// Objective Sugar, Github, 5 + +[mixedData reject:^BOOL(id object) { + return ([object class] == [NSString class]); +}]; +// 1, 4 + +NSArray *numbers = @[ @5, @2, @7, @1 ]; +[numbers sort]; +// 1, 2, 5, 7 +``` + +#### NSArray only + +``` objc + +NSArray *numbers = @[@1, @2, @3, @4, @5, @6]; + +// index from 2 to 4 +numbers[@"2..4"]; +// [@3, @4, @5] + +// index from 2 to 4 (excluded) +numbers[@"2...4"]; +// [@3, @4] + +// With NSRange location: 2, length: 4 +numbers[@"2,4"]; +// [@3, @4, @5, @6] + +NSValue *range = [NSValue valueWithRange:NSMakeRange(2, 4)]; +numbers[range]; +// [@3, @4, @5, @6] + +NSArray *fruits = @[ @"banana", @"mango", @"apple", @"pear" ]; + +NSLog(@"Is apple a fruit? %@", [fruits includes:@"apple"] ? @"Yes" : @"No"]; +// Is apple a fruit? Yes + +[fruits take:3]; +// banana, mango, apple + +[someFruits takeWhile:^BOOL(id fruit) { + return ![fruit isEqualToString:@"apple"]; +}]; +// banana, mango + +NSArray *nestedArray = @[ @[ @1, @2, @3 ], @[ @4, @5, @6, @[ @7, @8 ] ], @9, @10 ]; +[nestedArray flatten]; +// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + +NSArray *abc = @[ @"a", @"b", @"c" ]; +[abc join]; +// abc + +[abc join:@"-"]; +// a-b-c + +NSArray *obverseArray = @[@1, @2, @3, @4, @5]; +[obverseArray reverse]; +// [@5, @4, @3, @2, @1] + +NSArray *mixedData = @[ @1, @"Objective Sugar!", @"Github", @4, @"5"]; + +[mixedData detect:^BOOL(id object) { + return ([object class] == [NSString class]); +}]; +// Objective Sugar + + + +// TODO: Make a better / simpler example of this +NSArray *landlockedCountries = @[ @"Bolivia", @"Paraguay", @"Austria", @"Switzerland", @"Hungary" ]; +NSArray *europeanCountries = @[ @"France", @"Germany", @"Austria", @"Spain", @"Hungary", @"Poland", @"Switzerland" ]; + + +[landlockedCountries intersectionWithArray:europeanCountries]; +// landlockedEuropeanCountries = Austria, Switzerland, Hungary + +[landlockedCountries unionWithArray:europeanCountries]; +// landlockedOrEuropean = Bolivia, Paraguay, Austria, Switzerland, Hungary, France, Germany, Spain, Poland + +[landlockedCountries relativeComplement:europeanCountries]; +// nonEuropeanLandlockedCountries = Bolivia, Paraguay + +[europeanCountries relativeComplement:landlockedCountries]; +// notLandlockedEuropeanCountries = France, Germany, Spain, Poland + +[landlockedCountries symmetricDifference:europeanCountries]; +// uniqueCountries = Bolivia, Paraguay, France, Germany, Spain, Poland +``` + +#### NSMutableArray additions + +``` objc +NSMutableArray *people = @[ @"Alice", @"Benjamin", @"Christopher" ]; + +[people push:@"Daniel"]; // Alice, Benjamin, Christopher, Daniel + +[people pop]; // Daniel +// people = Alice, Benjamin, Christopher + +[people pop:2]; // Benjamin, Christopher +// people = Alice + +[people concat:@[ @"Evan", @"Frank", @"Gavin" ]]; +// people = Alice, Evan, Frank, Gavin + +``` + +#### NSDictionary additions + +``` objc +NSDictionary *dict = @{ @"one" : @1, @"two" : @2, @"three" : @3 }; + +[dict each:^(id key, id value){ + NSLog(@"Key: %@, Value: %@", key, value); +}]; +// Key: one, Value: 1 +// Key: two, Value: 2 +// Key: three, Value: 3 + +[dict eachKey:^(id key) { + NSLog(@"Key: %@", key); +}]; +// Key: one +// Key: two +// Key: three + +[dict eachValue:^(id value) { + NSLog(@"Value: %@", value); +}]; +// Value: 1 +// Value: 2 +// Value: 3 + +NSDictionary *errors = @{ + @"username" : @[ @"already taken" ], + @"password" : @[ @"is too short (minimum is 8 characters)", @"not complex enough" ], + @"email" : @[ @"can't be blank" ]; +}; + +[errors map:^(id attribute, id reasons) { + return NSStringWithFormat(@"%@ %@", attribute, [reasons join:@", "]); +}]; +// username already taken +// password is too short (minimum is 8 characters), not complex enough +// email can't be blank + +[errors hasKey:@"email"] +// true +[errors hasKey:@"Alcatraz"] +// false +``` + +#### NSString additions + +``` objc +NSString *sentence = NSStringWithFormat(@"This is a text-with-argument %@", @1234); +// This is a text-with-argument 1234 + +[sentence split]; +// array = this, is, a, text-with-argument, 1234 + +[sentence split:@"-"] +// array = this is a text, with, argument 1234 + +[sentence containsString:@"this is a"]; +// YES +``` + +#### C additions + +``` objc +unless(_messages) { + // The body is only executed if the condition is false + _messages = [self initializeMessages]; +} + +int iterations = 10; +until(iterations == 0) { + // The body is executed until the condition is false + // 10 9 8 7 6 5 4 3 2 1 + printf("%d ", iterations); + iterations--; +} +printf("\n"); + +iterations = 10; +do { + // The body is executed at least once until the condition is false + // Will print: Executed! + printf("Executed!\n"); +} until(true); +``` + +#### Contributing + +ObjectiveSugar is tested with [Kiwi](https://github.com/allending/Kiwi), and tests are located in SampleProject.
+If you plan on contributing to the project, please: + + * Write tests + * Write documentation + +
+ +#### Team + +- Marin Usalj [@mneorr](https://github.com/mneorr) +- Neil Cowburn [@neilco](https://github.com/neilco) + diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index f3f2336..7b12877 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -1,13914 +1,2585 @@ - - - - - archiveVersion - 1 - classes - - objectVersion - 46 - objects - - 00A88CA143DBCC80AD9BE279 - - fileRef - 938962EC2EECB2610DE86053 - isa - PBXBuildFile - - 00B561A39215EFF1751B4356 - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 00EB60C9A62A3767A2A113BD - - fileRef - 7FFC350D592E57C150B8970F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 010BAC3FDBBCE0DCD451EC06 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-Mantle.xcconfig - path - ../Pods-Mantle/Pods-Mantle.xcconfig - sourceTree - <group> - - 0114885A1181FC5F01EE73ED - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-libextobjc-dummy.m - path - ../Pods-libextobjc/Pods-libextobjc-dummy.m - sourceTree - <group> - - 011623DB8A11A1559279E2BF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - OHHTTPStubs+NSURLSessionConfiguration.m - path - OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m - sourceTree - <group> - - 018ED0095A44CF339C395EBF - - fileRef - 23A967C5A37AFDC511BAAFD0 - isa - PBXBuildFile - - 01BEECA3B833185A69868F19 - - fileRef - E22135502E6F21DDE43963C6 - isa - PBXBuildFile - - 022D472F320A705B6B2EEF5A - - fileRef - 3618A04504801463F3664011 - isa - PBXBuildFile - - 0279EDB65877E0B4B204862E - - fileRef - EFA167E931980D498BEDBA8C - isa - PBXBuildFile - - 028F8336E7D9DDC0C47F570B - - fileRef - 73DAFF00036F4792002AB223 - isa - PBXBuildFile - - 02DBE9C9DF1E0B0EEBA0646A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDASLLogCapture.h - path - Lumberjack/DDASLLogCapture.h - sourceTree - <group> - - 02F0A0CA7FC130C6EFC430F6 - - children - - F374224ACFF5AF242D15DEE2 - - isa - PBXGroup - name - UmbrellaHeader - sourceTree - <group> - - 030C2CB4A6BAD5A7E0F9B58A - - children - - 687778BA01286AD991757704 - C6C84C593E998BBE858E331B - 2A0931B9CBA71CAFE21F8382 - 1705BB75DAA0AB2240165F6E - D2D1D335CCB91AE5B63085BF - D04434DD0E4D7452AEEFD3D2 - 0114885A1181FC5F01EE73ED - 613EC9CAD21B8AB594DEFC5F - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-libextobjc - sourceTree - <group> - - 0325A3C73A337C97987152F4 - - buildConfigurations - - 2A7340B5DCBB5FE4BE4FD989 - C6C138FDDC2B6B93C0C1A86B - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 0332EEC146CEFE57854BEA43 - - buildActionMask - 2147483647 - files - - D630761F0BB3F47B4F5FFC3E - F4B68D70C8807A5AB449365B - BD5BA1C3E746D35FA8A78228 - 620903ACB6C56FA958F0D475 - 1AE6D8A7013D28B017877E5A - 4533EFD6D984FD606E90BFA8 - 26A0EB9773E5D8B1A16C42B4 - A3A6B41EB3B7DF33C044FBFB - C014312069CA82C2BF85484F - D1D92BFB5E4E5A39E16E7921 - A43DCF13B56E4F1A5B9008BD - E4234B3D55C40CACF3FBCE28 - C6431B7067E6FC24F64C2AE1 - 83617777ABD1FADFDC9BA18C - F17E98B1F085B9E5898DC23B - 55F387549037865FB6561C5E - 3C20827154A9B04ACFAF891C - 4942F30AC0DA29996C06C02D - EAF20C790CBA5E04FCC8CBAC - C42C74218F847931E9ED0F39 - B0A02669C19682986FDDB459 - EC026D2286E3E9E497A404FB - 27498FE4203166A99C9ED63C - 073C831CD238C04E8C8B888B - 7075264C7A078B3E1679391C - 9F9D0C6AD1CED13869444176 - B5D7C2BEB6C0412F9D0488FA - CF738663C04A0C77723C18CA - 3921FADA1AE6316C9A28ACE5 - 06AE71CD868E14F43F33FC1C - FAC6F666CA1E454F27A4F8BC - EFED7DD7C47CFA41BE33C3E3 - 3E6EB71B3F314876BF11166A - 028F8336E7D9DDC0C47F570B - 50E907BF5ABC5D19B4FDB836 - CFB5B5B8B787F3C692C3C9ED - ABBF95AAD79E181BF788A258 - 1579441F17A2C8760B3042A7 - 28099AA355746F5B578F4D04 - 0279EDB65877E0B4B204862E - 87786B738E70FD462DCB1501 - AB33EF177F2ED007711CB205 - 38A1039D4DBB2BF653BF42E4 - 146E0F23B2821B4E1CA89499 - 710F9EE2A1DAA415EC8B73A1 - 7E5D02DE1056A3198256BED5 - 59207766A0320FA3F0E4FE68 - 176411E7025810ABE8546215 - 9A7B22C758072DB3D063195E - 65C18D1263F393C601E3C50A - 393BBD320AF7C7C3E82648CE - D26C0011FF040C1E8181D18F - 698E1F13B0057DFF762A59B1 - 860A75C12C8EEE9B1CD01FC2 - E6CBBE066587633D9ED02573 - 316171FCCB0AABE279527975 - 75755FADD6F23C1F7D6B2407 - 0B21A53BBA1DA4388F54CDDD - 373E85A4772D3F741C3C38DA - 0401A470BBDCE64F9FA96F53 - 03FCBAC021AA1D5F1F1F51FF - F5C5F03FEA0D518524954D07 - C8DB94A0A2F90B36BFA5E7BF - 81FB29C0A41373CD2BAE212F - E88EE7CF821F0BCCD5229951 - 00A88CA143DBCC80AD9BE279 - 01BEECA3B833185A69868F19 - 1C542F87BD931714FEF6F0FC - D0D7E9ADC8AC927DCA2E34A0 - F6225A5910C1F7B16C6A2AA3 - 1272DB4807DB303BEE9AA36E - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 0383AA523C372C5E0BE85649 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-resources.sh - sourceTree - <group> - - 03C62DF4FF55BC48C381EDFF - - fileRef - 0D9752CEE76F92DBE94F3732 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 03FCBAC021AA1D5F1F1F51FF - - fileRef - AF4B16A7F886887E3429B1D4 - isa - PBXBuildFile - - 0401A470BBDCE64F9FA96F53 - - fileRef - AD2B1493CDAAF65711488F8D - isa - PBXBuildFile - - 0412BDD030399C866EED506C - - fileRef - 7C0E1DAA278CAF4CEB13ED80 - isa - PBXBuildFile - - 0426F1CA8AD4B65620814DF4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PMKPromise.m - path - objc/PMKPromise.m - sourceTree - <group> - - 0434CCF4135312096BB4BC99 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-YapDatabase-Private.xcconfig - sourceTree - <group> - - 0527FF600EDF15D508B9CC0F - - baseConfigurationReference - D04434DD0E4D7452AEEFD3D2 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-libextobjc/Pods-libextobjc-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 055E0558547AB714FEA492CF - - fileRef - 0114885A1181FC5F01EE73ED - isa - PBXBuildFile - - 058F5C316149DCE85212C22D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-PromiseKit-prefix.pch - sourceTree - <group> - - 05A2E1512618C9EE16B4813C - - fileRef - FA36EFEA598C18B00262C163 - isa - PBXBuildFile - - 05E9483268EA8F22B82242A4 - - fileRef - 68FDFCCDE4BECFD66CB5581C - isa - PBXBuildFile - - 05F4BC38378B22DC641DAECE - - fileRef - 450E21DD059A05B0C96858F2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 062F7ED90F24410039196758 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLValueTransformer.h - path - Mantle/MTLValueTransformer.h - sourceTree - <group> - - 064F60C168F0616EE6B27951 - - fileRef - E9BA319F7625FE787FF04357 - isa - PBXBuildFile - - 069AB01CC15FB623C707497D - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods.a - sourceTree - BUILT_PRODUCTS_DIR - - 06AE71CD868E14F43F33FC1C - - fileRef - 2568CFD4A6FAAB51C63F29F4 - isa - PBXBuildFile - - 06F5F64F7192F1ABA7FB9583 - - buildActionMask - 2147483647 - files - - 4EDD3C130475F1720C92288B - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 06FBBD6B7A406D3986E38436 - - fileRef - BAB779202635DD0BF3382B4F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 073C831CD238C04E8C8B888B - - fileRef - C4F7FEE942FEF691E3AA2B30 - isa - PBXBuildFile - - 076A6AC2BA9C31B408AEEB35 - - children - - CE201D26E25444A9A8BE49AD - AE190E4088CE4126A58EB2CC - 95A06746E8E22F9210701C20 - - isa - PBXGroup - name - UIActionSheet - sourceTree - <group> - - 0795C3F541DAC18BC24984B1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSInvocation+EXT.m - path - extobjc/NSInvocation+EXT.m - sourceTree - <group> - - 08063562731D3281924ED5B4 - - buildConfigurations - - E846228E4C2EEB6D5802E220 - 6DB2BFB41023617CC8196AAF - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 08076FA20D8ACA0E11E1AF6C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-Mantle-Private.xcconfig - path - ../Pods-Mantle/Pods-Mantle-Private.xcconfig - sourceTree - <group> - - 081102761BC1E0B03EF8BD0C - - children - - 6180F3A8B56688E31FA05138 - B02EDE68D12C8E7B4F857A94 - - isa - PBXGroup - name - When - sourceTree - <group> - - 0839683493E194E9778FD0C9 - - fileRef - F6098873BF3A85424034C965 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 08F2C7B599103FC0BCF1D7BB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDASLLogger.m - path - Lumberjack/DDASLLogger.m - sourceTree - <group> - - 09209F9245977177087929A3 - - fileRef - 27AAE6EFCA6056FFF1F3BF7E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 09267BA07E1B41DC602367AD - - children - - C2A3CF10E412976A8D9B0C12 - F5A8223B1C33B1AB9E498E85 - E5B4081AC0A6B88921DC5FB1 - A0BBCBEB76635DCFF2AC8D22 - 856A9BD39CE1E17DA9072E87 - F7E221B750098B1AFB5FE850 - 9F3504F83A04B43CBDAC7AAD - 18C20C33E9EE15AB6AFA5A7A - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-CocoaLumberjack - sourceTree - <group> - - 09BAD25366931CEA0CE78FA1 - - fileRef - 526514FC801A87957576E3CD - isa - PBXBuildFile - - 0A073915BA73A7E6CEB5F0A2 - - children - - 68FDFCCDE4BECFD66CB5581C - 786805C8B7F1B00080A91337 - 7831B1B4A66083F2F576334E - - isa - PBXGroup - name - iOS - sourceTree - <group> - - 0A76FD5A3DB281D4EFCAA061 - - buildActionMask - 2147483647 - files - - F671AB629B4C96D97FCF82DE - E9EB7DABD176D0FC42C73E7D - 9019B7655929D5E06FDE57C4 - EAFEA6BAA977E305C6355574 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 0A844C8CCC1499E2AF895CB9 - - children - - 6028C9A4C4F454EA341C09EE - E9BA319F7625FE787FF04357 - - isa - PBXGroup - name - Until - sourceTree - <group> - - 0ADA1F3E78D7F286AD9EB2CE - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-OMGHTTPURLRQ.a - sourceTree - BUILT_PRODUCTS_DIR - - 0AFD6B4581479C9C1307416A - - fileRef - 7546557388C901CF79E23BF1 - isa - PBXBuildFile - - 0B21A53BBA1DA4388F54CDDD - - fileRef - F2AC98A4DF465FBE6C7B1B28 - isa - PBXBuildFile - - 0BC9BEF690FE54343D4BF08A - - fileRef - 4461408D25667B0E5C30636E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 0C6C3F9E7BA954283A5C10E9 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 0CEF748D4643155C85A58AD8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-Mantle-prefix.pch - sourceTree - <group> - - 0D086505BA8DFD441153D392 - - buildConfigurations - - 386CAF582008202A84886B1E - 871FEDE668562DCEF3DDB8FA - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 0D2BEEA66F53ED2FC2927BD9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexConnection.h - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h - sourceTree - <group> - - 0D700C2A0BD0B56B170D7BA0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFullTextSearchTransaction.m - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m - sourceTree - <group> - - 0D712F3434D4B4C47CB4B500 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-YapDatabase.xcconfig - path - ../Pods-YapDatabase/Pods-YapDatabase.xcconfig - sourceTree - <group> - - 0D9752CEE76F92DBE94F3732 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSecondaryIndex.m - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m - sourceTree - <group> - - 0DBFE01B7F9FEF47FC396779 - - fileRef - C5E267FDD9E85E58C36D7876 - isa - PBXBuildFile - - 0E0CF4D6D7992833ED4BC003 - - fileRef - D084BE4E40606CBC76CE60B8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 0E0FF58E632DB352EEFC02D8 - - isa - PBXTargetDependency - target - C18E92409B2B034FA606C91B - targetProxy - 933CEF8D04B13B55EC3A9B7B - - 0E149F643670201E753CB1E2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseView.m - path - YapDatabase/Extensions/Views/YapDatabaseView.m - sourceTree - <group> - - 0F13A061204FC763FF0D82EA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-environment.h - sourceTree - <group> - - 0F456E30C3CE6879F902B4A4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapCache.h - path - YapDatabase/Internal/YapCache.h - sourceTree - <group> - - 0F5C7918D5A8760DA8F7C6A6 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 6831A48FA46B88E918F641FE - remoteInfo - Pods-BlogTests-YapDatabase - - 0FD3969237C6CD2004EBC12F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTConcreteProtocol.h - path - extobjc/EXTConcreteProtocol.h - sourceTree - <group> - - 10121E4202FAD5A14D2F9E4D - - fileRef - 354E0846412CEF0AD4E30091 - isa - PBXBuildFile - - 107F52C2668DE2225CB97946 - - includeInIndex - 1 - isa - PBXFileReference - name - YapRowidSet.mm - path - YapDatabase/Internal/YapRowidSet.mm - sourceTree - <group> - - 10BA123C353632C6F4FF978E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseExtensionTransaction.m - path - YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m - sourceTree - <group> - - 11B7AB3F5BFBD5CF64A24721 - - fileRef - EC45ECF020F53D7130C60B49 - isa - PBXBuildFile - - 1253578AB1AAC77D8E9D0693 - - fileRef - C4F7FEE942FEF691E3AA2B30 - isa - PBXBuildFile - - 125F562C09B53384674F5F25 - - fileRef - 7834620FC228C687526C0882 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 1272DB4807DB303BEE9AA36E - - fileRef - C927CCD7B19D8BE9BD48DA5B - isa - PBXBuildFile - - 1297791150752323B9C5A918 - - fileRef - 8D0E15185E65DE5CD8FB0EC0 - isa - PBXBuildFile - - 133C7F1888D2A13E4D0C8F05 - - fileRef - 3A534974C696B9A0DA1475EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 13485812D9778A975E6D1984 - - fileRef - F3AC7EDAEE527675163FE062 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 139CC4A2FEEBE5DB92E89CD1 - - fileRef - 74F67760F189409288A5B76A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 13EDCCF437738926B3FE4D51 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - name - Podfile - path - ../Podfile - sourceTree - SOURCE_ROOT - xcLanguageSpecificationIdentifier - xcode.lang.ruby - - 142261C9D5E03ED9066F9757 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseRelationshipConnection.m - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m - sourceTree - <group> - - 1434EAF36CB80F84ED9D98CB - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - CA890C10A80DEDD1E26EE1DA - remoteInfo - Pods-Mantle - - 146E0F23B2821B4E1CA89499 - - fileRef - 5700F30AA8FF03072E769739 - isa - PBXBuildFile - - 14DBC5B4821BA0066AFF2427 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.script.sh - path - Pods-BlogTests-resources.sh - sourceTree - <group> - - 14F3AE946DF04B4D5E4094A1 - - buildActionMask - 2147483647 - files - - E083CA8ED154237A8CDB02E2 - FFAB92700F871A6A2403ACED - 5D7481FB0678E06F7B9DD0BF - EB66BD1444806823CFC29A2F - A064109944BFE15E9CC6F683 - 6C95826FAFE52067611C3AB2 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 150046D4BBB554405597341C - - fileRef - BE22EAA169B8B803CAD3EC55 - isa - PBXBuildFile - - 1530A55349F9689E21C41082 - - fileRef - F1C0AE2EA4B0777F447899ED - isa - PBXBuildFile - - 154F39422960C9437CCBC9B7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapCache.m - path - YapDatabase/Internal/YapCache.m - sourceTree - <group> - - 1579441F17A2C8760B3042A7 - - fileRef - B9E284862E5B161637C31E2F - isa - PBXBuildFile - - 16023EC41B5908B6050C1E2A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-OMGHTTPURLRQ-dummy.m - sourceTree - <group> - - 164C2238E28F933A4FA99917 - - buildActionMask - 2147483647 - files - - 77F9E66E36DD6F4A2B22087F - 9F87EC64930BC0469F2B8B11 - 6846F8AEF440C58E171E9CD1 - 72A3EE0636B60EB81734DC4A - 357C3D5651AC802EDB7538AC - 10121E4202FAD5A14D2F9E4D - CD747D7642193FC6522E7961 - FBA25172F996FCAD1222219C - 6269EBE92133A139AE5719D4 - 45CC8CAE7571059D9578FC19 - 404B7C8116C415391D290C9E - EAABC9AEE4E42439C829CF83 - BCFFA8F7134C59821A06632E - E6A416C0262183A0CC6234EF - 8B0978A2E18E93557C563DAB - 641893280780C96904C92D8E - 7747A9662618843CAF380D5D - 6D924154EE1542A5264E7568 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 16F4B34792781B4C514BB77F - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 38C4AFA484E8999903545200 - remoteInfo - Pods-BlogTests-CocoaLumberjack - - 16F54F54720AF455AB13108B - - baseConfigurationReference - F5A8223B1C33B1AB9E498E85 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 1705BB75DAA0AB2240165F6E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-libextobjc-prefix.pch - sourceTree - <group> - - 176411E7025810ABE8546215 - - fileRef - F510A47072303B51AA70548A - isa - PBXBuildFile - - 1794C0E2E76FE4BFE1A0CABE - - fileRef - 7E6CED80016EDD51589D3B17 - isa - PBXBuildFile - - 1828359B46EB3D089BA4D625 - - baseConfigurationReference - 49DCEDEBD6B53F3D5FB4B231 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 18683B38509456F84BE7B660 - - fileRef - 9AA3B3F7CEFE467EF8D4CE3C - isa - PBXBuildFile - - 186B40C274F3C53F71FF6C5D - - buildActionMask - 2147483647 - files - - 28D68B5CF62A7AFBD64961C8 - F819B59CBA6E9CBD13A99193 - D7B29C97FCD74FE6EBF283ED - A5658BFED93F7E3925A1A68B - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 18C20C33E9EE15AB6AFA5A7A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-CocoaLumberjack-prefix.pch - path - ../Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch - sourceTree - <group> - - 18D52AE807BCFEF5991E1D52 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseConnection.h - path - YapDatabase/YapDatabaseConnection.h - sourceTree - <group> - - 1907684C5959A2AA26AA8C8F - - fileRef - DE96E0E294B8B2855408137C - isa - PBXBuildFile - - 1928E70C0C75F0E6345B57E8 - - buildActionMask - 2147483647 - files - - 2B2789D45B295C289BE6A5A0 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 19334C35B1BEA24172F483BD - - fileRef - D802336E1655FB340EBC9409 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 19B8ED727E1382FD355BC787 - - fileRef - 4DB22EF0176AD3E9EE1AFCC1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 19CBE819AC57B7FA45B028BB - - fileRef - 39A0FC41A341F9849B9A85C9 - isa - PBXBuildFile - - 1A060968773848D6597A2855 - - children - - B6A247EF445935E36BDC2A3F - C603E25AFF71674FCC071C5B - 011623DB8A11A1559279E2BF - 4A5D8E6B97678C68E29FBA44 - B97FDB48E920BEAC567F74F5 - 6607FCD887172A37860230BA - C113191CF8DA0D427360EF7E - D0D6A232D5FD929F3BB6072A - 7F7B8F4F89D04766CA64EC2B - - isa - PBXGroup - name - Core - sourceTree - <group> - - 1A0911F00B0DA68EE7CCAE14 - - fileRef - 5748AF96C02626E9AC3CF4AC - isa - PBXBuildFile - - 1A86FDB5729AEFE96524B17C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLJSONAdapter.h - path - Mantle/MTLJSONAdapter.h - sourceTree - <group> - - 1AA085110AD15069B5E90BD1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-PromiseKit.xcconfig - sourceTree - <group> - - 1AA787AD406B814B0D0356D2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewMappings.m - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m - sourceTree - <group> - - 1AADA015B3C139AA1AF718D0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - OMGUserAgent.m - sourceTree - <group> - - 1AC1CF0849D48151E1E69C28 - - fileRef - FA36EFEA598C18B00262C163 - isa - PBXBuildFile - - 1ADDDEDBB8B879847170B376 - - isa - PBXTargetDependency - target - A75BBDE7086438FB91D81927 - targetProxy - C54BA3F2BAB971FDD2C0B4D0 - - 1AE6D8A7013D28B017877E5A - - fileRef - 18D52AE807BCFEF5991E1D52 - isa - PBXBuildFile - - 1B5C84EC70CD51FC7D6A3FEF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTRuntimeExtensions.m - path - extobjc/EXTRuntimeExtensions.m - sourceTree - <group> - - 1BA3668BA75A90591EF78E13 - - fileRef - E1D6D694F1DC16E728BA5335 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 1C20335467792710E5686E3F - - fileRef - 26D7F66B26AFB0D48D3909ED - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 1C41FF4B3A0E0DB5910CB5D0 - - children - - 7A9A5B6340BEBDD388AACB2E - 0795C3F541DAC18BC24984B1 - - isa - PBXGroup - name - NSInvocation+EXT - sourceTree - <group> - - 1C542F87BD931714FEF6F0FC - - fileRef - 7D759C580C13C0CBACA0849F - isa - PBXBuildFile - - 1CD23595C52FE4BBC8452188 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSearchResultsViewTransaction.m - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m - sourceTree - <group> - - 1CDEDCFB0A90214027282936 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseRelationshipOptions.m - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.m - sourceTree - <group> - - 1D69C7FEED59B65516086308 - - fileRef - 5F160243B37AEEA900ADB3AE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 1DBA3D953891E8CDC57D37EB - - fileRef - F731AD145A1F295B60219D57 - isa - PBXBuildFile - - 1E1755287C8F9CE015AF34E1 - - fileRef - D9FBB555089342AAFF18FD1E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 1F1C7875CD243FCAF97214DA - - buildActionMask - 2147483647 - files - - 96495579CE3C1700DE85CE7E - A5EAEB3171E943E4AFF95766 - 8ADB5CED1DF4687B26BEEEA8 - 3FB2CBE4D726DF39181A8839 - 840C2D4D997AAEAF5E0AD670 - 2CED9EF471B2A665FB0CBBBD - 3522FC11B73B30CF5F62A62A - 5F82C55CAF05CB38608F9CA3 - 2F8A72776506798515BB0415 - E3C35F4D3DF454F73CA8785F - 49CE8C9906953C2138984BDB - C8A2DC4401EBDAB3C791ECBD - 2B0071A7ECBD7ECC047902E3 - 4161D6BF7B4D875157F557F4 - 50AAE224E6ADC0FD5F85E4CF - 61C3ACAF90F37EC3EAD03F4F - 09209F9245977177087929A3 - ABC3177E0211DEDB7F2B06EF - 0839683493E194E9778FD0C9 - C5C3A8EC782B842563F7D184 - 22CE65DA4BD2D520F7D573B9 - 53535C5107894BB74E450C37 - 3E42D5284AF42F19DFA496A4 - 7350E5020B318A47825510F1 - 6A6FAF1BAD4169AB70B6C6C4 - 59DBEB1BFE914694BC288777 - 6253A5BAB33E2973DF226DC3 - 00EB60C9A62A3767A2A113BD - 9D72CF34BB4423E525063C2E - 793F7860C7DB182A67093ADA - CD67CB5C6996D27DB6102909 - 94FB487503E56593B2B695FB - 26B23587F2748EDAE0D5CB4B - FBD7D896586B9E0068FB55DF - 8E70F07209CC2D575EC91585 - FBF2C9963DF0135B4AD36268 - FBC20005AFD4FCFC47240369 - B7544ECE4CD45786C4729F1B - C74BBE30744B5DEE6156E083 - 79BD2941A83A52734F4C8DDF - 4F93894C457FCBEC38A99C7C - 94B2ABF1707BC0E90D29B5E4 - A9335EF19AB0BF9F03670420 - 3F9E7441B1D8962BD7A9AF23 - D95CA84B08A32970F09A5E05 - C59D325C7C07DEE63219CE85 - 80CBE700928C6662146EEB60 - 89D33B31A6191EB6E232507B - 2D3773CDF075A22199F2269A - 1E1755287C8F9CE015AF34E1 - 0BC9BEF690FE54343D4BF08A - E0BD33C3DD199D1D1EFD5D78 - EDDF27F1172E0DA1E57C26BF - 5920786A09E9F299A5EB170E - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 1F1C8C36532C598F1D8558F5 - - fileRef - 8C1DA800013C02AFF58D3026 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 1F2F99DE9A4C00FE28AC55E4 - - fileRef - F6C2D3DB1C0774716908D4CE - isa - PBXBuildFile - - 203ADFB7C75EBBFBA41E0FF9 - - fileRef - 7831B1B4A66083F2F576334E - isa - PBXBuildFile - - 2042F3861AE68F90291A08C2 - - fileRef - 5F160243B37AEEA900ADB3AE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 20C23FEA78DBD1BFC56E7E0A - - fileRef - D1E996BE0ABBE568966B112E - isa - PBXBuildFile - - 210D02FF91F45B2FB59914CC - - children - - 9B0483DD5B5BBDECDD4D2AF5 - 6FBDCD7F6DEBB95DF41D9B10 - 09267BA07E1B41DC602367AD - - isa - PBXGroup - name - CocoaLumberjack - path - CocoaLumberjack - sourceTree - <group> - - 211A58100BF97F2BC12B0CE9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndex.h - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h - sourceTree - <group> - - 22053307FDF1C16A3DB7B69A - - fileRef - 7068E31E7E607DC5EAC6013C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2218A227904125628444950E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - fwd.h - path - objc/PromiseKit/fwd.h - sourceTree - <group> - - 221A53EC4947C90C2D4362EA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-OHHTTPStubs.xcconfig - sourceTree - <group> - - 224CEAD71C9359F3EAD49489 - - fileRef - F31E1FF6F19E0F532DC7509A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 22CE65DA4BD2D520F7D573B9 - - fileRef - 7068E31E7E607DC5EAC6013C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 232A0DC2E72551E99BE461D5 - - fileRef - 08F2C7B599103FC0BCF1D7BB - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 2364693DE0219DC6B2DE8076 - - buildConfigurations - - 16F54F54720AF455AB13108B - BE3F2CF21847E6E8FBE7AAC8 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 237BA153D36F33463310C7F5 - - buildConfigurations - - 7902B18040F651A41A6DE453 - E9F69165AC3BE90EA0B74B47 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 237CAA329FB0113337568BC8 - - children - - 2ED139D0342733701B6E1A87 - EA7C9AED1E39B7DB673D49A1 - - isa - PBXGroup - name - NSMethodSignature+EXT - sourceTree - <group> - - 23A967C5A37AFDC511BAAFD0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchResultsView.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h - sourceTree - <group> - - 241FDF80FF75DF004C3F0AA4 - - fileRef - EFA167E931980D498BEDBA8C - isa - PBXBuildFile - - 24307A2E70BE8D17F46A4D57 - - fileRef - C6FD6C921CE4D0F425C3FF6E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 24BE8A3460D04A6A9B3E401A - - fileRef - 86D0230FC98D0F981B53C5ED - isa - PBXBuildFile - - 250A78C8CD713B4BA457FF80 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTScope.h - path - extobjc/EXTScope.h - sourceTree - <group> - - 2544ECDCA0FC392F035DAAD9 - - baseConfigurationReference - 95F6567C7B6C184546B40F39 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 2568CFD4A6FAAB51C63F29F4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipEdgePrivate.h - path - YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipEdgePrivate.h - sourceTree - <group> - - 258589569DF12B3B2A8E27F9 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 25CE9737B115528D9F9D83C9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFilteredViewPrivate.h - path - YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h - sourceTree - <group> - - 25DEC9D4B916397DA565F38E - - fileRef - 4D563DD93791AE9C0A209D5B - isa - PBXBuildFile - - 26A0EB9773E5D8B1A16C42B4 - - fileRef - B0BDAB6707945969960AF8E8 - isa - PBXBuildFile - - 26B23587F2748EDAE0D5CB4B - - fileRef - 0D9752CEE76F92DBE94F3732 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 26CEC49654D040C607F2926F - - children - - F731AD145A1F295B60219D57 - 3BF31B96AD0DB5F1B8B616FA - - isa - PBXGroup - name - EXTSelectorChecking - sourceTree - <group> - - 26D7F66B26AFB0D48D3909ED - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLValueTransformer.m - path - Mantle/MTLValueTransformer.m - sourceTree - <group> - - 27498FE4203166A99C9ED63C - - fileRef - A4A72EB139270DB5877F98A7 - isa - PBXBuildFile - - 276A303F5FDA27ECB1617D24 - - children - - 6090A7DBDD38835B7972BF6D - 3847D75562C082A537FE72CC - E65E19BDC940636C60C594A6 - BA12C07BF7E1A9D36387BB74 - 0383AA523C372C5E0BE85649 - 6C0509647707EF0A91DD2713 - B01FA4EC7388A3CFBB3F639F - - isa - PBXGroup - name - Pods - path - Target Support Files/Pods - sourceTree - <group> - - 277AAF4FEF28F245ABAA2A3B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSNotificationCenter+PromiseKit.m - path - objc/NSNotificationCenter+PromiseKit.m - sourceTree - <group> - - 27A6D3B9C8E418175CA20FBC - - buildActionMask - 2147483647 - files - - 59FD414DCFD84791F8A2DD9F - CF9C3B66B5706C19E34E5127 - 24BE8A3460D04A6A9B3E401A - 46F99351566C8E9C042B1049 - 3633B8C77CD2A63E4A0B3A46 - DE918B5BF41F4A54E265AAD6 - F745A2219C91F2E7C3008F06 - A918BF1E6FAAEAE3B7D615E9 - 7D757A573C92300B9332CFBD - B8D4B978EE1B11904FD3F61F - E8C835FE2E4F0DCC9A36A609 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 27AAE6EFCA6056FFF1F3BF7E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFullTextSearchSnippetOptions.m - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m - sourceTree - <group> - - 27ADC5EDB57744914308E786 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-PromiseKit-dummy.m - sourceTree - <group> - - 27B274A3A7DA2A8DDB30F536 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseExtension.m - path - YapDatabase/Extensions/Protocol/YapDatabaseExtension.m - sourceTree - <group> - - 27FBE5EBD233856BBAC028A7 - - buildActionMask - 2147483647 - files - - 6009CAFC581F8D11D6407B63 - 8886A778D89621FC7587B7EB - F5E9E8E2FCE0F6F79EF148C4 - C6FC1041D0AE734E944134BA - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 28099AA355746F5B578F4D04 - - fileRef - 8B45DE3D58E4B19169D7854D - isa - PBXBuildFile - - 284ED893EBCECAB692803B2B - - children - - 0FD3969237C6CD2004EBC12F - 5F160243B37AEEA900ADB3AE - - isa - PBXGroup - name - EXTConcreteProtocol - sourceTree - <group> - - 2857515943CD6342037AD074 - - fileRef - 41CBFFEE64E51235F7CEBA13 - isa - PBXBuildFile - - 289ED5A99FC2F21CF7C72567 - - buildConfigurations - - CF36EF770B3BFC420327326F - 7A13D3F5DFFDFDF122432AE4 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 28D61E46758D919CBFFE2E9B - - fileRef - EC13AAB60B55E8C698F35744 - isa - PBXBuildFile - - 28D68B5CF62A7AFBD64961C8 - - fileRef - 6793C55A7342798A007B7BE6 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 2906854A9D6EBDEDAB4940BC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-Mantle-dummy.m - sourceTree - <group> - - 2916F4DE7130F1A90158970C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabasePrivate.h - path - YapDatabase/Internal/YapDatabasePrivate.h - sourceTree - <group> - - 298541E54701F5D2D54F84CB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationship.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h - sourceTree - <group> - - 29B22886BAFF71AE782E669A - - isa - PBXTargetDependency - target - A5C7FDB89949F4F113730ADF - targetProxy - 65D46D14A30F8F82762FBDC6 - - 2A0931B9CBA71CAFE21F8382 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-libextobjc-dummy.m - sourceTree - <group> - - 2A0A0DD82ACADA1A15078A75 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 2A344DE83E68E32EC8FB0A75 - - fileRef - 7D759C580C13C0CBACA0849F - isa - PBXBuildFile - - 2A3A8198CEF6A7DA0D0C8DDA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipNode.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h - sourceTree - <group> - - 2A644BC373CC5B46E82B4836 - - fileRef - 6732078F190FE3A6541908B5 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 2A7340B5DCBB5FE4BE4FD989 - - baseConfigurationReference - DE16E0B43555E1276393B2CB - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-YapDatabase/Pods-YapDatabase-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 2AC872F3FC3B531BC9047A47 - - baseConfigurationReference - 6064C9992B037CD5DDBE2E0D - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 2B0071A7ECBD7ECC047902E3 - - fileRef - C635B47476AEB1F75B8E4A59 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2B2789D45B295C289BE6A5A0 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 2B42F3392D5D4DC4FAE1E784 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-libextobjc.a - sourceTree - BUILT_PRODUCTS_DIR - - 2B9AF0E909B3217BC2B8CA0B - - fileRef - 8D0E15185E65DE5CD8FB0EC0 - isa - PBXBuildFile - - 2BE6F7CFD919CE760ABD5CFF - - fileRef - 70B0451AC76A668F9473988B - isa - PBXBuildFile - - 2BFD083E3A291B6822D31F46 - - fileRef - D1C13D67261C17D3CCA8934D - isa - PBXBuildFile - - 2C57FCB1FB0F0798C5865ED5 - - buildConfigurationList - AA782631F71F0C012E5D5995 - buildPhases - - 14F3AE946DF04B4D5E4094A1 - 8836C433152B661E7FAE2F87 - 0A76FD5A3DB281D4EFCAA061 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-BlogTests-OHHTTPStubs - productName - Pods-BlogTests-OHHTTPStubs - productReference - DF59954913D98ADEF2981676 - productType - com.apple.product-type.library.static - - 2CA126641BD6222948B53DF5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapCollectionKey.h - path - YapDatabase/Utilities/YapCollectionKey.h - sourceTree - <group> - - 2CED9EF471B2A665FB0CBBBD - - fileRef - B67A7082DD97F125F8E570C3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2D3773CDF075A22199F2269A - - fileRef - BCA4D743CE8358E7DCE71484 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2D41F9E5184FA73E6514699E - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 2D57BFA181418314DEE35199 - - buildActionMask - 2147483647 - files - - 86231AC0447491EEDE46A8D3 - 1F2F99DE9A4C00FE28AC55E4 - 0DBFE01B7F9FEF47FC396779 - 064F60C168F0616EE6B27951 - D97755ABDEC7FE511859791B - 5D4C9582549D16B738D58BDD - 09BAD25366931CEA0CE78FA1 - BAD11F8A0C6D34221236FC5F - 545993B9754CC64DF863CD8C - 00B561A39215EFF1751B4356 - 5FEDC40A191F9F6F2C661E44 - 2D41F9E5184FA73E6514699E - 7EC1F07D0D591112E9415495 - 9409BCC2B7B1A09973E00E62 - CA377536DB9E4EFCFC51334F - 150046D4BBB554405597341C - 93F1CD410DA33DB2DF2B3DC9 - 6AF4180D842303EE9893FBBE - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 2E4C2458446B7FB289F27881 - - fileRef - F8086C3AC09B25ED2B74DF4B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2E4DD1B85CBB0B9B4FE20622 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-dummy.m - sourceTree - <group> - - 2E569D36941B0C5CA76D56E2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapSet.h - path - YapDatabase/Utilities/YapSet.h - sourceTree - <group> - - 2E62776E143058C1EB05E368 - - baseConfigurationReference - 08076FA20D8ACA0E11E1AF6C - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-Mantle/Pods-Mantle-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 2E7A9AB0AA20A443C5A400EA - - baseConfigurationReference - 08076FA20D8ACA0E11E1AF6C - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-Mantle/Pods-Mantle-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 2ED139D0342733701B6E1A87 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSMethodSignature+EXT.h - path - extobjc/NSMethodSignature+EXT.h - sourceTree - <group> - - 2F1672B212AA041F47E06565 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-YapDatabase.a - sourceTree - BUILT_PRODUCTS_DIR - - 2F2692A93F2126F92E26FB8C - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 2F381278E3B56A8F25876C6F - - isa - PBXTargetDependency - target - C18E92409B2B034FA606C91B - targetProxy - 82FE4D9FF895D48EA279B3F7 - - 2F80D3CFCCA1A010EF0F415D - - fileRef - B52A16813A4A1CE2F582CA7A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2F8A72776506798515BB0415 - - fileRef - 27B274A3A7DA2A8DDB30F536 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 2FA8AF4D3A0DAB3533455EB2 - - buildConfigurations - - 4D664B9CF91ED60F8308878F - 875B1C7C2FEDB4E8932A6348 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 2FE0F3F24F4E8BB06C84608C - - fileRef - 7A5AC30E079774B19A2F2280 - isa - PBXBuildFile - - 2FE793C339D4F2D5FFAA4399 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTScope.m - path - Mantle/extobjc/EXTScope.m - sourceTree - <group> - - 30F22C84531501D7A3372097 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseExtensionConnection.m - path - YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m - sourceTree - <group> - - 316171FCCB0AABE279527975 - - fileRef - 5E2F3B23634215065298448F - isa - PBXBuildFile - - 3263798E68084DBDC26C4B05 - - fileRef - A32C636BF537187FE0C16EE5 - isa - PBXBuildFile - - 32A72324F4A6C84ABB17E2C0 - - fileRef - 7E6CED80016EDD51589D3B17 - isa - PBXBuildFile - - 338924D00EA0CC52E2007C7B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexSetupPrivate.h - path - YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h - sourceTree - <group> - - 33FAA249EC636E22F4DEC988 - - fileRef - 4DA4F4EA6D77D73C78853D97 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3480411692A4F653B3E73C38 - - fileRef - DF0E0A58400AC34BF025F0E3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 3490E786050FA5CC50C84CD8 - - fileRef - 522C87EB500EE5B12ACEEE5A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 3522FC11B73B30CF5F62A62A - - fileRef - 7834620FC228C687526C0882 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 354E0846412CEF0AD4E30091 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Promise.h - path - objc/PromiseKit/Promise.h - sourceTree - <group> - - 357C3D5651AC802EDB7538AC - - fileRef - B02EDE68D12C8E7B4F857A94 - isa - PBXBuildFile - - 359948A64E24BE0C9EDDF8EE - - attributes - - LastUpgradeCheck - 0510 - - buildConfigurationList - 237BA153D36F33463310C7F5 - compatibilityVersion - Xcode 3.2 - developmentRegion - English - hasScannedForEncodings - 0 - isa - PBXProject - knownRegions - - en - - mainGroup - 8BDBEB7E3352C3BB23D812CB - productRefGroup - 981A35969EFD8A8CD96149B1 - projectDirPath - - projectReferences - - projectRoot - - targets - - 7E628556C9D4AF0D8A7BA197 - 926587A7088B1C71AF12ABED - 38C4AFA484E8999903545200 - A5C7FDB89949F4F113730ADF - 2C57FCB1FB0F0798C5865ED5 - 4B474CABC48D73A142E712D3 - C7CB59FD96B0D84FE5F98540 - 6831A48FA46B88E918F641FE - 42F4D37A0CEF471792804AC3 - CB3C845CD2284348BA439199 - CA890C10A80DEDD1E26EE1DA - C18E92409B2B034FA606C91B - 8D55202778D4D2D16D149057 - A75BBDE7086438FB91D81927 - B6741702AE4E022F6A4078C2 - - - 35E5B349224C4F8550F055DA - - fileRef - 58D904E7D52CDC8603AE0006 - isa - PBXBuildFile - - 36154702DA969D3E68BAAB63 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewTransaction.h - path - YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h - sourceTree - <group> - - 3618A04504801463F3664011 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseQuery.h - path - YapDatabase/Utilities/YapDatabaseQuery.h - sourceTree - <group> - - 361F5B3321DDFB93D97D5886 - - fileRef - 2FE793C339D4F2D5FFAA4399 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3633B8C77CD2A63E4A0B3A46 - - fileRef - B0E7EA1627E40379E605D413 - isa - PBXBuildFile - - 3633F56F980CECA78B6869E9 - - children - - 1A86FDB5729AEFE96524B17C - 4DA4F4EA6D77D73C78853D97 - 8D0E15185E65DE5CD8FB0EC0 - D7536964C22982A04E649E91 - 7C0E1DAA278CAF4CEB13ED80 - E16890EE7DBF711D338DF459 - DE96E0E294B8B2855408137C - 867752A3C7B2670ACBDF32DE - 70B0451AC76A668F9473988B - CDFF8E8307D4F378212C6A5B - 062F7ED90F24410039196758 - 26D7F66B26AFB0D48D3909ED - EC45ECF020F53D7130C60B49 - 8CB496A1D29F4F27BA895341 - F6ED69D788774E3D338D2BC9 - 90A448ECAB2BF9356CD7FFDA - BAB779202635DD0BF3382B4F - 6339D26E247F363AABF23B50 - 366561ED25A6F8A70756ED1A - 58D904E7D52CDC8603AE0006 - D4D6570710557532B7432896 - B63E1A4B3FC3022C9D696DAD - 9C7D485F506CEDBF73A533CA - 504892A7A23057E7857AB508 - 3A534974C696B9A0DA1475EE - D080FD9604103BE0640F89DE - 419C839945F685EF06AEF6A0 - - isa - PBXGroup - name - Mantle - path - Mantle - sourceTree - <group> - - 366561ED25A6F8A70756ED1A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSError+MTLModelException.m - path - Mantle/NSError+MTLModelException.m - sourceTree - <group> - - 373C4956C235E248F65354EB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFilteredViewTransaction.m - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m - sourceTree - <group> - - 373E85A4772D3F741C3C38DA - - fileRef - D8585C3EDC9BF6E4EBD080E6 - isa - PBXBuildFile - - 379329E7D9832FAF6DA3CCF4 - - fileRef - 43CA323806A6948788759144 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 37CA1596F8B37A20C61D0417 - - fileRef - 547FECE7A3BD7B14D730F49E - isa - PBXBuildFile - - 38181B270180D765C5AFDDE9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-YapDatabase-dummy.m - path - ../Pods-YapDatabase/Pods-YapDatabase-dummy.m - sourceTree - <group> - - 383B6F17A788889033FFE2F4 - - fileRef - 78FA48202A994D971298A670 - isa - PBXBuildFile - - 38428240938B9F343493DCA0 - - fileRef - CDFF8E8307D4F378212C6A5B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3847D75562C082A537FE72CC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Pods-acknowledgements.plist - sourceTree - <group> - - 386CAF582008202A84886B1E - - baseConfigurationReference - 4368E21FD1F0A9DCC27EADBE - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 38A1039D4DBB2BF653BF42E4 - - fileRef - 0D2BEEA66F53ED2FC2927BD9 - isa - PBXBuildFile - - 38C4AFA484E8999903545200 - - buildConfigurationList - 2364693DE0219DC6B2DE8076 - buildPhases - - 695EAE7E4AD280D1CAEB77AF - 8924C299BA29A65346C228B3 - 695ABFE78B38236E7C01FC7D - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-BlogTests-CocoaLumberjack - productName - Pods-BlogTests-CocoaLumberjack - productReference - B58A60B3858FD623033B63C1 - productType - com.apple.product-type.library.static - - 3921FADA1AE6316C9A28ACE5 - - fileRef - 5C841B874C97CD7073E9E0EC - isa - PBXBuildFile - - 393BBD320AF7C7C3E82648CE - - fileRef - D2B248A85F1C7437A6C33E20 - isa - PBXBuildFile - - 39A073AA28B50F500C84B821 - - fileRef - B63E1A4B3FC3022C9D696DAD - isa - PBXBuildFile - - 39A0FC41A341F9849B9A85C9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipConnection.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h - sourceTree - <group> - - 3A31BB4201E034889A8C6FA6 - - fileRef - 74F67760F189409288A5B76A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3A534974C696B9A0DA1475EE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSValueTransformer+MTLPredefinedTransformerAdditions.m - path - Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m - sourceTree - <group> - - 3AAB2DFEEB0EB34EF9814A16 - - fileRef - 4B89BD4C135CD3CBF84E541D - isa - PBXBuildFile - - 3B32D0FC8252A74B6E79CBE7 - - fileRef - 7A52CC8626648093CEF7AE4A - isa - PBXBuildFile - - 3B3D883DDFB8585D392CA046 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewState.m - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m - sourceTree - <group> - - 3BA6018DD772EA2374EFEFDB - - fileRef - 02DBE9C9DF1E0B0EEBA0646A - isa - PBXBuildFile - - 3BAB55D8C39CB29C7BD4546D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDLog.h - path - Lumberjack/DDLog.h - sourceTree - <group> - - 3BF31B96AD0DB5F1B8B616FA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTSelectorChecking.m - path - extobjc/EXTSelectorChecking.m - sourceTree - <group> - - 3C20827154A9B04ACFAF891C - - fileRef - 55472893377C7DCEA23941A3 - isa - PBXBuildFile - - 3C7164025C8086CB0FD1A89C - - fileRef - 0795C3F541DAC18BC24984B1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3CE8B3156FCD8ABDF43DD480 - - fileRef - D8585C3EDC9BF6E4EBD080E6 - isa - PBXBuildFile - - 3D2D47E887770E30631EA286 - - isa - PBXTargetDependency - target - 38C4AFA484E8999903545200 - targetProxy - 16F4B34792781B4C514BB77F - - 3D9A9AC30E8560E53C84C05B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewRangeOptionsPrivate.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h - sourceTree - <group> - - 3DAFBD3E9A0627BB7058615F - - fileRef - D67B8B4615343EA915F59B63 - isa - PBXBuildFile - - 3DD8402C7BA55BFF09B4632F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTScope.h - path - Mantle/extobjc/EXTScope.h - sourceTree - <group> - - 3DDF9DF8D7DF393258D985FC - - buildActionMask - 2147483647 - files - - 0AFD6B4581479C9C1307416A - 383B6F17A788889033FFE2F4 - 71A318F233310166E54A5AC6 - 49C593CB362C5195898A33D0 - 1297791150752323B9C5A918 - 75F02582F35DDF6C5AD819DA - 0412BDD030399C866EED506C - BF7BFAA783101D1987EEFD2B - FC813BAE54124E511519FA2D - EDC5CAF7C7C80E3E2A2D7ACE - D17206B823C3958618C6FA67 - 8CC3D79704CCE254511379A8 - F61CAD9071BE127939616308 - A570DDCA14F226264040EDBB - 9C363A2CCDB295751EB81EC9 - 5018984047F465DCCC2C54C8 - ABCD292FC5A3E55C6F18660F - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 3E42D5284AF42F19DFA496A4 - - fileRef - C6FD6C921CE4D0F425C3FF6E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 3E532AC8C420C790FCD188DA - - fileRef - 4E059837F347B34276C71290 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 3E6EB71B3F314876BF11166A - - fileRef - 611C30C092B9666EE6A0C788 - isa - PBXBuildFile - - 3F0BE7C879F42DDD970ABAFA - - children - - E938B4E9BD4AEA348A41C73B - 6E30A649D0ED2E40F3148DBE - 4CD8C1D08D4858BB2991BAB8 - 6BF8D3DA96A53B9FF39B3E8F - E00A3BCDDE919BD915C9752F - - isa - PBXGroup - name - OMGHTTPURLRQ - path - OMGHTTPURLRQ - sourceTree - <group> - - 3F72484C3810AB03BCE6D24E - - fileRef - 938962EC2EECB2610DE86053 - isa - PBXBuildFile - - 3F9E7441B1D8962BD7A9AF23 - - fileRef - 9CE4EC9165C231CFC4DC9316 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 3FB2CBE4D726DF39181A8839 - - fileRef - 5BA5B6F01AEBE7FCBA5D1A5F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 404B7C8116C415391D290C9E - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 40CDE38ACDC59C7C8BE0C99B - - fileRef - 4DA4F4EA6D77D73C78853D97 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 40D3E914D38C3D28367514AE - - fileRef - FC0366356620DF9861F43225 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 40DE3B79980EAF060496E853 - - fileRef - 2CA126641BD6222948B53DF5 - isa - PBXBuildFile - - 41116C01E47A42EEBDC6895C - - fileRef - E5B4081AC0A6B88921DC5FB1 - isa - PBXBuildFile - - 412353141474E421CEA26A7F - - fileRef - F374224ACFF5AF242D15DEE2 - isa - PBXBuildFile - - 4161D6BF7B4D875157F557F4 - - fileRef - 373C4956C235E248F65354EB - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 419C839945F685EF06AEF6A0 - - children - - 7546557388C901CF79E23BF1 - 78FA48202A994D971298A670 - 4F2E4FAADD6297C85BE36092 - 3DD8402C7BA55BFF09B4632F - 2FE793C339D4F2D5FFAA4399 - E7AAAC5CF03046134533E163 - - isa - PBXGroup - name - extobjc - sourceTree - <group> - - 41CAD9A74D3A66E4D4E78444 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSDictionary+YapDatabase.m - path - YapDatabase/Internal/NSDictionary+YapDatabase.m - sourceTree - <group> - - 41CBFFEE64E51235F7CEBA13 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFilteredViewTransaction.h - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h - sourceTree - <group> - - 423F116EDFDA79C7E0CD41FE - - fileRef - 8CB496A1D29F4F27BA895341 - isa - PBXBuildFile - - 42D5E8BE1C55D670088F3516 - - fileRef - 55472893377C7DCEA23941A3 - isa - PBXBuildFile - - 42F4D37A0CEF471792804AC3 - - buildConfigurationList - DB9F42EBD379D35ECB4ED533 - buildPhases - - 81F2A0C04F4B23CAE5B79213 - A28D475229208F2DE7160037 - C031756E8371D8EF0232CC22 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-BlogTests-libextobjc - productName - Pods-BlogTests-libextobjc - productReference - 2B42F3392D5D4DC4FAE1E784 - productType - com.apple.product-type.library.static - - 4331ACC94CF1314F64CE5715 - - fileRef - 95A06746E8E22F9210701C20 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 4368E21FD1F0A9DCC27EADBE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-OMGHTTPURLRQ-Private.xcconfig - sourceTree - <group> - - 43CA323806A6948788759144 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDMultiFormatter.m - path - Lumberjack/Extensions/DDMultiFormatter.m - sourceTree - <group> - - 44051C84E1D6B418B3CD96DA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseManager.m - path - YapDatabase/Internal/YapDatabaseManager.m - sourceTree - <group> - - 4461408D25667B0E5C30636E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapNull.m - path - YapDatabase/Internal/YapNull.m - sourceTree - <group> - - 44CEB83E1D29D338646183FA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseRelationshipTransaction.m - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m - sourceTree - <group> - - 450E21DD059A05B0C96858F2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSURLConnection+PromiseKit.m - path - objc/NSURLConnection+PromiseKit.m - sourceTree - <group> - - 4533A270C27A3A6C4CC7A60D - - children - - B959903CD20DBFADD1872FC8 - 41CAD9A74D3A66E4D4E78444 - 0F456E30C3CE6879F902B4A4 - 154F39422960C9437CCBC9B7 - 2CA126641BD6222948B53DF5 - 5BA5B6F01AEBE7FCBA5D1A5F - C1446E03977584F292E382D2 - A0A00489F6014D923B83648A - 18D52AE807BCFEF5991E1D52 - B67A7082DD97F125F8E570C3 - 4B89BD4C135CD3CBF84E541D - 7834620FC228C687526C0882 - B0BDAB6707945969960AF8E8 - C512CB35DECD2AF094B06608 - 510C9911703F11FB4D0090DF - 27B274A3A7DA2A8DDB30F536 - 6FBCDD252928F404E3196B62 - 30F22C84531501D7A3372097 - F1C0AE2EA4B0777F447899ED - 4D563DD93791AE9C0A209D5B - 10BA123C353632C6F4FF978E - 9BAE8517935E4652DA18C03F - FDD93D0B6173305BBF61C92C - EAA54005DF3802B5546464A2 - C635B47476AEB1F75B8E4A59 - 25CE9737B115528D9F9D83C9 - 41CBFFEE64E51235F7CEBA13 - 373C4956C235E248F65354EB - 5EE55C5C761C7A0D95109C58 - 55472893377C7DCEA23941A3 - C9CDABBFA46667358027FC6A - F955D1FAF99985C04E471CC4 - A1A500530821BC19FFD71BF2 - 96B496B9BA6DEDCC0CF4FEB5 - 73420BB7DEB31ACBFA43E030 - 27AAE6EFCA6056FFF1F3BF7E - D99791BAD09133E58E937091 - 0D700C2A0BD0B56B170D7BA0 - 5748AF96C02626E9AC3CF4AC - F6098873BF3A85424034C965 - A4A72EB139270DB5877F98A7 - 44051C84E1D6B418B3CD96DA - C4F7FEE942FEF691E3AA2B30 - 7068E31E7E607DC5EAC6013C - 2916F4DE7130F1A90158970C - 3618A04504801463F3664011 - DF0E0A58400AC34BF025F0E3 - 298541E54701F5D2D54F84CB - C6FD6C921CE4D0F425C3FF6E - 39A0FC41A341F9849B9A85C9 - 142261C9D5E03ED9066F9757 - 5C841B874C97CD7073E9E0EC - FC0366356620DF9861F43225 - 2568CFD4A6FAAB51C63F29F4 - 2A3A8198CEF6A7DA0D0C8DDA - 8D55FA7D2E10B4E5BDBCBC7D - 1CDEDCFB0A90214027282936 - 611C30C092B9666EE6A0C788 - 73DAFF00036F4792002AB223 - 44CEB83E1D29D338646183FA - D1C13D67261C17D3CCA8934D - 7FFC350D592E57C150B8970F - A6773877A672078CBD6D2122 - 23A967C5A37AFDC511BAAFD0 - CFF4322F158FA5348F260B7E - B9E284862E5B161637C31E2F - 9ED8B6288E2CF5F95D626F53 - 8B45DE3D58E4B19169D7854D - 8C1DA800013C02AFF58D3026 - EFA167E931980D498BEDBA8C - 53545B12E4A487595ED3541A - 1CD23595C52FE4BBC8452188 - 211A58100BF97F2BC12B0CE9 - 0D9752CEE76F92DBE94F3732 - 0D2BEEA66F53ED2FC2927BD9 - BAD8B2814A3FB6D5EFC732EE - 5700F30AA8FF03072E769739 - 522C87EB500EE5B12ACEEE5A - 83FEB76F6002C9CDDF1EC006 - 9AA3B3F7CEFE467EF8D4CE3C - D084BE4E40606CBC76CE60B8 - 338924D00EA0CC52E2007C7B - F510A47072303B51AA70548A - D4BF1170DCB1DE7AF085A112 - 7A52CC8626648093CEF7AE4A - F0CB53A38F4A65F13419D7F7 - CDD7A7066B13434D8FA030CE - D2B248A85F1C7437A6C33E20 - 85A7A35498CDA73E12FAE079 - 834CB96786F68598ABDC42B9 - 0E149F643670201E753CB1E2 - 4763506A491EFCCF16E29DD3 - E1D6D694F1DC16E728BA5335 - 88FE7FFFEAB6DF14572DA07A - D1E996BE0ABBE568966B112E - 7BDEC11412D59D2DB449B754 - 5E2F3B23634215065298448F - 1AA787AD406B814B0D0356D2 - A11CAC5E5E88C2454F959D60 - F2AC98A4DF465FBE6C7B1B28 - 9CE4EC9165C231CFC4DC9316 - D8585C3EDC9BF6E4EBD080E6 - B52A16813A4A1CE2F582CA7A - AD2B1493CDAAF65711488F8D - 76D179A9618236CAB6A3079A - AF4B16A7F886887E3429B1D4 - C69BCF8DB07E1BDADBBD4A65 - AD85D1B60A21BC6069E26213 - 3D9A9AC30E8560E53C84C05B - A3D56F7C0081101236A1ADFB - 3B3D883DDFB8585D392CA046 - 36154702DA969D3E68BAAB63 - BCA4D743CE8358E7DCE71484 - 938962EC2EECB2610DE86053 - E22135502E6F21DDE43963C6 - D9FBB555089342AAFF18FD1E - 7D759C580C13C0CBACA0849F - 4461408D25667B0E5C30636E - 79AE24DD32AD0A77E53AD976 - 107F52C2668DE2225CB97946 - 2E569D36941B0C5CA76D56E2 - B8A98F7EBA444817481514EE - C927CCD7B19D8BE9BD48DA5B - F3AC7EDAEE527675163FE062 - - isa - PBXGroup - name - common - sourceTree - <group> - - 4533EFD6D984FD606E90BFA8 - - fileRef - 4B89BD4C135CD3CBF84E541D - isa - PBXBuildFile - - 4564BFB8DD35CC49BBA83003 - - fileRef - D802336E1655FB340EBC9409 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 45CC8CAE7571059D9578FC19 - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 46B5E383E5459D1F9A59E391 - - fileRef - 0FD3969237C6CD2004EBC12F - isa - PBXBuildFile - - 46F99351566C8E9C042B1049 - - fileRef - CEB8B561F98987335D130E56 - isa - PBXBuildFile - - 4763506A491EFCCF16E29DD3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewChange.h - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h - sourceTree - <group> - - 4942F30AC0DA29996C06C02D - - fileRef - F955D1FAF99985C04E471CC4 - isa - PBXBuildFile - - 49C593CB362C5195898A33D0 - - fileRef - 1A86FDB5729AEFE96524B17C - isa - PBXBuildFile - - 49CE8C9906953C2138984BDB - - fileRef - 10BA123C353632C6F4FF978E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 49DCEDEBD6B53F3D5FB4B231 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests.release.xcconfig - sourceTree - <group> - - 4A1A06F2A5C18C7EFF4C5B0A - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 4A2DAB25F31AC9E43FA6314E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-YapDatabase-prefix.pch - path - ../Pods-YapDatabase/Pods-YapDatabase-prefix.pch - sourceTree - <group> - - 4A40B27CCAEB84F14D7EF3A0 - - baseConfigurationReference - C6C84C593E998BBE858E331B - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 4A5D8E6B97678C68E29FBA44 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - OHHTTPStubsResponse.h - path - OHHTTPStubs/Sources/OHHTTPStubsResponse.h - sourceTree - <group> - - 4B2BFBB3BAF1D7D390C7C64A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - UIViewController+PromiseKit.h - path - objc/UIViewController+PromiseKit.h - sourceTree - <group> - - 4B474CABC48D73A142E712D3 - - buildConfigurationList - 0D086505BA8DFD441153D392 - buildPhases - - 186B40C274F3C53F71FF6C5D - B999EF649B40AF9EE6B3436C - 548F95433077DC04A4FD7E78 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-BlogTests-OMGHTTPURLRQ - productName - Pods-BlogTests-OMGHTTPURLRQ - productReference - 0ADA1F3E78D7F286AD9EB2CE - productType - com.apple.product-type.library.static - - 4B89BD4C135CD3CBF84E541D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseConnectionDefaults.h - path - YapDatabase/Internal/YapDatabaseConnectionDefaults.h - sourceTree - <group> - - 4BC566EA61666FAC176E66D9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTSynthesize.h - path - extobjc/EXTSynthesize.h - sourceTree - <group> - - 4C24CD3EC2B8F8C7C3681DCE - - fileRef - AF4B16A7F886887E3429B1D4 - isa - PBXBuildFile - - 4CD8C1D08D4858BB2991BAB8 - - children - - 7501B6E05F277908F49B1A2C - 6793C55A7342798A007B7BE6 - - isa - PBXGroup - name - FormURLEncode - sourceTree - <group> - - 4CFB2D7C0381F7C08C8867D2 - - fileRef - 53545B12E4A487595ED3541A - isa - PBXBuildFile - - 4D344199CFBF21CC8F08412B - - fileRef - 90A448ECAB2BF9356CD7FFDA - isa - PBXBuildFile - - 4D563DD93791AE9C0A209D5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseExtensionTransaction.h - path - YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h - sourceTree - <group> - - 4D664B9CF91ED60F8308878F - - baseConfigurationReference - 9BDBADA6AC31F46AE620270E - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PromiseKit/Pods-PromiseKit-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 4D8AFB2005B50CC1CE0E3A3A - - fileRef - C512CB35DECD2AF094B06608 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 4DA4F4EA6D77D73C78853D97 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLJSONAdapter.m - path - Mantle/MTLJSONAdapter.m - sourceTree - <group> - - 4DB22EF0176AD3E9EE1AFCC1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - UIView+PromiseKit.m - path - objc/UIView+PromiseKit.m - sourceTree - <group> - - 4E059837F347B34276C71290 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDLog.m - path - Lumberjack/DDLog.m - sourceTree - <group> - - 4EDD3C130475F1720C92288B - - fileRef - 2E4DD1B85CBB0B9B4FE20622 - isa - PBXBuildFile - - 4F2E4FAADD6297C85BE36092 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTRuntimeExtensions.m - path - Mantle/extobjc/EXTRuntimeExtensions.m - sourceTree - <group> - - 4F644E76076FCBD98D2BF7C5 - - fileRef - 44CEB83E1D29D338646183FA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 4F93894C457FCBEC38A99C7C - - fileRef - E1D6D694F1DC16E728BA5335 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 4FEC11B7B1234A00901A6F6E - - fileRef - B9E284862E5B161637C31E2F - isa - PBXBuildFile - - 5018984047F465DCCC2C54C8 - - fileRef - 504892A7A23057E7857AB508 - isa - PBXBuildFile - - 504892A7A23057E7857AB508 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSValueTransformer+MTLPredefinedTransformerAdditions.h - path - Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h - sourceTree - <group> - - 50AAE224E6ADC0FD5F85E4CF - - fileRef - C9CDABBFA46667358027FC6A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 50E907BF5ABC5D19B4FDB836 - - fileRef - D1C13D67261C17D3CCA8934D - isa - PBXBuildFile - - 510C9911703F11FB4D0090DF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseExtension.h - path - YapDatabase/Extensions/Protocol/YapDatabaseExtension.h - sourceTree - <group> - - 516776F29F82903BC216725F - - fileRef - 366561ED25A6F8A70756ED1A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 516FFB7AF0EF7083290567C5 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - B6741702AE4E022F6A4078C2 - remoteInfo - Pods-libextobjc - - 517B08CAFF905E0535E8F506 - - fileRef - 79AE24DD32AD0A77E53AD976 - isa - PBXBuildFile - - 5190A5E03231E9612A665B2F - - fileRef - 2ED139D0342733701B6E1A87 - isa - PBXBuildFile - - 51BF4631E636D3074819F80C - - fileRef - 0F456E30C3CE6879F902B4A4 - isa - PBXBuildFile - - 51BFE639418954157FD9CA51 - - fileRef - BAB779202635DD0BF3382B4F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 51F394BFC606EEC54B93A4A9 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 2C57FCB1FB0F0798C5865ED5 - remoteInfo - Pods-BlogTests-OHHTTPStubs - - 522C87EB500EE5B12ACEEE5A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSecondaryIndexOptions.m - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m - sourceTree - <group> - - 525F3EBAC3828750176EA9B5 - - fileRef - D7536964C22982A04E649E91 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 526514FC801A87957576E3CD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PromiseKit+Foundation.h - path - objc/deprecated/PromiseKit+Foundation.h - sourceTree - <group> - - 52A95E926EE03709543D744A - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 53535C5107894BB74E450C37 - - fileRef - DF0E0A58400AC34BF025F0E3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 53545B12E4A487595ED3541A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchResultsViewTransaction.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.h - sourceTree - <group> - - 535E8B823A530096896631A2 - - fileRef - 95A06746E8E22F9210701C20 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 540EFADE59DEA99C26D030B8 - - fileRef - F731AD145A1F295B60219D57 - isa - PBXBuildFile - - 545993B9754CC64DF863CD8C - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 547FECE7A3BD7B14D730F49E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDDispatchQueueLogFormatter.h - path - Lumberjack/Extensions/DDDispatchQueueLogFormatter.h - sourceTree - <group> - - 548F95433077DC04A4FD7E78 - - buildActionMask - 2147483647 - files - - 7C5D21B39C85F0DBA566CFEA - F13B084D8A4FFE7E1F1C45F0 - 3DAFBD3E9A0627BB7058615F - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 55025150AAAC34CB87BC2C00 - - fileRef - 611C30C092B9666EE6A0C788 - isa - PBXBuildFile - - 55472893377C7DCEA23941A3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFullTextSearch.h - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h - sourceTree - <group> - - 55647965FC4BC1D0149D79CC - - fileRef - 8B9548ECA3F342A1E5B13FA8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 558E2ABECE30B09027FCA6EF - - fileRef - D99791BAD09133E58E937091 - isa - PBXBuildFile - - 55D5F5E55C384B44FF3F8388 - - fileRef - 211A58100BF97F2BC12B0CE9 - isa - PBXBuildFile - - 55F387549037865FB6561C5E - - fileRef - 5EE55C5C761C7A0D95109C58 - isa - PBXBuildFile - - 56512318CDB690F3C59EB754 - - fileRef - B0E7EA1627E40379E605D413 - isa - PBXBuildFile - - 5700F30AA8FF03072E769739 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexOptions.h - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h - sourceTree - <group> - - 5748AF96C02626E9AC3CF4AC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseLogging.h - path - YapDatabase/Internal/YapDatabaseLogging.h - sourceTree - <group> - - 57BB40ADF6BD419284934FAA - - fileRef - 77377418499DFD94DDEF729F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 5826709045CFBF1DBBB2BBE0 - - fileRef - 5E2F3B23634215065298448F - isa - PBXBuildFile - - 58D904E7D52CDC8603AE0006 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSObject+MTLComparisonAdditions.h - path - Mantle/NSObject+MTLComparisonAdditions.h - sourceTree - <group> - - 59207766A0320FA3F0E4FE68 - - fileRef - 338924D00EA0CC52E2007C7B - isa - PBXBuildFile - - 5920786A09E9F299A5EB170E - - fileRef - F3AC7EDAEE527675163FE062 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 592F7BD907EDDFC3A0B0502F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDFileLogger.h - path - Lumberjack/DDFileLogger.h - sourceTree - <group> - - 597AEB5FE901D518D08E176E - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 38C4AFA484E8999903545200 - remoteInfo - Pods-BlogTests-CocoaLumberjack - - 59DBEB1BFE914694BC288777 - - fileRef - 1CDEDCFB0A90214027282936 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 59FD414DCFD84791F8A2DD9F - - fileRef - 02DBE9C9DF1E0B0EEBA0646A - isa - PBXBuildFile - - 5AADEA1F2899529E15064940 - - fileRef - CEB8B561F98987335D130E56 - isa - PBXBuildFile - - 5B06038C4324D650F35BD2DC - - fileRef - E7AAAC5CF03046134533E163 - isa - PBXBuildFile - - 5B35572AABE92AC585EE2CE2 - - buildActionMask - 2147483647 - files - - 2A0A0DD82ACADA1A15078A75 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 5BA5B6F01AEBE7FCBA5D1A5F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapCollectionKey.m - path - YapDatabase/Utilities/YapCollectionKey.m - sourceTree - <group> - - 5C7928C562CC241ECF958B52 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-PromiseKit.a - sourceTree - BUILT_PRODUCTS_DIR - - 5C841B874C97CD7073E9E0EC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipEdge.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h - sourceTree - <group> - - 5D171B9A326B7170186B556B - - baseConfigurationReference - D04434DD0E4D7452AEEFD3D2 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-libextobjc/Pods-libextobjc-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 5D4C9582549D16B738D58BDD - - fileRef - 354E0846412CEF0AD4E30091 - isa - PBXBuildFile - - 5D7481FB0678E06F7B9DD0BF - - fileRef - C113191CF8DA0D427360EF7E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 5DA8F53587BDA5D41977D980 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-YapDatabase-prefix.pch - sourceTree - <group> - - 5E2F3B23634215065298448F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewMappings.h - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h - sourceTree - <group> - - 5E3D4E9C4767941218D65C98 - - fileRef - 7C0E1DAA278CAF4CEB13ED80 - isa - PBXBuildFile - - 5EC72243060BD371DAA8D819 - - fileRef - F374224ACFF5AF242D15DEE2 - isa - PBXBuildFile - - 5EE55C5C761C7A0D95109C58 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFilteredViewTypes.h - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h - sourceTree - <group> - - 5F160243B37AEEA900ADB3AE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTConcreteProtocol.m - path - extobjc/EXTConcreteProtocol.m - sourceTree - <group> - - 5F221F2201A6CF41C8FCF89B - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 5F34F5B9F65E04C0A3C258DE - - fileRef - 96B496B9BA6DEDCC0CF4FEB5 - isa - PBXBuildFile - - 5F82C55CAF05CB38608F9CA3 - - fileRef - C512CB35DECD2AF094B06608 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 5FA053A75B7E6228374F7C41 - - fileRef - 5EE55C5C761C7A0D95109C58 - isa - PBXBuildFile - - 5FEDC40A191F9F6F2C661E44 - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 6009CAFC581F8D11D6407B63 - - fileRef - 6793C55A7342798A007B7BE6 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 6028C9A4C4F454EA341C09EE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PMKPromise+Until.m - path - objc/PMKPromise+Until.m - sourceTree - <group> - - 60627821084163E440BA1EBE - - fileRef - 2A0931B9CBA71CAFE21F8382 - isa - PBXBuildFile - - 6064C9992B037CD5DDBE2E0D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-OHHTTPStubs-Private.xcconfig - sourceTree - <group> - - 6090A7DBDD38835B7972BF6D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - path - Pods-acknowledgements.markdown - sourceTree - <group> - - 60DC861BD52C14581D8E303A - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 8D55202778D4D2D16D149057 - remoteInfo - Pods-PromiseKit - - 611C30C092B9666EE6A0C788 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipPrivate.h - path - YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h - sourceTree - <group> - - 613EC9CAD21B8AB594DEFC5F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-libextobjc-prefix.pch - path - ../Pods-libextobjc/Pods-libextobjc-prefix.pch - sourceTree - <group> - - 6180F3A8B56688E31FA05138 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PMKPromise+When.m - path - objc/PMKPromise+When.m - sourceTree - <group> - - 61C3ACAF90F37EC3EAD03F4F - - fileRef - A1A500530821BC19FFD71BF2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 61C3FDDAB0B0A4E7CA4E106C - - buildActionMask - 2147483647 - files - - 988EC031282D71BD495516F5 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 620903ACB6C56FA958F0D475 - - fileRef - C1446E03977584F292E382D2 - isa - PBXBuildFile - - 6253A5BAB33E2973DF226DC3 - - fileRef - 44CEB83E1D29D338646183FA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 6269EBE92133A139AE5719D4 - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - 6339D26E247F363AABF23B50 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSError+MTLModelException.h - path - Mantle/NSError+MTLModelException.h - sourceTree - <group> - - 63F931C7AE1CD6A7BBD1FBAD - - isa - PBXTargetDependency - target - 38C4AFA484E8999903545200 - targetProxy - 597AEB5FE901D518D08E176E - - 64015EC9C536E16CC7165B31 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 641893280780C96904C92D8E - - fileRef - BE22EAA169B8B803CAD3EC55 - isa - PBXBuildFile - - 64A643B016A920DC52DC4C2F - - isa - PBXTargetDependency - target - B6741702AE4E022F6A4078C2 - targetProxy - 516FFB7AF0EF7083290567C5 - - 64B8F0ABC56325CB2F2219A3 - - fileRef - 25CE9737B115528D9F9D83C9 - isa - PBXBuildFile - - 653F594C56A55E81B7FB9092 - - fileRef - 7546557388C901CF79E23BF1 - isa - PBXBuildFile - - 65452084924ABCBD89B3BB11 - - buildActionMask - 2147483647 - files - - 0C6C3F9E7BA954283A5C10E9 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 65C18D1263F393C601E3C50A - - fileRef - CDD7A7066B13434D8FA030CE - isa - PBXBuildFile - - 65D46D14A30F8F82762FBDC6 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - A5C7FDB89949F4F113730ADF - remoteInfo - Pods-BlogTests-Mantle - - 6607FCD887172A37860230BA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - OHHTTPStubsResponse+HTTPMessage.h - path - OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h - sourceTree - <group> - - 671B606AA04BECD54EDADD20 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 6732078F190FE3A6541908B5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTScope.m - path - extobjc/EXTScope.m - sourceTree - <group> - - 6793C55A7342798A007B7BE6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - OMGFormURLEncode.m - sourceTree - <group> - - 681E4941AF9E021F344185A2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-YapDatabase-dummy.m - sourceTree - <group> - - 6831A48FA46B88E918F641FE - - buildConfigurationList - 8753C521EF78FDF274E1CCF8 - buildPhases - - 1F1C7875CD243FCAF97214DA - 5B35572AABE92AC585EE2CE2 - E7D7FB096B137887FAD12FA8 - - buildRules - - dependencies - - 3D2D47E887770E30631EA286 - - isa - PBXNativeTarget - name - Pods-BlogTests-YapDatabase - productName - Pods-BlogTests-YapDatabase - productReference - 9C3ED594E2C2DB7060B9F8B1 - productType - com.apple.product-type.library.static - - 6846F8AEF440C58E171E9CD1 - - fileRef - C5E267FDD9E85E58C36D7876 - isa - PBXBuildFile - - 687778BA01286AD991757704 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-libextobjc.xcconfig - sourceTree - <group> - - 68FD3DD3DE00649A6F854708 - - fileRef - A1A500530821BC19FFD71BF2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 68FDFCCDE4BECFD66CB5581C - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - CFNetwork.framework - path - Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/CFNetwork.framework - sourceTree - DEVELOPER_DIR - - 6908B4FF840722B6ED1AEDAC - - isa - PBXTargetDependency - target - 4B474CABC48D73A142E712D3 - targetProxy - ED9B9113E2FD3276D07AF2F7 - - 693AE3FEFC8C5C0C2C4811C7 - - fileRef - 154F39422960C9437CCBC9B7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 695ABFE78B38236E7C01FC7D - - buildActionMask - 2147483647 - files - - 3BA6018DD772EA2374EFEFDB - 3263798E68084DBDC26C4B05 - 98DE99E69C34E00BA3EF5A74 - 5AADEA1F2899529E15064940 - 56512318CDB690F3C59EB754 - 37CA1596F8B37A20C61D0417 - AA67DBF6AE394E2E9DDF82B7 - A67B35DFB9E94C7256CE7C24 - CEEE09C293C589BB15784702 - 99261ACC17A96B9BAAF917CE - B1592B8C6AE3DE21DE1B41C0 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 695EAE7E4AD280D1CAEB77AF - - buildActionMask - 2147483647 - files - - 139CC4A2FEEBE5DB92E89CD1 - CE474BCEF0BF770CEB935B0E - C7BA8A7172D99199821BBAF1 - D3C220DC7B6F85F26C116C1C - 9E71B9B9EA1A2BB000B5AE82 - 901E551ABE25FA722A0D8359 - D08DBB25003E9108E490B3CD - 9DA1A72405E5046F9536E89D - 8EE09702608D2991BAB2F315 - 41116C01E47A42EEBDC6895C - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 6964785BA1259C10EB24CD57 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDMultiFormatter.h - path - Lumberjack/Extensions/DDMultiFormatter.h - sourceTree - <group> - - 698E1F13B0057DFF762A59B1 - - fileRef - 4763506A491EFCCF16E29DD3 - isa - PBXBuildFile - - 6A34E058B19AC6BC6E2C3A75 - - fileRef - 9F3504F83A04B43CBDAC7AAD - isa - PBXBuildFile - - 6A4B4CAC9182CAC89A93D9B6 - - fileRef - F2AC98A4DF465FBE6C7B1B28 - isa - PBXBuildFile - - 6A6FAF1BAD4169AB70B6C6C4 - - fileRef - FC0366356620DF9861F43225 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 6AF4180D842303EE9893FBBE - - fileRef - 2218A227904125628444950E - isa - PBXBuildFile - - 6BF8D3DA96A53B9FF39B3E8F - - children - - DE0E0E0F02BD4BC7A4393BAD - 4368E21FD1F0A9DCC27EADBE - 16023EC41B5908B6050C1E2A - 8B0673C65359BD0FF2D9C6CA - DB65AF84447377AF627E15B9 - 95F6567C7B6C184546B40F39 - 9113B3D208D259AF36D23E37 - 863FB5A85BB3959140E1C35C - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-OMGHTTPURLRQ - sourceTree - <group> - - 6C0509647707EF0A91DD2713 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods.debug.xcconfig - sourceTree - <group> - - 6C95826FAFE52067611C3AB2 - - fileRef - CF16E11D068D3825818CD19C - isa - PBXBuildFile - - 6CC186CA605402EEB58AE7F1 - - fileRef - 867752A3C7B2670ACBDF32DE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 6D2A243653758240F9ECE969 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDFileLogger.m - path - Lumberjack/DDFileLogger.m - sourceTree - <group> - - 6D924154EE1542A5264E7568 - - fileRef - 2218A227904125628444950E - isa - PBXBuildFile - - 6DB1B8271DC40A44A2EA73E4 - - fileRef - 41CAD9A74D3A66E4D4E78444 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 6DB2BFB41023617CC8196AAF - - baseConfigurationReference - B01FA4EC7388A3CFBB3F639F - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 6E30A649D0ED2E40F3148DBE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - OMGHTTPURLRQ.m - sourceTree - <group> - - 6F4E4A12F7B70B61DBF2503B - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - CB3C845CD2284348BA439199 - remoteInfo - Pods-CocoaLumberjack - - 6F607CEB17F04D85751C6E60 - - fileRef - 6028C9A4C4F454EA341C09EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 6F6B2C937D13887B500EBFB2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-PromiseKit-dummy.m - path - ../Pods-PromiseKit/Pods-PromiseKit-dummy.m - sourceTree - <group> - - 6FB185CC357C8497E602C138 - - fileRef - 18D52AE807BCFEF5991E1D52 - isa - PBXBuildFile - - 6FBCDD252928F404E3196B62 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseExtensionConnection.h - path - YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h - sourceTree - <group> - - 6FBDCD7F6DEBB95DF41D9B10 - - children - - B0E7EA1627E40379E605D413 - DFCE3E0CD8464A45CF86BE31 - 547FECE7A3BD7B14D730F49E - 861BE1E8ACA8F5793D6CB4E0 - 6964785BA1259C10EB24CD57 - 43CA323806A6948788759144 - - isa - PBXGroup - name - Extensions - sourceTree - <group> - - 703F42AC30F552983C9375A6 - - fileRef - D67B8B4615343EA915F59B63 - isa - PBXBuildFile - - 7068E31E7E607DC5EAC6013C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseOptions.m - path - YapDatabase/YapDatabaseOptions.m - sourceTree - <group> - - 7075264C7A078B3E1679391C - - fileRef - 2916F4DE7130F1A90158970C - isa - PBXBuildFile - - 707CD685B66FA1569F7FFEE3 - - fileRef - 8D55FA7D2E10B4E5BDBCBC7D - isa - PBXBuildFile - - 7094E96F28DE8358507193D0 - - baseConfigurationReference - C6C84C593E998BBE858E331B - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 70B0451AC76A668F9473988B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLReflection.h - path - Mantle/MTLReflection.h - sourceTree - <group> - - 710F9EE2A1DAA415EC8B73A1 - - fileRef - 83FEB76F6002C9CDDF1EC006 - isa - PBXBuildFile - - 71A318F233310166E54A5AC6 - - fileRef - 3DD8402C7BA55BFF09B4632F - isa - PBXBuildFile - - 7239454B418BD457145B6C25 - - buildConfigurations - - C5119503BCC8C40A84D41F6B - 1828359B46EB3D089BA4D625 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 72A3EE0636B60EB81734DC4A - - fileRef - E9BA319F7625FE787FF04357 - isa - PBXBuildFile - - 73420BB7DEB31ACBFA43E030 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFullTextSearchSnippetOptions.h - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h - sourceTree - <group> - - 7350E5020B318A47825510F1 - - fileRef - 142261C9D5E03ED9066F9757 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 736AA0D96F78E49B849C0F78 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 73CA4FB00E4CE235A8AF3C28 - - fileRef - 4BC566EA61666FAC176E66D9 - isa - PBXBuildFile - - 73DAFF00036F4792002AB223 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipTransaction.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h - sourceTree - <group> - - 73EA636BE31415DCB2D761B2 - - fileRef - CDFF8E8307D4F378212C6A5B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 74F67760F189409288A5B76A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDASLLogCapture.m - path - Lumberjack/DDASLLogCapture.m - sourceTree - <group> - - 7501B6E05F277908F49B1A2C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - OMGFormURLEncode.h - sourceTree - <group> - - 753714B52EE5427BBBB2D37F - - fileRef - 6028C9A4C4F454EA341C09EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 7546557388C901CF79E23BF1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTKeyPathCoding.h - path - Mantle/extobjc/EXTKeyPathCoding.h - sourceTree - <group> - - 75755FADD6F23C1F7D6B2407 - - fileRef - A11CAC5E5E88C2454F959D60 - isa - PBXBuildFile - - 75F02582F35DDF6C5AD819DA - - fileRef - DE96E0E294B8B2855408137C - isa - PBXBuildFile - - 768FC5585CA0FC914DF6650C - - baseConfigurationReference - 0434CCF4135312096BB4BC99 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 76BDA76C965B116AE30AF8C7 - - children - - E39CC4AE9B4D7DB598B0D6B3 - E51A0CF3C9459AAB05EEB297 - A73624C41FDEB50383A5CEB4 - A94C7718E3FA1AA861E101BB - 7B93E24211B849E7D777BB70 - 076A6AC2BA9C31B408AEEB35 - FDAD26F8537873C4EBE10B86 - B247123E198CE745EC4AA65A - 9F022C004ED472AD11E8E4B0 - 0A844C8CCC1499E2AF895CB9 - 081102761BC1E0B03EF8BD0C - - isa - PBXGroup - name - PromiseKit - path - PromiseKit - sourceTree - <group> - - 76D179A9618236CAB6A3079A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewPageMetadata.m - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m - sourceTree - <group> - - 77377418499DFD94DDEF729F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDTTYLogger.m - path - Lumberjack/DDTTYLogger.m - sourceTree - <group> - - 7747A9662618843CAF380D5D - - fileRef - 4B2BFBB3BAF1D7D390C7C64A - isa - PBXBuildFile - - 77EF1FF1F96D038A00C272A0 - - fileRef - 1CD23595C52FE4BBC8452188 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 77F380DB3BF15D255DA49392 - - fileRef - 4763506A491EFCCF16E29DD3 - isa - PBXBuildFile - - 77F9E66E36DD6F4A2B22087F - - fileRef - DE4463B89BD90C96A117E02D - isa - PBXBuildFile - - 7831B1B4A66083F2F576334E - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - UIKit.framework - path - Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/UIKit.framework - sourceTree - DEVELOPER_DIR - - 7834620FC228C687526C0882 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseConnectionDefaults.m - path - YapDatabase/Internal/YapDatabaseConnectionDefaults.m - sourceTree - <group> - - 786805C8B7F1B00080A91337 - - isa - PBXFileReference - lastKnownFileType - wrapper.framework - name - Foundation.framework - path - Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Foundation.framework - sourceTree - DEVELOPER_DIR - - 78928D183EC6FFF2F458444E - - fileRef - 5BA5B6F01AEBE7FCBA5D1A5F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 78EA958FC1EDE2C0C73753AA - - fileRef - 510C9911703F11FB4D0090DF - isa - PBXBuildFile - - 78FA48202A994D971298A670 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTRuntimeExtensions.h - path - Mantle/extobjc/EXTRuntimeExtensions.h - sourceTree - <group> - - 7902B18040F651A41A6DE453 - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - NO - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - COPY_PHASE_STRIP - YES - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_DYNAMIC_NO_PIC - NO - 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 - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - ONLY_ACTIVE_ARCH - YES - STRIP_INSTALLED_PRODUCT - NO - - isa - XCBuildConfiguration - name - Debug - - 7902C99FF56CB7013E1E0893 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-CocoaLumberjack.a - sourceTree - BUILT_PRODUCTS_DIR - - 79303D9AD61100BC3C54B3E8 - - children - - BE123C9C9D19C7C4E86FA126 - 8B9548ECA3F342A1E5B13FA8 - - isa - PBXGroup - name - EXTNil - sourceTree - <group> - - 793F7860C7DB182A67093ADA - - fileRef - 9ED8B6288E2CF5F95D626F53 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 79AE24DD32AD0A77E53AD976 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapRowidSet.h - path - YapDatabase/Internal/YapRowidSet.h - sourceTree - <group> - - 79BD2941A83A52734F4C8DDF - - fileRef - 0E149F643670201E753CB1E2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 7A063F7858F89CF341784E7B - - isa - PBXTargetDependency - target - C7CB59FD96B0D84FE5F98540 - targetProxy - 866E717CE1584D5D19957D9A - - 7A13D3F5DFFDFDF122432AE4 - - baseConfigurationReference - 9E4F674C887BDB6A5261AB57 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 7A29076BA7C76328C53B4329 - - fileRef - 366561ED25A6F8A70756ED1A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 7A52CC8626648093CEF7AE4A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseStatement.h - path - YapDatabase/Internal/YapDatabaseStatement.h - sourceTree - <group> - - 7A5AC30E079774B19A2F2280 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTKeyPathCoding.h - path - extobjc/EXTKeyPathCoding.h - sourceTree - <group> - - 7A9A5B6340BEBDD388AACB2E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSInvocation+EXT.h - path - extobjc/NSInvocation+EXT.h - sourceTree - <group> - - 7B4FA73DC6373158457CAC62 - - isa - PBXTargetDependency - target - 6831A48FA46B88E918F641FE - targetProxy - 0F5C7918D5A8760DA8F7C6A6 - - 7B7B70013FEDAAEDADCF00B5 - - fileRef - 7A5AC30E079774B19A2F2280 - isa - PBXBuildFile - - 7B93E24211B849E7D777BB70 - - children - - 1AA085110AD15069B5E90BD1 - BB6C9EA334CA2A15FDF86E2E - 27ADC5EDB57744914308E786 - 058F5C316149DCE85212C22D - 96D29C0E0E225F5707F96C89 - 9BDBADA6AC31F46AE620270E - 6F6B2C937D13887B500EBFB2 - F6824343229661CDBBDA3877 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-PromiseKit - sourceTree - <group> - - 7BDEC11412D59D2DB449B754 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewConnection.m - path - YapDatabase/Extensions/Views/YapDatabaseViewConnection.m - sourceTree - <group> - - 7C0E1DAA278CAF4CEB13ED80 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLModel.h - path - Mantle/MTLModel.h - sourceTree - <group> - - 7C20F1E4EE02A6CFD1478999 - - fileRef - C927CCD7B19D8BE9BD48DA5B - isa - PBXBuildFile - - 7C5D21B39C85F0DBA566CFEA - - fileRef - 7501B6E05F277908F49B1A2C - isa - PBXBuildFile - - 7D757A573C92300B9332CFBD - - fileRef - 3BAB55D8C39CB29C7BD4546D - isa - PBXBuildFile - - 7D759C580C13C0CBACA0849F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapNull.h - path - YapDatabase/Internal/YapNull.h - sourceTree - <group> - - 7DB9B85ED5E03DFD1CEDD41E - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests.a - sourceTree - BUILT_PRODUCTS_DIR - - 7E5D02DE1056A3198256BED5 - - fileRef - 9AA3B3F7CEFE467EF8D4CE3C - isa - PBXBuildFile - - 7E628556C9D4AF0D8A7BA197 - - buildConfigurationList - 08063562731D3281924ED5B4 - buildPhases - - A570EC12F9E13C1C230D8EB0 - FF26035F0910419CDDCA55CF - - buildRules - - dependencies - - DF02AD7B823B7B540B2EE3D9 - B7DBDD67F5E104CE08581D95 - 0E0FF58E632DB352EEFC02D8 - B3852267A310BBCF6D8F9291 - 1ADDDEDBB8B879847170B376 - 64A643B016A920DC52DC4C2F - - isa - PBXNativeTarget - name - Pods - productName - Pods - productReference - 069AB01CC15FB623C707497D - productType - com.apple.product-type.library.static - - 7E6B74F301A8CA2159487E2D - - fileRef - F510A47072303B51AA70548A - isa - PBXBuildFile - - 7E6CED80016EDD51589D3B17 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTRuntimeExtensions.h - path - extobjc/EXTRuntimeExtensions.h - sourceTree - <group> - - 7EC1F07D0D591112E9415495 - - fileRef - B5C26AC372BD6258D8197812 - isa - PBXBuildFile - - 7F2F476B65078CECD86A674B - - fileRef - 9ED8B6288E2CF5F95D626F53 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 7F31154F0ADFE51C87138E84 - - children - - 4BC566EA61666FAC176E66D9 - - isa - PBXGroup - name - EXTSynthesize - sourceTree - <group> - - 7F7B8F4F89D04766CA64EC2B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - OHHTTPStubsResponse+JSON.m - path - OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m - sourceTree - <group> - - 7F9CDD6B8EFB999E6AF7B1AD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDLog+LOGV.h - path - Lumberjack/DDLog+LOGV.h - sourceTree - <group> - - 7FD720BB604A8D2532ADC5E1 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-Mantle.a - sourceTree - BUILT_PRODUCTS_DIR - - 7FFC350D592E57C150B8970F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSearchQueue.m - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueue.m - sourceTree - <group> - - 805BC5EC9D02D9B69FB84182 - - buildActionMask - 2147483647 - files - - 8F2367DDFF1EF20E31957FB6 - 05F4BC38378B22DC641DAECE - 4564BFB8DD35CC49BBA83003 - 753714B52EE5427BBBB2D37F - BEEE82B90DD3CF30FC985616 - 97F90BDB2630422AF3626A20 - AC7F41EDC0096CBDBD1E7E3F - 4331ACC94CF1314F64CE5715 - F7BC5FD7CD8DB934A586D4B9 - 19B8ED727E1382FD355BC787 - 990BE95A216CF7E1C5E7D497 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 8077D404E70F1D5D7A516D20 - - fileRef - 250A78C8CD713B4BA457FF80 - isa - PBXBuildFile - - 8099774C919DAB5D56342CB1 - - fileRef - 1B5C84EC70CD51FC7D6A3FEF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 80B47767066F4F95D769274B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-YapDatabase.xcconfig - sourceTree - <group> - - 80CBE700928C6662146EEB60 - - fileRef - AD85D1B60A21BC6069E26213 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8110A3A0A2D8A527B681632D - - fileRef - 27AAE6EFCA6056FFF1F3BF7E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 814F508F4D2D5F2496432305 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 815912D1CE937B8603FBFE87 - - buildActionMask - 2147483647 - files - - D5FF4F0EF64541091A4250BD - 8E145B804353932A7117C3E9 - 19334C35B1BEA24172F483BD - 6F607CEB17F04D85751C6E60 - C45CD764F16DAF464FD6592C - FD338B9F8CF780B08C0757C4 - DA05E0EB819A6C421E7721B7 - 535E8B823A530096896631A2 - B5670A607FEDA0BE553C2851 - DE98787F03FA7B959AB44C04 - 2E4C2458446B7FB289F27881 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 81F2A0C04F4B23CAE5B79213 - - buildActionMask - 2147483647 - files - - F43CBC5611EB4B8400EECC8F - 2042F3861AE68F90291A08C2 - D0A664498A6D67605C996D7C - C9B5DDA318C401856D25FFAF - 224CEAD71C9359F3EAD49489 - 2A644BC373CC5B46E82B4836 - FAC409A9E75704939C58961A - 3C7164025C8086CB0FD1A89C - 92D3B103446AACE45B1F64C4 - 60627821084163E440BA1EBE - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 81FA0CD4E13F0145FC562398 - - baseConfigurationReference - 0434CCF4135312096BB4BC99 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - 81FB29C0A41373CD2BAE212F - - fileRef - A3D56F7C0081101236A1ADFB - isa - PBXBuildFile - - 821C64EEB6C9BEF530223DA0 - - baseConfigurationReference - F7E221B750098B1AFB5FE850 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 8220A024B01E73EBB1EF1579 - - buildActionMask - 2147483647 - files - - AB9EB946EDE35D243AB37DC2 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 82BEA720A09B82DE1A547133 - - fileRef - AED58546469E42129793D2EB - isa - PBXBuildFile - - 82E4062A9BDB9F51065F0F80 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - UIAlertView+PromiseKit.m - path - objc/UIAlertView+PromiseKit.m - sourceTree - <group> - - 82FE4D9FF895D48EA279B3F7 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - C18E92409B2B034FA606C91B - remoteInfo - Pods-OMGHTTPURLRQ - - 83209793414FF0DD29D0822A - - fileRef - F0CB53A38F4A65F13419D7F7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 834CB96786F68598ABDC42B9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseView.h - path - YapDatabase/Extensions/Views/YapDatabaseView.h - sourceTree - <group> - - 83617777ABD1FADFDC9BA18C - - fileRef - 25CE9737B115528D9F9D83C9 - isa - PBXBuildFile - - 838F21450136BE375CFE6031 - - fileRef - 27B274A3A7DA2A8DDB30F536 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 83FEB76F6002C9CDDF1EC006 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexPrivate.h - path - YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h - sourceTree - <group> - - 840C2D4D997AAEAF5E0AD670 - - fileRef - A0A00489F6014D923B83648A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 847484FA8697A6EEA9EDB3CF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDTTYLogger.h - path - Lumberjack/DDTTYLogger.h - sourceTree - <group> - - 85252833972BB6F41B3B6E38 - - fileRef - 142261C9D5E03ED9066F9757 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 856A9BD39CE1E17DA9072E87 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-CocoaLumberjack.xcconfig - path - ../Pods-CocoaLumberjack/Pods-CocoaLumberjack.xcconfig - sourceTree - <group> - - 85A7A35498CDA73E12FAE079 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseTransaction.m - path - YapDatabase/YapDatabaseTransaction.m - sourceTree - <group> - - 860A75C12C8EEE9B1CD01FC2 - - fileRef - 88FE7FFFEAB6DF14572DA07A - isa - PBXBuildFile - - 861BE1E8ACA8F5793D6CB4E0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDDispatchQueueLogFormatter.m - path - Lumberjack/Extensions/DDDispatchQueueLogFormatter.m - sourceTree - <group> - - 86231AC0447491EEDE46A8D3 - - fileRef - DE4463B89BD90C96A117E02D - isa - PBXBuildFile - - 863FB5A85BB3959140E1C35C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-OMGHTTPURLRQ-prefix.pch - path - ../Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-prefix.pch - sourceTree - <group> - - 866E717CE1584D5D19957D9A - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - C7CB59FD96B0D84FE5F98540 - remoteInfo - Pods-BlogTests-PromiseKit - - 867752A3C7B2670ACBDF32DE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLModel+NSCoding.m - path - Mantle/MTLModel+NSCoding.m - sourceTree - <group> - - 86C8CBD60564F016423F170C - - fileRef - FEEE5F726EDC77D9BF046929 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 86D0230FC98D0F981B53C5ED - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDAbstractDatabaseLogger.h - path - Lumberjack/DDAbstractDatabaseLogger.h - sourceTree - <group> - - 86DE1CEEAB43F4F9085EE09B - - children - - 276A303F5FDA27ECB1617D24 - FFD33E76F2A861FF2B548512 - - isa - PBXGroup - name - Targets Support Files - sourceTree - <group> - - 871FEDE668562DCEF3DDB8FA - - baseConfigurationReference - 4368E21FD1F0A9DCC27EADBE - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 8753C521EF78FDF274E1CCF8 - - buildConfigurations - - 81FA0CD4E13F0145FC562398 - 768FC5585CA0FC914DF6650C - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 875B1C7C2FEDB4E8932A6348 - - baseConfigurationReference - 9BDBADA6AC31F46AE620270E - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-PromiseKit/Pods-PromiseKit-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - 87786B738E70FD462DCB1501 - - fileRef - 53545B12E4A487595ED3541A - isa - PBXBuildFile - - 8836C433152B661E7FAE2F87 - - buildActionMask - 2147483647 - files - - 05E9483268EA8F22B82242A4 - 2F2692A93F2126F92E26FB8C - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 8886A778D89621FC7587B7EB - - fileRef - 6E30A649D0ED2E40F3148DBE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 88FE7FFFEAB6DF14572DA07A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewChangePrivate.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h - sourceTree - <group> - - 890600ECF89A0DEE79274A8C - - fileRef - 44051C84E1D6B418B3CD96DA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8924C299BA29A65346C228B3 - - buildActionMask - 2147483647 - files - - 4A1A06F2A5C18C7EFF4C5B0A - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 8933AAD92D28207D86A630ED - - fileRef - E22135502E6F21DDE43963C6 - isa - PBXBuildFile - - 893707A29536883A73DEC89C - - fileRef - B959903CD20DBFADD1872FC8 - isa - PBXBuildFile - - 89D33B31A6191EB6E232507B - - fileRef - 3B3D883DDFB8585D392CA046 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 89D62AD0128848713EF389B9 - - fileRef - 73420BB7DEB31ACBFA43E030 - isa - PBXBuildFile - - 8ADB5CED1DF4687B26BEEEA8 - - fileRef - 154F39422960C9437CCBC9B7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8B0673C65359BD0FF2D9C6CA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-OMGHTTPURLRQ-prefix.pch - sourceTree - <group> - - 8B0978A2E18E93557C563DAB - - fileRef - F48E98A555245C01A80D1139 - isa - PBXBuildFile - - 8B45DE3D58E4B19169D7854D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchResultsViewOptions.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h - sourceTree - <group> - - 8B9548ECA3F342A1E5B13FA8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTNil.m - path - extobjc/EXTNil.m - sourceTree - <group> - - 8BA4248E080E8BCCAEF77A6E - - children - - FA36EFEA598C18B00262C163 - EFDB2A224CB583CB06A1A6BD - - isa - PBXGroup - name - EXTADT - sourceTree - <group> - - 8BDBEB7E3352C3BB23D812CB - - children - - 13EDCCF437738926B3FE4D51 - 8D3CB3A6241A460F43F91ED7 - EF85220ED86C8EF77A59F98C - 981A35969EFD8A8CD96149B1 - 86DE1CEEAB43F4F9085EE09B - - isa - PBXGroup - sourceTree - <group> - - 8C1DA800013C02AFF58D3026 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSearchResultsViewOptions.m - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.m - sourceTree - <group> - - 8C8FC286136416FF8B08094C - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-libextobjc.a - sourceTree - BUILT_PRODUCTS_DIR - - 8CB06E1A5A187106D29EC099 - - buildActionMask - 2147483647 - files - - 671B606AA04BECD54EDADD20 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 8CB496A1D29F4F27BA895341 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSArray+MTLManipulationAdditions.h - path - Mantle/NSArray+MTLManipulationAdditions.h - sourceTree - <group> - - 8CC3D79704CCE254511379A8 - - fileRef - 90A448ECAB2BF9356CD7FFDA - isa - PBXBuildFile - - 8D0E15185E65DE5CD8FB0EC0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLManagedObjectAdapter.h - path - Mantle/MTLManagedObjectAdapter.h - sourceTree - <group> - - 8D23F3922648D498D1C9D9E7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTSafeCategory.h - path - extobjc/EXTSafeCategory.h - sourceTree - <group> - - 8D3CB3A6241A460F43F91ED7 - - children - - 0A073915BA73A7E6CEB5F0A2 - - isa - PBXGroup - name - Frameworks - sourceTree - <group> - - 8D55202778D4D2D16D149057 - - buildConfigurationList - 2FA8AF4D3A0DAB3533455EB2 - buildPhases - - 805BC5EC9D02D9B69FB84182 - D73015BF2976FB6985487314 - 164C2238E28F933A4FA99917 - - buildRules - - dependencies - - 2F381278E3B56A8F25876C6F - - isa - PBXNativeTarget - name - Pods-PromiseKit - productName - Pods-PromiseKit - productReference - B13BA45A6B9BBC80811C7757 - productType - com.apple.product-type.library.static - - 8D55FA7D2E10B4E5BDBCBC7D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseRelationshipOptions.h - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h - sourceTree - <group> - - 8E145B804353932A7117C3E9 - - fileRef - 450E21DD059A05B0C96858F2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8E70F07209CC2D575EC91585 - - fileRef - 522C87EB500EE5B12ACEEE5A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8EE09702608D2991BAB2F315 - - fileRef - 77377418499DFD94DDEF729F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 8F2367DDFF1EF20E31957FB6 - - fileRef - 277AAF4FEF28F245ABAA2A3B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8F4804CC2A6289AF20410ECB - - fileRef - 373C4956C235E248F65354EB - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 8F806688B9B6C89E4EF8EAF0 - - fileRef - E16890EE7DBF711D338DF459 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 900140167D0999AAA31BFA30 - - buildActionMask - 2147483647 - files - - 3A31BB4201E034889A8C6FA6 - 232A0DC2E72551E99BE461D5 - 86C8CBD60564F016423F170C - F6BFBE6487C6B515B2D47C4A - B42594E62CF0D0205BFC4E06 - CE47F6F93CDAB6A65753F5E5 - 3E532AC8C420C790FCD188DA - 379329E7D9832FAF6DA3CCF4 - 57BB40ADF6BD419284934FAA - 6A34E058B19AC6BC6E2C3A75 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - 9019B7655929D5E06FDE57C4 - - fileRef - D0D6A232D5FD929F3BB6072A - isa - PBXBuildFile - - 901E551ABE25FA722A0D8359 - - fileRef - 6D2A243653758240F9ECE969 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 907C5384B14C9F96A7D558D6 - - fileRef - 8D23F3922648D498D1C9D9E7 - isa - PBXBuildFile - - 90A448ECAB2BF9356CD7FFDA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSDictionary+MTLManipulationAdditions.h - path - Mantle/NSDictionary+MTLManipulationAdditions.h - sourceTree - <group> - - 90FC66842201BF01F1272508 - - fileRef - 0795C3F541DAC18BC24984B1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 9113B3D208D259AF36D23E37 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-OMGHTTPURLRQ-dummy.m - path - ../Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-dummy.m - sourceTree - <group> - - 915E56EE38FA9697601D0E1C - - children - - 221A53EC4947C90C2D4362EA - 6064C9992B037CD5DDBE2E0D - CF16E11D068D3825818CD19C - FC4D9E64F3EF821EC3CC9181 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-OHHTTPStubs - sourceTree - <group> - - 9170E1D913BF5BEB10E9BC85 - - fileRef - BCA4D743CE8358E7DCE71484 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 926587A7088B1C71AF12ABED - - buildConfigurationList - 7239454B418BD457145B6C25 - buildPhases - - 06F5F64F7192F1ABA7FB9583 - 61C3FDDAB0B0A4E7CA4E106C - - buildRules - - dependencies - - 63F931C7AE1CD6A7BBD1FBAD - 29B22886BAFF71AE782E669A - ED30D9579189880EC25AEB5E - 6908B4FF840722B6ED1AEDAC - 7A063F7858F89CF341784E7B - 7B4FA73DC6373158457CAC62 - B934CA5D2F11E30226B64457 - - isa - PBXNativeTarget - name - Pods-BlogTests - productName - Pods-BlogTests - productReference - 7DB9B85ED5E03DFD1CEDD41E - productType - com.apple.product-type.library.static - - 926ABD523243BF8158594D8C - - fileRef - 10BA123C353632C6F4FF978E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 92D3B103446AACE45B1F64C4 - - fileRef - EA7C9AED1E39B7DB673D49A1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 9301203F411CB95AA89FAE4B - - fileRef - 88FE7FFFEAB6DF14572DA07A - isa - PBXBuildFile - - 933CEF8D04B13B55EC3A9B7B - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - C18E92409B2B034FA606C91B - remoteInfo - Pods-OMGHTTPURLRQ - - 9374BBBDAD91927A8F67FE1C - - fileRef - 85A7A35498CDA73E12FAE079 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 937AB3B3D9523B93E1292FDC - - fileRef - 2568CFD4A6FAAB51C63F29F4 - isa - PBXBuildFile - - 938962EC2EECB2610DE86053 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewTypes.h - path - YapDatabase/Extensions/Views/YapDatabaseViewTypes.h - sourceTree - <group> - - 938C0D7B2B43A11319F0DA32 - - fileRef - B67A7082DD97F125F8E570C3 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 93F1CD410DA33DB2DF2B3DC9 - - fileRef - 4B2BFBB3BAF1D7D390C7C64A - isa - PBXBuildFile - - 9409BCC2B7B1A09973E00E62 - - fileRef - AE190E4088CE4126A58EB2CC - isa - PBXBuildFile - - 944EDD509871F82E2228A59F - - fileRef - 834CB96786F68598ABDC42B9 - isa - PBXBuildFile - - 948154E79FAF259EEE86708B - - fileRef - 1AA787AD406B814B0D0356D2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 9491B9D069B63235787BFF4C - - fileRef - 7831B1B4A66083F2F576334E - isa - PBXBuildFile - - 94B2ABF1707BC0E90D29B5E4 - - fileRef - 7BDEC11412D59D2DB449B754 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 94FB487503E56593B2B695FB - - fileRef - 1CD23595C52FE4BBC8452188 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 95859E34052D8F028113786A - - fileRef - 1A86FDB5729AEFE96524B17C - isa - PBXBuildFile - - 95A06746E8E22F9210701C20 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - UIActionSheet+PromiseKit.m - path - objc/UIActionSheet+PromiseKit.m - sourceTree - <group> - - 95F6567C7B6C184546B40F39 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-OMGHTTPURLRQ-Private.xcconfig - path - ../Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-Private.xcconfig - sourceTree - <group> - - 96495579CE3C1700DE85CE7E - - fileRef - 41CAD9A74D3A66E4D4E78444 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 96B496B9BA6DEDCC0CF4FEB5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFullTextSearchPrivate.h - path - YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h - sourceTree - <group> - - 96D29C0E0E225F5707F96C89 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-PromiseKit.xcconfig - path - ../Pods-PromiseKit/Pods-PromiseKit.xcconfig - sourceTree - <group> - - 97F90BDB2630422AF3626A20 - - fileRef - 0426F1CA8AD4B65620814DF4 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 981A35969EFD8A8CD96149B1 - - children - - 069AB01CC15FB623C707497D - 7DB9B85ED5E03DFD1CEDD41E - B58A60B3858FD623033B63C1 - 7FD720BB604A8D2532ADC5E1 - DF59954913D98ADEF2981676 - 0ADA1F3E78D7F286AD9EB2CE - 5C7928C562CC241ECF958B52 - 9C3ED594E2C2DB7060B9F8B1 - 2B42F3392D5D4DC4FAE1E784 - 7902C99FF56CB7013E1E0893 - FEFD8FB2EFC0C6BD03805A23 - D03B94A00C83B558319BD434 - B13BA45A6B9BBC80811C7757 - 2F1672B212AA041F47E06565 - 8C8FC286136416FF8B08094C - - isa - PBXGroup - name - Products - sourceTree - <group> - - 9868DC5282E31D45699FF11B - - fileRef - C635B47476AEB1F75B8E4A59 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 988EC031282D71BD495516F5 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - 98DE99E69C34E00BA3EF5A74 - - fileRef - 86D0230FC98D0F981B53C5ED - isa - PBXBuildFile - - 990BE95A216CF7E1C5E7D497 - - fileRef - F8086C3AC09B25ED2B74DF4B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 99261ACC17A96B9BAAF917CE - - fileRef - 6964785BA1259C10EB24CD57 - isa - PBXBuildFile - - 99357F9E64220BC943EE8D09 - - fileRef - D9FBB555089342AAFF18FD1E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 9A7B22C758072DB3D063195E - - fileRef - 7A52CC8626648093CEF7AE4A - isa - PBXBuildFile - - 9AA3B3F7CEFE467EF8D4CE3C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexSetup.h - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h - sourceTree - <group> - - 9B0483DD5B5BBDECDD4D2AF5 - - children - - 02DBE9C9DF1E0B0EEBA0646A - 74F67760F189409288A5B76A - A32C636BF537187FE0C16EE5 - 08F2C7B599103FC0BCF1D7BB - 86D0230FC98D0F981B53C5ED - FEEE5F726EDC77D9BF046929 - CEB8B561F98987335D130E56 - 592F7BD907EDDFC3A0B0502F - 6D2A243653758240F9ECE969 - 3BAB55D8C39CB29C7BD4546D - 4E059837F347B34276C71290 - 7F9CDD6B8EFB999E6AF7B1AD - 847484FA8697A6EEA9EDB3CF - 77377418499DFD94DDEF729F - - isa - PBXGroup - name - Core - sourceTree - <group> - - 9BAE8517935E4652DA18C03F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFilteredView.h - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h - sourceTree - <group> - - 9BDBADA6AC31F46AE620270E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-PromiseKit-Private.xcconfig - path - ../Pods-PromiseKit/Pods-PromiseKit-Private.xcconfig - sourceTree - <group> - - 9C0361391A58A4191337F8B8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests.debug.xcconfig - sourceTree - <group> - - 9C363A2CCDB295751EB81EC9 - - fileRef - B63E1A4B3FC3022C9D696DAD - isa - PBXBuildFile - - 9C3ED594E2C2DB7060B9F8B1 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-YapDatabase.a - sourceTree - BUILT_PRODUCTS_DIR - - 9C7D485F506CEDBF73A533CA - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSValueTransformer+MTLInversionAdditions.m - path - Mantle/NSValueTransformer+MTLInversionAdditions.m - sourceTree - <group> - - 9CE4EC9165C231CFC4DC9316 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewOptions.m - path - YapDatabase/Extensions/Views/YapDatabaseViewOptions.m - sourceTree - <group> - - 9CF17BE81AC5CB87305562B4 - - fileRef - F31E1FF6F19E0F532DC7509A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 9CFDB2F70E46B4FB4BD50F1B - - fileRef - 7BDEC11412D59D2DB449B754 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 9D150DD9458627602248BD44 - - fileRef - 3D9A9AC30E8560E53C84C05B - isa - PBXBuildFile - - 9D55D25EF97E2865313A8CF8 - - fileRef - 9CE4EC9165C231CFC4DC9316 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 9D72CF34BB4423E525063C2E - - fileRef - CFF4322F158FA5348F260B7E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - 9DA1A72405E5046F9536E89D - - fileRef - 43CA323806A6948788759144 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 9E4F674C887BDB6A5261AB57 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-Mantle-Private.xcconfig - sourceTree - <group> - - 9E71B9B9EA1A2BB000B5AE82 - - fileRef - 861BE1E8ACA8F5793D6CB4E0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - 9ED8B6288E2CF5F95D626F53 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSearchResultsViewConnection.m - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m - sourceTree - <group> - - 9F022C004ED472AD11E8E4B0 - - children - - 4B2BFBB3BAF1D7D390C7C64A - F8086C3AC09B25ED2B74DF4B - - isa - PBXGroup - name - UIViewController - sourceTree - <group> - - 9F3504F83A04B43CBDAC7AAD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-CocoaLumberjack-dummy.m - path - ../Pods-CocoaLumberjack/Pods-CocoaLumberjack-dummy.m - sourceTree - <group> - - 9F3BC7B20238DEFFDD1E4011 - - buildConfigurations - - 2E7A9AB0AA20A443C5A400EA - 2E62776E143058C1EB05E368 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - 9F87EC64930BC0469F2B8B11 - - fileRef - F6C2D3DB1C0774716908D4CE - isa - PBXBuildFile - - 9F9D0C6AD1CED13869444176 - - fileRef - 3618A04504801463F3664011 - isa - PBXBuildFile - - 9FDB52B741B00B969118FB22 - - buildActionMask - 2147483647 - files - - D66A679D958209DC5DE38CEF - B8F2C7FB8961E5F48DBF5945 - 703F42AC30F552983C9375A6 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - A0284E8BDF6518D7E70B32BE - - fileRef - 5C841B874C97CD7073E9E0EC - isa - PBXBuildFile - - A040D223ABC00B888E543E1F - - fileRef - EA7C9AED1E39B7DB673D49A1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - A064109944BFE15E9CC6F683 - - fileRef - B97FDB48E920BEAC567F74F5 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - A0A00489F6014D923B83648A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabase.m - path - YapDatabase/YapDatabase.m - sourceTree - <group> - - A0BBCBEB76635DCFF2AC8D22 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-CocoaLumberjack-prefix.pch - sourceTree - <group> - - A0E8575B3BB05198EA828BB4 - - baseConfigurationReference - BB6C9EA334CA2A15FDF86E2E - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - A11CAC5E5E88C2454F959D60 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewMappingsPrivate.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h - sourceTree - <group> - - A12F29E7A0DC9EF6397B3A68 - - children - - 7A5AC30E079774B19A2F2280 - - isa - PBXGroup - name - EXTKeyPathCoding - sourceTree - <group> - - A183CDE4DF77587D2A3EE2B3 - - fileRef - 2FE793C339D4F2D5FFAA4399 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - A1A500530821BC19FFD71BF2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFullTextSearchConnection.m - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m - sourceTree - <group> - - A1BFAF7557B15449F15BF597 - - fileRef - E65E19BDC940636C60C594A6 - isa - PBXBuildFile - - A28D475229208F2DE7160037 - - buildActionMask - 2147483647 - files - - A2AC6806E1646A7E5D55589D - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - A2A75EA7B19D685458B67F3B - - fileRef - 5700F30AA8FF03072E769739 - isa - PBXBuildFile - - A2AC6806E1646A7E5D55589D - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - A32C636BF537187FE0C16EE5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDASLLogger.h - path - Lumberjack/DDASLLogger.h - sourceTree - <group> - - A39BC41ADC5447539F96A0B0 - - fileRef - 36154702DA969D3E68BAAB63 - isa - PBXBuildFile - - A3A1604BCC9DFADE5148A5AB - - children - - 8BA4248E080E8BCCAEF77A6E - 284ED893EBCECAB692803B2B - A12F29E7A0DC9EF6397B3A68 - 79303D9AD61100BC3C54B3E8 - D9FE47FD270E867DAEAF75AE - B368E6096173C29E2633DCC4 - 26CEC49654D040C607F2926F - 7F31154F0ADFE51C87138E84 - 1C41FF4B3A0E0DB5910CB5D0 - 237CAA329FB0113337568BC8 - DCB32AA665AD6E7EFCB344FA - 030C2CB4A6BAD5A7E0F9B58A - 02F0A0CA7FC130C6EFC430F6 - - isa - PBXGroup - name - libextobjc - path - libextobjc - sourceTree - <group> - - A3A6B41EB3B7DF33C044FBFB - - fileRef - 510C9911703F11FB4D0090DF - isa - PBXBuildFile - - A3D56F7C0081101236A1ADFB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewState.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.h - sourceTree - <group> - - A43DCF13B56E4F1A5B9008BD - - fileRef - 4D563DD93791AE9C0A209D5B - isa - PBXBuildFile - - A4A72EB139270DB5877F98A7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseManager.h - path - YapDatabase/Internal/YapDatabaseManager.h - sourceTree - <group> - - A5658BFED93F7E3925A1A68B - - fileRef - 16023EC41B5908B6050C1E2A - isa - PBXBuildFile - - A570DDCA14F226264040EDBB - - fileRef - 58D904E7D52CDC8603AE0006 - isa - PBXBuildFile - - A570EC12F9E13C1C230D8EB0 - - buildActionMask - 2147483647 - files - - A1BFAF7557B15449F15BF597 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - A5778933D0ED5B3FA744E028 - - fileRef - FDD93D0B6173305BBF61C92C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - A58BD77753929E7ABA84FAC5 - - fileRef - C69BCF8DB07E1BDADBBD4A65 - isa - PBXBuildFile - - A5C7FDB89949F4F113730ADF - - buildConfigurationList - 289ED5A99FC2F21CF7C72567 - buildPhases - - BE1C29D8026ED3B1382BEB16 - E91A19F1AD72577E78E274D5 - F631A7CDC3E62F8A427A0421 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-BlogTests-Mantle - productName - Pods-BlogTests-Mantle - productReference - 7FD720BB604A8D2532ADC5E1 - productType - com.apple.product-type.library.static - - A5EAEB3171E943E4AFF95766 - - fileRef - 681E4941AF9E021F344185A2 - isa - PBXBuildFile - - A5EEA0315206E202B878AA4A - - fileRef - 0FD3969237C6CD2004EBC12F - isa - PBXBuildFile - - A656E90D18D8F78161DC465B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text - path - Pods-BlogTests-acknowledgements.markdown - sourceTree - <group> - - A6773877A672078CBD6D2122 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchQueuePrivate.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueuePrivate.h - sourceTree - <group> - - A67B35DFB9E94C7256CE7C24 - - fileRef - 7F9CDD6B8EFB999E6AF7B1AD - isa - PBXBuildFile - - A6B2BF5293274ED1406F2349 - - fileRef - B0BDAB6707945969960AF8E8 - isa - PBXBuildFile - - A73624C41FDEB50383A5CEB4 - - children - - D802336E1655FB340EBC9409 - C5E267FDD9E85E58C36D7876 - - isa - PBXGroup - name - Pause - sourceTree - <group> - - A75BBDE7086438FB91D81927 - - buildConfigurationList - 0325A3C73A337C97987152F4 - buildPhases - - FFB9F7BDE103B355177B48CD - AC889D88BB9C91A46E488CD4 - 0332EEC146CEFE57854BEA43 - - buildRules - - dependencies - - E688C041405EECEA1A0AC6DB - - isa - PBXNativeTarget - name - Pods-YapDatabase - productName - Pods-YapDatabase - productReference - 2F1672B212AA041F47E06565 - productType - com.apple.product-type.library.static - - A798705A52FA872AB15155F4 - - fileRef - 338924D00EA0CC52E2007C7B - isa - PBXBuildFile - - A918BF1E6FAAEAE3B7D615E9 - - fileRef - 7F9CDD6B8EFB999E6AF7B1AD - isa - PBXBuildFile - - A9335EF19AB0BF9F03670420 - - fileRef - 1AA787AD406B814B0D0356D2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - A94C7718E3FA1AA861E101BB - - children - - 0426F1CA8AD4B65620814DF4 - 354E0846412CEF0AD4E30091 - B5C26AC372BD6258D8197812 - 2218A227904125628444950E - - isa - PBXGroup - name - Promise - sourceTree - <group> - - AA15386C0C7674AFCE654090 - - fileRef - A11CAC5E5E88C2454F959D60 - isa - PBXBuildFile - - AA67DBF6AE394E2E9DDF82B7 - - fileRef - 592F7BD907EDDFC3A0B0502F - isa - PBXBuildFile - - AA782631F71F0C012E5D5995 - - buildConfigurations - - E39A8F67B948EFD4DD086A51 - 2AC872F3FC3B531BC9047A47 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - AB33EF177F2ED007711CB205 - - fileRef - 211A58100BF97F2BC12B0CE9 - isa - PBXBuildFile - - AB38AF8060F4DFFDC853BECC - - fileRef - A4A72EB139270DB5877F98A7 - isa - PBXBuildFile - - AB9EB946EDE35D243AB37DC2 - - fileRef - 786805C8B7F1B00080A91337 - isa - PBXBuildFile - - ABBF95AAD79E181BF788A258 - - fileRef - 23A967C5A37AFDC511BAAFD0 - isa - PBXBuildFile - - ABC3177E0211DEDB7F2B06EF - - fileRef - 0D700C2A0BD0B56B170D7BA0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - ABCD292FC5A3E55C6F18660F - - fileRef - E7AAAC5CF03046134533E163 - isa - PBXBuildFile - - AC7F41EDC0096CBDBD1E7E3F - - fileRef - 6F6B2C937D13887B500EBFB2 - isa - PBXBuildFile - - AC889D88BB9C91A46E488CD4 - - buildActionMask - 2147483647 - files - - 258589569DF12B3B2A8E27F9 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - AD2B1493CDAAF65711488F8D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewPageMetadata.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h - sourceTree - <group> - - AD85D1B60A21BC6069E26213 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewRangeOptions.m - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m - sourceTree - <group> - - ADAD229FA4C0D416D30B82EB - - fileRef - EAA54005DF3802B5546464A2 - isa - PBXBuildFile - - AE190E4088CE4126A58EB2CC - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - UIActionSheet+PromiseKit.h - path - objc/UIActionSheet+PromiseKit.h - sourceTree - <group> - - AEC0355C98BD94BFBE907A46 - - fileRef - 867752A3C7B2670ACBDF32DE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - AED252066CE09B1A9FD4C871 - - fileRef - F6ED69D788774E3D338D2BC9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - AED58546469E42129793D2EB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - metamacros.h - path - extobjc/metamacros.h - sourceTree - <group> - - AF1F99B464C13A834C683878 - - children - - B0065057B7D2BBE33467071C - 4533A270C27A3A6C4CC7A60D - - isa - PBXGroup - name - YapDatabase - path - YapDatabase - sourceTree - <group> - - AF4B16A7F886887E3429B1D4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewPrivate.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h - sourceTree - <group> - - AFBC4A8822EA4B93ADE8C43B - - fileRef - D4D6570710557532B7432896 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - B0065057B7D2BBE33467071C - - children - - 80B47767066F4F95D769274B - 0434CCF4135312096BB4BC99 - 681E4941AF9E021F344185A2 - 5DA8F53587BDA5D41977D980 - 0D712F3434D4B4C47CB4B500 - DE16E0B43555E1276393B2CB - 38181B270180D765C5AFDDE9 - 4A2DAB25F31AC9E43FA6314E - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-YapDatabase - sourceTree - <group> - - B01FA4EC7388A3CFBB3F639F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods.release.xcconfig - sourceTree - <group> - - B02EDE68D12C8E7B4F857A94 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Promise+When.h - path - objc/PromiseKit/Promise+When.h - sourceTree - <group> - - B0A02669C19682986FDDB459 - - fileRef - D99791BAD09133E58E937091 - isa - PBXBuildFile - - B0BDAB6707945969960AF8E8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseConnectionState.h - path - YapDatabase/Internal/YapDatabaseConnectionState.h - sourceTree - <group> - - B0E7EA1627E40379E605D413 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDContextFilterLogFormatter.h - path - Lumberjack/Extensions/DDContextFilterLogFormatter.h - sourceTree - <group> - - B13BA45A6B9BBC80811C7757 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-PromiseKit.a - sourceTree - BUILT_PRODUCTS_DIR - - B1592B8C6AE3DE21DE1B41C0 - - fileRef - 847484FA8697A6EEA9EDB3CF - isa - PBXBuildFile - - B247123E198CE745EC4AA65A - - children - - BE22EAA169B8B803CAD3EC55 - 4DB22EF0176AD3E9EE1AFCC1 - - isa - PBXGroup - name - UIView - sourceTree - <group> - - B27D872D869BE292A4939472 - - fileRef - BE123C9C9D19C7C4E86FA126 - isa - PBXBuildFile - - B34BA05D0222D59875EC5A7F - - buildActionMask - 2147483647 - files - - 1AC1CF0849D48151E1E69C28 - A5EEA0315206E202B878AA4A - 2FE0F3F24F4E8BB06C84608C - F15B5FCF47884A96045896B7 - 1794C0E2E76FE4BFE1A0CABE - 907C5384B14C9F96A7D558D6 - 8077D404E70F1D5D7A516D20 - 1DBA3D953891E8CDC57D37EB - EFEB5CDA6D801588C9EB4CD8 - CFA7DDF69CD4AD2B74331D93 - E9E83C1F5E89CAEF3631B6C8 - 412353141474E421CEA26A7F - 82BEA720A09B82DE1A547133 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - B368E6096173C29E2633DCC4 - - children - - 250A78C8CD713B4BA457FF80 - 6732078F190FE3A6541908B5 - - isa - PBXGroup - name - EXTScope - sourceTree - <group> - - B3852267A310BBCF6D8F9291 - - isa - PBXTargetDependency - target - 8D55202778D4D2D16D149057 - targetProxy - 60DC861BD52C14581D8E303A - - B42594E62CF0D0205BFC4E06 - - fileRef - 861BE1E8ACA8F5793D6CB4E0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - B4D2174DD2F308B87C6886A3 - - fileRef - 062F7ED90F24410039196758 - isa - PBXBuildFile - - B52A16813A4A1CE2F582CA7A - - includeInIndex - 1 - isa - PBXFileReference - name - YapDatabaseViewPage.mm - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm - sourceTree - <group> - - B5670A607FEDA0BE553C2851 - - fileRef - 82E4062A9BDB9F51065F0F80 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - B58A60B3858FD623033B63C1 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-CocoaLumberjack.a - sourceTree - BUILT_PRODUCTS_DIR - - B5B68C91352F233507EDC6A7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-Mantle-prefix.pch - path - ../Pods-Mantle/Pods-Mantle-prefix.pch - sourceTree - <group> - - B5C26AC372BD6258D8197812 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PromiseKit.h - path - objc/PromiseKit.h - sourceTree - <group> - - B5D7C2BEB6C0412F9D0488FA - - fileRef - 298541E54701F5D2D54F84CB - isa - PBXBuildFile - - B63E1A4B3FC3022C9D696DAD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSValueTransformer+MTLInversionAdditions.h - path - Mantle/NSValueTransformer+MTLInversionAdditions.h - sourceTree - <group> - - B6741702AE4E022F6A4078C2 - - buildConfigurationList - FB1116CF3534A90969E20BD5 - buildPhases - - EEED8A19153177323E851F33 - 8CB06E1A5A187106D29EC099 - B34BA05D0222D59875EC5A7F - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-libextobjc - productName - Pods-libextobjc - productReference - 8C8FC286136416FF8B08094C - productType - com.apple.product-type.library.static - - B67A7082DD97F125F8E570C3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseConnection.m - path - YapDatabase/YapDatabaseConnection.m - sourceTree - <group> - - B6A247EF445935E36BDC2A3F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - OHHTTPStubs.h - path - OHHTTPStubs/Sources/OHHTTPStubs.h - sourceTree - <group> - - B7544ECE4CD45786C4729F1B - - fileRef - F0CB53A38F4A65F13419D7F7 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - B781161C41E34196282E4097 - - fileRef - 2916F4DE7130F1A90158970C - isa - PBXBuildFile - - B7D0E52354B65AC88EABAA32 - - fileRef - F6ED69D788774E3D338D2BC9 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - B7DBDD67F5E104CE08581D95 - - isa - PBXTargetDependency - target - CA890C10A80DEDD1E26EE1DA - targetProxy - 1434EAF36CB80F84ED9D98CB - - B8A98F7EBA444817481514EE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapSet.m - path - YapDatabase/Utilities/YapSet.m - sourceTree - <group> - - B8D4B978EE1B11904FD3F61F - - fileRef - 6964785BA1259C10EB24CD57 - isa - PBXBuildFile - - B8F2C7FB8961E5F48DBF5945 - - fileRef - E938B4E9BD4AEA348A41C73B - isa - PBXBuildFile - - B934CA5D2F11E30226B64457 - - isa - PBXTargetDependency - target - 42F4D37A0CEF471792804AC3 - targetProxy - FF67271E3AC8AC0E3BD9011A - - B959903CD20DBFADD1872FC8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSDictionary+YapDatabase.h - path - YapDatabase/Internal/NSDictionary+YapDatabase.h - sourceTree - <group> - - B97FDB48E920BEAC567F74F5 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - OHHTTPStubsResponse.m - path - OHHTTPStubs/Sources/OHHTTPStubsResponse.m - sourceTree - <group> - - B999EF649B40AF9EE6B3436C - - buildActionMask - 2147483647 - files - - 736AA0D96F78E49B849C0F78 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - B9E284862E5B161637C31E2F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchResultsViewConnection.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.h - sourceTree - <group> - - BA12C07BF7E1A9D36387BB74 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-environment.h - sourceTree - <group> - - BAB779202635DD0BF3382B4F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSDictionary+MTLManipulationAdditions.m - path - Mantle/NSDictionary+MTLManipulationAdditions.m - sourceTree - <group> - - BAD11F8A0C6D34221236FC5F - - fileRef - 526514FC801A87957576E3CD - isa - PBXBuildFile - - BAD8B2814A3FB6D5EFC732EE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSecondaryIndexConnection.m - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m - sourceTree - <group> - - BB6C9EA334CA2A15FDF86E2E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-PromiseKit-Private.xcconfig - sourceTree - <group> - - BBD6CE7E3C56F3A05CD0E0E0 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-Mantle.xcconfig - sourceTree - <group> - - BCA4D743CE8358E7DCE71484 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewTransaction.m - path - YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m - sourceTree - <group> - - BCFFA8F7134C59821A06632E - - fileRef - B5C26AC372BD6258D8197812 - isa - PBXBuildFile - - BD5BA1C3E746D35FA8A78228 - - fileRef - 2CA126641BD6222948B53DF5 - isa - PBXBuildFile - - BE123C9C9D19C7C4E86FA126 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTNil.h - path - extobjc/EXTNil.h - sourceTree - <group> - - BE1C29D8026ED3B1382BEB16 - - buildActionMask - 2147483647 - files - - C3608C022B3E6467997D742C - 361F5B3321DDFB93D97D5886 - 40CDE38ACDC59C7C8BE0C99B - 525F3EBAC3828750176EA9B5 - AEC0355C98BD94BFBE907A46 - 8F806688B9B6C89E4EF8EAF0 - 38428240938B9F343493DCA0 - CBAAF0073DF6ED5430D1AE54 - AED252066CE09B1A9FD4C871 - 06FBBD6B7A406D3986E38436 - 516776F29F82903BC216725F - AFBC4A8822EA4B93ADE8C43B - E99A36B1CC892747CEEB2D34 - E026B419422DA6C2BEFCB031 - D13FBAB7601B511A88AC0EF5 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - BE22EAA169B8B803CAD3EC55 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - UIView+PromiseKit.h - path - objc/UIView+PromiseKit.h - sourceTree - <group> - - BE3F2CF21847E6E8FBE7AAC8 - - baseConfigurationReference - F5A8223B1C33B1AB9E498E85 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - BEEE82B90DD3CF30FC985616 - - fileRef - 6180F3A8B56688E31FA05138 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - BF7BFAA783101D1987EEFD2B - - fileRef - 70B0451AC76A668F9473988B - isa - PBXBuildFile - - BFDB8B8FA6F05B3ED13CF6E7 - - fileRef - C9CDABBFA46667358027FC6A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C014312069CA82C2BF85484F - - fileRef - 6FBCDD252928F404E3196B62 - isa - PBXBuildFile - - C031756E8371D8EF0232CC22 - - buildActionMask - 2147483647 - files - - 05A2E1512618C9EE16B4813C - 46B5E383E5459D1F9A59E391 - 7B7B70013FEDAAEDADCF00B5 - B27D872D869BE292A4939472 - 32A72324F4A6C84ABB17E2C0 - FFDB6BB64625972F477FE7D4 - CE4664104E4E693B8A7148A0 - 540EFADE59DEA99C26D030B8 - 73CA4FB00E4CE235A8AF3C28 - CB25D1B3BC11FDF66237B0D3 - 5190A5E03231E9612A665B2F - 5EC72243060BD371DAA8D819 - FB1B51B109FA18EE59BC666E - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - C0685FC8629461A9EB558777 - - fileRef - 7FFC350D592E57C150B8970F - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C108B20E9CF45386E2C0F3B2 - - fileRef - 2A3A8198CEF6A7DA0D0C8DDA - isa - PBXBuildFile - - C113191CF8DA0D427360EF7E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - OHHTTPStubsResponse+HTTPMessage.m - path - OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m - sourceTree - <group> - - C1446E03977584F292E382D2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabase.h - path - YapDatabase/YapDatabase.h - sourceTree - <group> - - C18E92409B2B034FA606C91B - - buildConfigurationList - D027FF13511254443219CE45 - buildPhases - - 27FBE5EBD233856BBAC028A7 - 1928E70C0C75F0E6345B57E8 - 9FDB52B741B00B969118FB22 - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-OMGHTTPURLRQ - productName - Pods-OMGHTTPURLRQ - productReference - D03B94A00C83B558319BD434 - productType - com.apple.product-type.library.static - - C269A9DA884CE9A70DB9CFF2 - - fileRef - 38181B270180D765C5AFDDE9 - isa - PBXBuildFile - - C2A3CF10E412976A8D9B0C12 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-CocoaLumberjack.xcconfig - sourceTree - <group> - - C3608C022B3E6467997D742C - - fileRef - 4F2E4FAADD6297C85BE36092 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - C42C74218F847931E9ED0F39 - - fileRef - 73420BB7DEB31ACBFA43E030 - isa - PBXBuildFile - - C437D08F0C1627C11731D429 - - fileRef - 4F2E4FAADD6297C85BE36092 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - C4401EC7CB524A464387775B - - fileRef - 78FA48202A994D971298A670 - isa - PBXBuildFile - - C45CD764F16DAF464FD6592C - - fileRef - 6180F3A8B56688E31FA05138 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C4F7FEE942FEF691E3AA2B30 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseOptions.h - path - YapDatabase/YapDatabaseOptions.h - sourceTree - <group> - - C5119503BCC8C40A84D41F6B - - baseConfigurationReference - 9C0361391A58A4191337F8B8 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - C512CB35DECD2AF094B06608 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseConnectionState.m - path - YapDatabase/Internal/YapDatabaseConnectionState.m - sourceTree - <group> - - C54BA3F2BAB971FDD2C0B4D0 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - A75BBDE7086438FB91D81927 - remoteInfo - Pods-YapDatabase - - C59D325C7C07DEE63219CE85 - - fileRef - 76D179A9618236CAB6A3079A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C5C3A8EC782B842563F7D184 - - fileRef - 44051C84E1D6B418B3CD96DA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C5E267FDD9E85E58C36D7876 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Promise+Pause.h - path - objc/PromiseKit/Promise+Pause.h - sourceTree - <group> - - C603E25AFF71674FCC071C5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - OHHTTPStubs.m - path - OHHTTPStubs/Sources/OHHTTPStubs.m - sourceTree - <group> - - C635B47476AEB1F75B8E4A59 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFilteredViewConnection.m - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m - sourceTree - <group> - - C6431B7067E6FC24F64C2AE1 - - fileRef - EAA54005DF3802B5546464A2 - isa - PBXBuildFile - - C69726FB98D1679AB022BA62 - - fileRef - 6339D26E247F363AABF23B50 - isa - PBXBuildFile - - C69BCF8DB07E1BDADBBD4A65 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewRangeOptions.h - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h - sourceTree - <group> - - C6C138FDDC2B6B93C0C1A86B - - baseConfigurationReference - DE16E0B43555E1276393B2CB - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-YapDatabase/Pods-YapDatabase-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - C6C84C593E998BBE858E331B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-libextobjc-Private.xcconfig - sourceTree - <group> - - C6FC1041D0AE734E944134BA - - fileRef - 9113B3D208D259AF36D23E37 - isa - PBXBuildFile - - C6FD6C921CE4D0F425C3FF6E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseRelationship.m - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationship.m - sourceTree - <group> - - C74BBE30744B5DEE6156E083 - - fileRef - 85A7A35498CDA73E12FAE079 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C7BA8A7172D99199821BBAF1 - - fileRef - FEEE5F726EDC77D9BF046929 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - C7CB59FD96B0D84FE5F98540 - - buildConfigurationList - E280F0BA81DEFC4B15970E16 - buildPhases - - 815912D1CE937B8603FBFE87 - D774BD043AADBD9843208EC1 - 2D57BFA181418314DEE35199 - - buildRules - - dependencies - - E58B2643A8A88595955F784D - - isa - PBXNativeTarget - name - Pods-BlogTests-PromiseKit - productName - Pods-BlogTests-PromiseKit - productReference - 5C7928C562CC241ECF958B52 - productType - com.apple.product-type.library.static - - C8A2DC4401EBDAB3C791ECBD - - fileRef - FDD93D0B6173305BBF61C92C - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - C8DB94A0A2F90B36BFA5E7BF - - fileRef - 3D9A9AC30E8560E53C84C05B - isa - PBXBuildFile - - C927CCD7B19D8BE9BD48DA5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapTouch.h - path - YapDatabase/Internal/YapTouch.h - sourceTree - <group> - - C96483D6EDDC1D9D80CC3D14 - - buildActionMask - 2147483647 - files - - C437D08F0C1627C11731D429 - A183CDE4DF77587D2A3EE2B3 - 33FAA249EC636E22F4DEC988 - F5026F0CE7205EDC989EFCA3 - 6CC186CA605402EEB58AE7F1 - E70B7CB94D7522DD387DEACC - 73EA636BE31415DCB2D761B2 - 1C20335467792710E5686E3F - B7D0E52354B65AC88EABAA32 - 51BFE639418954157FD9CA51 - 7A29076BA7C76328C53B4329 - EBF1D368FBD93B61BAF61A5F - DD91382C4D1F8F4AF0C78438 - 133C7F1888D2A13E4D0C8F05 - 28D61E46758D919CBFFE2E9B - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - C9B5DDA318C401856D25FFAF - - fileRef - 1B5C84EC70CD51FC7D6A3FEF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - C9CDABBFA46667358027FC6A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFullTextSearch.m - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m - sourceTree - <group> - - CA3437B9167B07D72EFD626D - - children - - 1A060968773848D6597A2855 - 915E56EE38FA9697601D0E1C - - isa - PBXGroup - name - OHHTTPStubs - path - OHHTTPStubs - sourceTree - <group> - - CA377536DB9E4EFCFC51334F - - fileRef - F48E98A555245C01A80D1139 - isa - PBXBuildFile - - CA890C10A80DEDD1E26EE1DA - - buildConfigurationList - 9F3BC7B20238DEFFDD1E4011 - buildPhases - - C96483D6EDDC1D9D80CC3D14 - 8220A024B01E73EBB1EF1579 - 3DDF9DF8D7DF393258D985FC - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-Mantle - productName - Pods-Mantle - productReference - FEFD8FB2EFC0C6BD03805A23 - productType - com.apple.product-type.library.static - - CB25D1B3BC11FDF66237B0D3 - - fileRef - 7A9A5B6340BEBDD388AACB2E - isa - PBXBuildFile - - CB3C845CD2284348BA439199 - - buildConfigurationList - DC5D4A52CC77342D0226293D - buildPhases - - 900140167D0999AAA31BFA30 - 65452084924ABCBD89B3BB11 - 27A6D3B9C8E418175CA20FBC - - buildRules - - dependencies - - isa - PBXNativeTarget - name - Pods-CocoaLumberjack - productName - Pods-CocoaLumberjack - productReference - 7902C99FF56CB7013E1E0893 - productType - com.apple.product-type.library.static - - CB651DAE1663518DF1B7CC3C - - fileRef - C1446E03977584F292E382D2 - isa - PBXBuildFile - - CBAAF0073DF6ED5430D1AE54 - - fileRef - 26D7F66B26AFB0D48D3909ED - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - CBC51A1C218B97A22835318C - - baseConfigurationReference - BB6C9EA334CA2A15FDF86E2E - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - CD67CB5C6996D27DB6102909 - - fileRef - 8C1DA800013C02AFF58D3026 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - CD747D7642193FC6522E7961 - - fileRef - 526514FC801A87957576E3CD - isa - PBXBuildFile - - CDD7A7066B13434D8FA030CE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseString.h - path - YapDatabase/Internal/YapDatabaseString.h - sourceTree - <group> - - CDFF8E8307D4F378212C6A5B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLReflection.m - path - Mantle/MTLReflection.m - sourceTree - <group> - - CE201D26E25444A9A8BE49AD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - PromiseKit+UIKit.h - path - objc/deprecated/PromiseKit+UIKit.h - sourceTree - <group> - - CE4664104E4E693B8A7148A0 - - fileRef - 250A78C8CD713B4BA457FF80 - isa - PBXBuildFile - - CE474BCEF0BF770CEB935B0E - - fileRef - 08F2C7B599103FC0BCF1D7BB - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - CE47D64D786A3851228DD4B8 - - fileRef - A0A00489F6014D923B83648A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - CE47F6F93CDAB6A65753F5E5 - - fileRef - 6D2A243653758240F9ECE969 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - CE5514AC12936CECD10262FD - - fileRef - 0D2BEEA66F53ED2FC2927BD9 - isa - PBXBuildFile - - CEA0D1BBB3A6A4ABAD837ED5 - - baseConfigurationReference - F7E221B750098B1AFB5FE850 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - CEB8B561F98987335D130E56 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - DDAssert.h - path - Lumberjack/DDAssert.h - sourceTree - <group> - - CEEE09C293C589BB15784702 - - fileRef - 3BAB55D8C39CB29C7BD4546D - isa - PBXBuildFile - - CF16E11D068D3825818CD19C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-OHHTTPStubs-dummy.m - sourceTree - <group> - - CF36EF770B3BFC420327326F - - baseConfigurationReference - 9E4F674C887BDB6A5261AB57 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - CF738663C04A0C77723C18CA - - fileRef - 39A0FC41A341F9849B9A85C9 - isa - PBXBuildFile - - CF9C3B66B5706C19E34E5127 - - fileRef - A32C636BF537187FE0C16EE5 - isa - PBXBuildFile - - CFA7DDF69CD4AD2B74331D93 - - fileRef - 7A9A5B6340BEBDD388AACB2E - isa - PBXBuildFile - - CFB5B5B8B787F3C692C3C9ED - - fileRef - A6773877A672078CBD6D2122 - isa - PBXBuildFile - - CFD940372C922FA9891EE171 - - fileRef - 3BF31B96AD0DB5F1B8B616FA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - CFF4322F158FA5348F260B7E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSearchResultsView.m - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m - sourceTree - <group> - - D027FF13511254443219CE45 - - buildConfigurations - - 2544ECDCA0FC392F035DAAD9 - D3F739A3D45B4B79DE954C74 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - D02E2E3640634D6BA728267D - - fileRef - 83FEB76F6002C9CDDF1EC006 - isa - PBXBuildFile - - D03B94A00C83B558319BD434 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-OMGHTTPURLRQ.a - sourceTree - BUILT_PRODUCTS_DIR - - D04434DD0E4D7452AEEFD3D2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-libextobjc-Private.xcconfig - path - ../Pods-libextobjc/Pods-libextobjc-Private.xcconfig - sourceTree - <group> - - D080FD9604103BE0640F89DE - - children - - BBD6CE7E3C56F3A05CD0E0E0 - 9E4F674C887BDB6A5261AB57 - 2906854A9D6EBDEDAB4940BC - 0CEF748D4643155C85A58AD8 - 010BAC3FDBBCE0DCD451EC06 - 08076FA20D8ACA0E11E1AF6C - EC13AAB60B55E8C698F35744 - B5B68C91352F233507EDC6A7 - - isa - PBXGroup - name - Support Files - path - ../Target Support Files/Pods-BlogTests-Mantle - sourceTree - <group> - - D084BE4E40606CBC76CE60B8 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSecondaryIndexSetup.m - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m - sourceTree - <group> - - D08DBB25003E9108E490B3CD - - fileRef - 4E059837F347B34276C71290 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - D0A664498A6D67605C996D7C - - fileRef - 8B9548ECA3F342A1E5B13FA8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - D0D6A232D5FD929F3BB6072A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - OHHTTPStubsResponse+JSON.h - path - OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h - sourceTree - <group> - - D0D7E9ADC8AC927DCA2E34A0 - - fileRef - 79AE24DD32AD0A77E53AD976 - isa - PBXBuildFile - - D13FBAB7601B511A88AC0EF5 - - fileRef - 2906854A9D6EBDEDAB4940BC - isa - PBXBuildFile - - D17206B823C3958618C6FA67 - - fileRef - 8CB496A1D29F4F27BA895341 - isa - PBXBuildFile - - D1C13D67261C17D3CCA8934D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchQueue.h - path - YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueue.h - sourceTree - <group> - - D1D92BFB5E4E5A39E16E7921 - - fileRef - F1C0AE2EA4B0777F447899ED - isa - PBXBuildFile - - D1E996BE0ABBE568966B112E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewConnection.h - path - YapDatabase/Extensions/Views/YapDatabaseViewConnection.h - sourceTree - <group> - - D261294CAA6F2CCE72C03C31 - - fileRef - 3B3D883DDFB8585D392CA046 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - D26C0011FF040C1E8181D18F - - fileRef - 834CB96786F68598ABDC42B9 - isa - PBXBuildFile - - D2B248A85F1C7437A6C33E20 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseTransaction.h - path - YapDatabase/YapDatabaseTransaction.h - sourceTree - <group> - - D2D1D335CCB91AE5B63085BF - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-libextobjc.xcconfig - path - ../Pods-libextobjc/Pods-libextobjc.xcconfig - sourceTree - <group> - - D3C220DC7B6F85F26C116C1C - - fileRef - DFCE3E0CD8464A45CF86BE31 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - D3F739A3D45B4B79DE954C74 - - baseConfigurationReference - 95F6567C7B6C184546B40F39 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - YES - DSTROOT - /tmp/xcodeproj.dst - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-prefix.pch - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_CFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_CPLUSPLUSFLAGS - - -DNS_BLOCK_ASSERTIONS=1 - $(inherited) - - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - D49FEFE1C9590F94D187CA8B - - fileRef - 2E569D36941B0C5CA76D56E2 - isa - PBXBuildFile - - D4BF1170DCB1DE7AF085A112 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseSecondaryIndexTransaction.m - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m - sourceTree - <group> - - D4D6570710557532B7432896 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSObject+MTLComparisonAdditions.m - path - Mantle/NSObject+MTLComparisonAdditions.m - sourceTree - <group> - - D593B47FC6321C1668C7BB55 - - fileRef - 8B45DE3D58E4B19169D7854D - isa - PBXBuildFile - - D5FF4F0EF64541091A4250BD - - fileRef - 277AAF4FEF28F245ABAA2A3B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - D630761F0BB3F47B4F5FFC3E - - fileRef - B959903CD20DBFADD1872FC8 - isa - PBXBuildFile - - D66A679D958209DC5DE38CEF - - fileRef - 7501B6E05F277908F49B1A2C - isa - PBXBuildFile - - D67B8B4615343EA915F59B63 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - OMGUserAgent.h - sourceTree - <group> - - D73015BF2976FB6985487314 - - buildActionMask - 2147483647 - files - - 64015EC9C536E16CC7165B31 - 203ADFB7C75EBBFBA41E0FF9 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - D7536964C22982A04E649E91 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLManagedObjectAdapter.m - path - Mantle/MTLManagedObjectAdapter.m - sourceTree - <group> - - D774BD043AADBD9843208EC1 - - buildActionMask - 2147483647 - files - - 5F221F2201A6CF41C8FCF89B - 9491B9D069B63235787BFF4C - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - D7B29C97FCD74FE6EBF283ED - - fileRef - 1AADA015B3C139AA1AF718D0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - D7EAE36B659F0C295C80F2CE - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - CB3C845CD2284348BA439199 - remoteInfo - Pods-CocoaLumberjack - - D802336E1655FB340EBC9409 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - PMKPromise+Pause.m - path - objc/PMKPromise+Pause.m - sourceTree - <group> - - D8585C3EDC9BF6E4EBD080E6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewPage.h - path - YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h - sourceTree - <group> - - D94029E8D4838B9C3D8C311E - - fileRef - F6098873BF3A85424034C965 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - D95CA84B08A32970F09A5E05 - - fileRef - B52A16813A4A1CE2F582CA7A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - D97755ABDEC7FE511859791B - - fileRef - B02EDE68D12C8E7B4F857A94 - isa - PBXBuildFile - - D99791BAD09133E58E937091 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFullTextSearchTransaction.h - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h - sourceTree - <group> - - D9FBB555089342AAFF18FD1E - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapMemoryTable.m - path - YapDatabase/Internal/YapMemoryTable.m - sourceTree - <group> - - D9FE47FD270E867DAEAF75AE - - children - - 8D23F3922648D498D1C9D9E7 - F31E1FF6F19E0F532DC7509A - - isa - PBXGroup - name - EXTSafeCategory - sourceTree - <group> - - DA05E0EB819A6C421E7721B7 - - fileRef - 27ADC5EDB57744914308E786 - isa - PBXBuildFile - - DB65AF84447377AF627E15B9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-OMGHTTPURLRQ.xcconfig - path - ../Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ.xcconfig - sourceTree - <group> - - DB9F42EBD379D35ECB4ED533 - - buildConfigurations - - 4A40B27CCAEB84F14D7EF3A0 - 7094E96F28DE8358507193D0 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - DBD201095177854D0954B1EA - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 4B474CABC48D73A142E712D3 - remoteInfo - Pods-BlogTests-OMGHTTPURLRQ - - DC025172746856511FADA7CE - - fileRef - 6FBCDD252928F404E3196B62 - isa - PBXBuildFile - - DC502A19A4F283A7749BD7E7 - - fileRef - A6773877A672078CBD6D2122 - isa - PBXBuildFile - - DC5D4A52CC77342D0226293D - - buildConfigurations - - CEA0D1BBB3A6A4ABAD837ED5 - 821C64EEB6C9BEF530223DA0 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - DCB32AA665AD6E7EFCB344FA - - children - - 7E6CED80016EDD51589D3B17 - 1B5C84EC70CD51FC7D6A3FEF - AED58546469E42129793D2EB - - isa - PBXGroup - name - RuntimeExtensions - sourceTree - <group> - - DD91382C4D1F8F4AF0C78438 - - fileRef - 9C7D485F506CEDBF73A533CA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - DE0E0E0F02BD4BC7A4393BAD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-OMGHTTPURLRQ.xcconfig - sourceTree - <group> - - DE16E0B43555E1276393B2CB - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-YapDatabase-Private.xcconfig - path - ../Pods-YapDatabase/Pods-YapDatabase-Private.xcconfig - sourceTree - <group> - - DE4463B89BD90C96A117E02D - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSNotificationCenter+PromiseKit.h - path - objc/NSNotificationCenter+PromiseKit.h - sourceTree - <group> - - DE918B5BF41F4A54E265AAD6 - - fileRef - 547FECE7A3BD7B14D730F49E - isa - PBXBuildFile - - DE96E0E294B8B2855408137C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - MTLModel+NSCoding.h - path - Mantle/MTLModel+NSCoding.h - sourceTree - <group> - - DE98787F03FA7B959AB44C04 - - fileRef - 4DB22EF0176AD3E9EE1AFCC1 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - DF02AD7B823B7B540B2EE3D9 - - isa - PBXTargetDependency - target - CB3C845CD2284348BA439199 - targetProxy - D7EAE36B659F0C295C80F2CE - - DF0E0A58400AC34BF025F0E3 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseQuery.m - path - YapDatabase/Utilities/YapDatabaseQuery.m - sourceTree - <group> - - DF59954913D98ADEF2981676 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-BlogTests-OHHTTPStubs.a - sourceTree - BUILT_PRODUCTS_DIR - - DFCE3E0CD8464A45CF86BE31 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDContextFilterLogFormatter.m - path - Lumberjack/Extensions/DDContextFilterLogFormatter.m - sourceTree - <group> - - E00A3BCDDE919BD915C9752F - - children - - D67B8B4615343EA915F59B63 - 1AADA015B3C139AA1AF718D0 - - isa - PBXGroup - name - UserAgent - sourceTree - <group> - - E00F87E916682C9F2FCE40F4 - - fileRef - B8A98F7EBA444817481514EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E026B419422DA6C2BEFCB031 - - fileRef - 3A534974C696B9A0DA1475EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - E083CA8ED154237A8CDB02E2 - - fileRef - 011623DB8A11A1559279E2BF - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - E0BD33C3DD199D1D1EFD5D78 - - fileRef - 107F52C2668DE2225CB97946 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E16890EE7DBF711D338DF459 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - MTLModel.m - path - Mantle/MTLModel.m - sourceTree - <group> - - E1D6D694F1DC16E728BA5335 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseViewChange.m - path - YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m - sourceTree - <group> - - E22135502E6F21DDE43963C6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapMemoryTable.h - path - YapDatabase/Internal/YapMemoryTable.h - sourceTree - <group> - - E280F0BA81DEFC4B15970E16 - - buildConfigurations - - CBC51A1C218B97A22835318C - A0E8575B3BB05198EA828BB4 - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - E2BE48AD8D7A6D4A13A3C9BD - - fileRef - F955D1FAF99985C04E471CC4 - isa - PBXBuildFile - - E2C1299E87EE96DA4264103F - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.plist.xml - path - Pods-BlogTests-acknowledgements.plist - sourceTree - <group> - - E37F6EDD9146A3BB48351C38 - - fileRef - 1CDEDCFB0A90214027282936 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E39A8F67B948EFD4DD086A51 - - baseConfigurationReference - 6064C9992B037CD5DDBE2E0D - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREFIX_HEADER - Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - E39CC4AE9B4D7DB598B0D6B3 - - children - - DE4463B89BD90C96A117E02D - 277AAF4FEF28F245ABAA2A3B - 526514FC801A87957576E3CD - - isa - PBXGroup - name - NSNotificationCenter - sourceTree - <group> - - E3C35F4D3DF454F73CA8785F - - fileRef - 30F22C84531501D7A3372097 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E4234B3D55C40CACF3FBCE28 - - fileRef - 9BAE8517935E4652DA18C03F - isa - PBXBuildFile - - E51A0CF3C9459AAB05EEB297 - - children - - F6C2D3DB1C0774716908D4CE - 450E21DD059A05B0C96858F2 - - isa - PBXGroup - name - NSURLConnection - sourceTree - <group> - - E58B2643A8A88595955F784D - - isa - PBXTargetDependency - target - 4B474CABC48D73A142E712D3 - targetProxy - DBD201095177854D0954B1EA - - E5B4081AC0A6B88921DC5FB1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-BlogTests-CocoaLumberjack-dummy.m - sourceTree - <group> - - E627F5158B64A78CAF06AAD6 - - fileRef - D2B248A85F1C7437A6C33E20 - isa - PBXBuildFile - - E64D055B89DD3EEF7A81311F - - fileRef - EFDB2A224CB583CB06A1A6BD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - E65E19BDC940636C60C594A6 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - path - Pods-dummy.m - sourceTree - <group> - - E688C041405EECEA1A0AC6DB - - isa - PBXTargetDependency - target - CB3C845CD2284348BA439199 - targetProxy - 6F4E4A12F7B70B61DBF2503B - - E6A416C0262183A0CC6234EF - - fileRef - AE190E4088CE4126A58EB2CC - isa - PBXBuildFile - - E6CBBE066587633D9ED02573 - - fileRef - D1E996BE0ABBE568966B112E - isa - PBXBuildFile - - E70B7CB94D7522DD387DEACC - - fileRef - E16890EE7DBF711D338DF459 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - E70E53F9FBEB18D70B23BC15 - - fileRef - 76D179A9618236CAB6A3079A - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E7AAAC5CF03046134533E163 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - metamacros.h - path - Mantle/extobjc/metamacros.h - sourceTree - <group> - - E7D7FB096B137887FAD12FA8 - - buildActionMask - 2147483647 - files - - 893707A29536883A73DEC89C - 51BF4631E636D3074819F80C - 40DE3B79980EAF060496E853 - CB651DAE1663518DF1B7CC3C - 6FB185CC357C8497E602C138 - 3AAB2DFEEB0EB34EF9814A16 - A6B2BF5293274ED1406F2349 - 78EA958FC1EDE2C0C73753AA - DC025172746856511FADA7CE - 1530A55349F9689E21C41082 - 25DEC9D4B916397DA565F38E - EC83056DEED4CE5F1D5464DE - ADAD229FA4C0D416D30B82EB - 64B8F0ABC56325CB2F2219A3 - 2857515943CD6342037AD074 - 5FA053A75B7E6228374F7C41 - 42D5E8BE1C55D670088F3516 - E2BE48AD8D7A6D4A13A3C9BD - 5F34F5B9F65E04C0A3C258DE - 89D62AD0128848713EF389B9 - 558E2ABECE30B09027FCA6EF - 1A0911F00B0DA68EE7CCAE14 - AB38AF8060F4DFFDC853BECC - 1253578AB1AAC77D8E9D0693 - B781161C41E34196282E4097 - 022D472F320A705B6B2EEF5A - E978097FECEC5AB38A4464B5 - 19CBE819AC57B7FA45B028BB - A0284E8BDF6518D7E70B32BE - 937AB3B3D9523B93E1292FDC - C108B20E9CF45386E2C0F3B2 - 707CD685B66FA1569F7FFEE3 - 55025150AAAC34CB87BC2C00 - F221E2F2EBD9D2DC8A44B89E - 2BFD083E3A291B6822D31F46 - DC502A19A4F283A7749BD7E7 - 018ED0095A44CF339C395EBF - 4FEC11B7B1234A00901A6F6E - D593B47FC6321C1668C7BB55 - 241FDF80FF75DF004C3F0AA4 - 4CFB2D7C0381F7C08C8867D2 - 55D5F5E55C384B44FF3F8388 - CE5514AC12936CECD10262FD - A2A75EA7B19D685458B67F3B - D02E2E3640634D6BA728267D - 18683B38509456F84BE7B660 - A798705A52FA872AB15155F4 - 7E6B74F301A8CA2159487E2D - 3B32D0FC8252A74B6E79CBE7 - E9213329112E90E61F48DD72 - E627F5158B64A78CAF06AAD6 - 944EDD509871F82E2228A59F - 77F380DB3BF15D255DA49392 - 9301203F411CB95AA89FAE4B - 20C23FEA78DBD1BFC56E7E0A - 5826709045CFBF1DBBB2BBE0 - AA15386C0C7674AFCE654090 - 6A4B4CAC9182CAC89A93D9B6 - 3CE8B3156FCD8ABDF43DD480 - F495ED33098CC7C006BCDDAA - 4C24CD3EC2B8F8C7C3681DCE - A58BD77753929E7ABA84FAC5 - 9D150DD9458627602248BD44 - F3D7EDE038F970115684449E - A39BC41ADC5447539F96A0B0 - 3F72484C3810AB03BCE6D24E - 8933AAD92D28207D86A630ED - 2A344DE83E68E32EC8FB0A75 - 517B08CAFF905E0535E8F506 - D49FEFE1C9590F94D187CA8B - 7C20F1E4EE02A6CFD1478999 - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - E7DC822910C3D0B5174A9F31 - - fileRef - 107F52C2668DE2225CB97946 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - E846228E4C2EEB6D5802E220 - - baseConfigurationReference - 6C0509647707EF0A91DD2713 - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - COPY_PHASE_STRIP - NO - DSTROOT - /tmp/xcodeproj.dst - GCC_DYNAMIC_NO_PIC - NO - GCC_OPTIMIZATION_LEVEL - 0 - GCC_PRECOMPILE_PREFIX_HEADER - YES - GCC_PREPROCESSOR_DEFINITIONS - - DEBUG=1 - $(inherited) - - GCC_SYMBOLS_PRIVATE_EXTERN - NO - INSTALL_PATH - $(BUILT_PRODUCTS_DIR) - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - OTHER_LDFLAGS - - OTHER_LIBTOOLFLAGS - - PRODUCT_NAME - $(TARGET_NAME) - PUBLIC_HEADERS_FOLDER_PATH - $(TARGET_NAME) - SDKROOT - iphoneos - SKIP_INSTALL - YES - - isa - XCBuildConfiguration - name - Debug - - E88EE7CF821F0BCCD5229951 - - fileRef - 36154702DA969D3E68BAAB63 - isa - PBXBuildFile - - E8C835FE2E4F0DCC9A36A609 - - fileRef - 847484FA8697A6EEA9EDB3CF - isa - PBXBuildFile - - E91A19F1AD72577E78E274D5 - - buildActionMask - 2147483647 - files - - 52A95E926EE03709543D744A - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - E9213329112E90E61F48DD72 - - fileRef - CDD7A7066B13434D8FA030CE - isa - PBXBuildFile - - E938B4E9BD4AEA348A41C73B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - OMGHTTPURLRQ.h - sourceTree - <group> - - E978097FECEC5AB38A4464B5 - - fileRef - 298541E54701F5D2D54F84CB - isa - PBXBuildFile - - E99A36B1CC892747CEEB2D34 - - fileRef - 9C7D485F506CEDBF73A533CA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - E9BA319F7625FE787FF04357 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Promise+Until.h - path - objc/PromiseKit/Promise+Until.h - sourceTree - <group> - - E9E83C1F5E89CAEF3631B6C8 - - fileRef - 2ED139D0342733701B6E1A87 - isa - PBXBuildFile - - E9EB7DABD176D0FC42C73E7D - - fileRef - 6607FCD887172A37860230BA - isa - PBXBuildFile - - E9F69165AC3BE90EA0B74B47 - - buildSettings - - ALWAYS_SEARCH_USER_PATHS - NO - CLANG_CXX_LANGUAGE_STANDARD - gnu++0x - CLANG_CXX_LIBRARY - libc++ - CLANG_ENABLE_MODULES - YES - CLANG_ENABLE_OBJC_ARC - NO - CLANG_WARN_BOOL_CONVERSION - YES - CLANG_WARN_CONSTANT_CONVERSION - YES - CLANG_WARN_DIRECT_OBJC_ISA_USAGE - YES - CLANG_WARN_EMPTY_BODY - YES - CLANG_WARN_ENUM_CONVERSION - YES - CLANG_WARN_INT_CONVERSION - YES - CLANG_WARN_OBJC_ROOT_CLASS - YES - COPY_PHASE_STRIP - NO - ENABLE_NS_ASSERTIONS - NO - GCC_C_LANGUAGE_STANDARD - gnu99 - GCC_PREPROCESSOR_DEFINITIONS - - RELEASE=1 - - GCC_WARN_64_TO_32_BIT_CONVERSION - YES - GCC_WARN_ABOUT_RETURN_TYPE - YES - GCC_WARN_UNDECLARED_SELECTOR - YES - GCC_WARN_UNINITIALIZED_AUTOS - YES - GCC_WARN_UNUSED_FUNCTION - YES - GCC_WARN_UNUSED_VARIABLE - YES - IPHONEOS_DEPLOYMENT_TARGET - 8.0 - STRIP_INSTALLED_PRODUCT - NO - VALIDATE_PRODUCT - YES - - isa - XCBuildConfiguration - name - Release - - EA7C9AED1E39B7DB673D49A1 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSMethodSignature+EXT.m - path - extobjc/NSMethodSignature+EXT.m - sourceTree - <group> - - EAA54005DF3802B5546464A2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFilteredViewConnection.h - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h - sourceTree - <group> - - EAABC9AEE4E42439C829CF83 - - fileRef - CE201D26E25444A9A8BE49AD - isa - PBXBuildFile - - EAC703E0CDA5BADA3E32E586 - - fileRef - 0E149F643670201E753CB1E2 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - EAF20C790CBA5E04FCC8CBAC - - fileRef - 96B496B9BA6DEDCC0CF4FEB5 - isa - PBXBuildFile - - EAFEA6BAA977E305C6355574 - - fileRef - 4A5D8E6B97678C68E29FBA44 - isa - PBXBuildFile - - EB2C21534F4F113805ADD79F - - fileRef - CFF4322F158FA5348F260B7E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - EB66BD1444806823CFC29A2F - - fileRef - 7F7B8F4F89D04766CA64EC2B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - EBF1D368FBD93B61BAF61A5F - - fileRef - D4D6570710557532B7432896 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - EC026D2286E3E9E497A404FB - - fileRef - 5748AF96C02626E9AC3CF4AC - isa - PBXBuildFile - - EC13AAB60B55E8C698F35744 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - Pods-Mantle-dummy.m - path - ../Pods-Mantle/Pods-Mantle-dummy.m - sourceTree - <group> - - EC45ECF020F53D7130C60B49 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Mantle.h - path - Mantle/Mantle.h - sourceTree - <group> - - EC83056DEED4CE5F1D5464DE - - fileRef - 9BAE8517935E4652DA18C03F - isa - PBXBuildFile - - ED30D9579189880EC25AEB5E - - isa - PBXTargetDependency - target - 2C57FCB1FB0F0798C5865ED5 - targetProxy - 51F394BFC606EEC54B93A4A9 - - ED5E2561031FA84CB2242FD6 - - fileRef - 4461408D25667B0E5C30636E - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - ED9B9113E2FD3276D07AF2F7 - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 4B474CABC48D73A142E712D3 - remoteInfo - Pods-BlogTests-OMGHTTPURLRQ - - EDC5CAF7C7C80E3E2A2D7ACE - - fileRef - EC45ECF020F53D7130C60B49 - isa - PBXBuildFile - - EDDF27F1172E0DA1E57C26BF - - fileRef - B8A98F7EBA444817481514EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - EEED8A19153177323E851F33 - - buildActionMask - 2147483647 - files - - E64D055B89DD3EEF7A81311F - 1D69C7FEED59B65516086308 - 55647965FC4BC1D0149D79CC - 8099774C919DAB5D56342CB1 - 9CF17BE81AC5CB87305562B4 - FBE7B8C08F4802FC84E518AE - CFD940372C922FA9891EE171 - 90FC66842201BF01F1272508 - A040D223ABC00B888E543E1F - 055E0558547AB714FEA492CF - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - EF85220ED86C8EF77A59F98C - - children - - 210D02FF91F45B2FB59914CC - 3633F56F980CECA78B6869E9 - CA3437B9167B07D72EFD626D - 3F0BE7C879F42DDD970ABAFA - 76BDA76C965B116AE30AF8C7 - AF1F99B464C13A834C683878 - A3A1604BCC9DFADE5148A5AB - - isa - PBXGroup - name - Pods - sourceTree - <group> - - EFA167E931980D498BEDBA8C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSearchResultsViewPrivate.h - path - YapDatabase/Extensions/SearchResults/Internal/YapDatabaseSearchResultsViewPrivate.h - sourceTree - <group> - - EFDB2A224CB583CB06A1A6BD - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTADT.m - path - extobjc/EXTADT.m - sourceTree - <group> - - EFEB5CDA6D801588C9EB4CD8 - - fileRef - 4BC566EA61666FAC176E66D9 - isa - PBXBuildFile - - EFED7DD7C47CFA41BE33C3E3 - - fileRef - 8D55FA7D2E10B4E5BDBCBC7D - isa - PBXBuildFile - - F0CB53A38F4A65F13419D7F7 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseStatement.m - path - YapDatabase/Internal/YapDatabaseStatement.m - sourceTree - <group> - - F0DB725FACD906073AD22268 - - fileRef - 30F22C84531501D7A3372097 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - F13B084D8A4FFE7E1F1C45F0 - - fileRef - E938B4E9BD4AEA348A41C73B - isa - PBXBuildFile - - F15B5FCF47884A96045896B7 - - fileRef - BE123C9C9D19C7C4E86FA126 - isa - PBXBuildFile - - F17E98B1F085B9E5898DC23B - - fileRef - 41CBFFEE64E51235F7CEBA13 - isa - PBXBuildFile - - F1C0AE2EA4B0777F447899ED - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseExtensionPrivate.h - path - YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h - sourceTree - <group> - - F221E2F2EBD9D2DC8A44B89E - - fileRef - 73DAFF00036F4792002AB223 - isa - PBXBuildFile - - F2AC98A4DF465FBE6C7B1B28 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseViewOptions.h - path - YapDatabase/Extensions/Views/YapDatabaseViewOptions.h - sourceTree - <group> - - F2EFFB28FAE3BA4C87EE4EAE - - fileRef - AD85D1B60A21BC6069E26213 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - F31E1FF6F19E0F532DC7509A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - EXTSafeCategory.m - path - extobjc/EXTSafeCategory.m - sourceTree - <group> - - F374224ACFF5AF242D15DEE2 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - extobjc.h - path - extobjc/extobjc.h - sourceTree - <group> - - F3A5C126CFD2DA64D444EAC3 - - fileRef - 3DD8402C7BA55BFF09B4632F - isa - PBXBuildFile - - F3AC7EDAEE527675163FE062 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapTouch.m - path - YapDatabase/Internal/YapTouch.m - sourceTree - <group> - - F3D7EDE038F970115684449E - - fileRef - A3D56F7C0081101236A1ADFB - isa - PBXBuildFile - - F43CBC5611EB4B8400EECC8F - - fileRef - EFDB2A224CB583CB06A1A6BD - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - F48E98A555245C01A80D1139 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - UIAlertView+PromiseKit.h - path - objc/UIAlertView+PromiseKit.h - sourceTree - <group> - - F495ED33098CC7C006BCDDAA - - fileRef - AD2B1493CDAAF65711488F8D - isa - PBXBuildFile - - F4B68D70C8807A5AB449365B - - fileRef - 0F456E30C3CE6879F902B4A4 - isa - PBXBuildFile - - F5026F0CE7205EDC989EFCA3 - - fileRef - D7536964C22982A04E649E91 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - F510A47072303B51AA70548A - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseSecondaryIndexTransaction.h - path - YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h - sourceTree - <group> - - F55BA22691FB8864D4BFE57E - - fileRef - BAD8B2814A3FB6D5EFC732EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - F5A8223B1C33B1AB9E498E85 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - path - Pods-BlogTests-CocoaLumberjack-Private.xcconfig - sourceTree - <group> - - F5C5F03FEA0D518524954D07 - - fileRef - C69BCF8DB07E1BDADBBD4A65 - isa - PBXBuildFile - - F5E9E8E2FCE0F6F79EF148C4 - - fileRef - 1AADA015B3C139AA1AF718D0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - F6098873BF3A85424034C965 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseLogging.m - path - YapDatabase/Internal/YapDatabaseLogging.m - sourceTree - <group> - - F61CAD9071BE127939616308 - - fileRef - 6339D26E247F363AABF23B50 - isa - PBXBuildFile - - F6225A5910C1F7B16C6A2AA3 - - fileRef - 2E569D36941B0C5CA76D56E2 - isa - PBXBuildFile - - F631A7CDC3E62F8A427A0421 - - buildActionMask - 2147483647 - files - - 653F594C56A55E81B7FB9092 - C4401EC7CB524A464387775B - F3A5C126CFD2DA64D444EAC3 - 95859E34052D8F028113786A - 2B9AF0E909B3217BC2B8CA0B - 1907684C5959A2AA26AA8C8F - 5E3D4E9C4767941218D65C98 - 2BE6F7CFD919CE760ABD5CFF - B4D2174DD2F308B87C6886A3 - 11B7AB3F5BFBD5CF64A24721 - 423F116EDFDA79C7E0CD41FE - 4D344199CFBF21CC8F08412B - C69726FB98D1679AB022BA62 - 35E5B349224C4F8550F055DA - 39A073AA28B50F500C84B821 - FCE5C9E87FD073D0FF24795B - 5B06038C4324D650F35BD2DC - - isa - PBXHeadersBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - F671AB629B4C96D97FCF82DE - - fileRef - B6A247EF445935E36BDC2A3F - isa - PBXBuildFile - - F6824343229661CDBBDA3877 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - Pods-PromiseKit-prefix.pch - path - ../Pods-PromiseKit/Pods-PromiseKit-prefix.pch - sourceTree - <group> - - F6BFBE6487C6B515B2D47C4A - - fileRef - DFCE3E0CD8464A45CF86BE31 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - F6C2D3DB1C0774716908D4CE - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - NSURLConnection+PromiseKit.h - path - objc/NSURLConnection+PromiseKit.h - sourceTree - <group> - - F6ED69D788774E3D338D2BC9 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - NSArray+MTLManipulationAdditions.m - path - Mantle/NSArray+MTLManipulationAdditions.m - sourceTree - <group> - - F731AD145A1F295B60219D57 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTSelectorChecking.h - path - extobjc/EXTSelectorChecking.h - sourceTree - <group> - - F745A2219C91F2E7C3008F06 - - fileRef - 592F7BD907EDDFC3A0B0502F - isa - PBXBuildFile - - F7BC5FD7CD8DB934A586D4B9 - - fileRef - 82E4062A9BDB9F51065F0F80 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - F7E221B750098B1AFB5FE850 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - text.xcconfig - name - Pods-CocoaLumberjack-Private.xcconfig - path - ../Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig - sourceTree - <group> - - F8086C3AC09B25ED2B74DF4B - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - UIViewController+PromiseKit.m - path - objc/UIViewController+PromiseKit.m - sourceTree - <group> - - F819B59CBA6E9CBD13A99193 - - fileRef - 6E30A649D0ED2E40F3148DBE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - F8FE99ADB926CF2B33429BD0 - - fileRef - D4BF1170DCB1DE7AF085A112 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - F955D1FAF99985C04E471CC4 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - YapDatabaseFullTextSearchConnection.h - path - YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h - sourceTree - <group> - - FA36EFEA598C18B00262C163 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - name - EXTADT.h - path - extobjc/EXTADT.h - sourceTree - <group> - - FAC409A9E75704939C58961A - - fileRef - 3BF31B96AD0DB5F1B8B616FA - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - FAC6F666CA1E454F27A4F8BC - - fileRef - 2A3A8198CEF6A7DA0D0C8DDA - isa - PBXBuildFile - - FB1116CF3534A90969E20BD5 - - buildConfigurations - - 0527FF600EDF15D508B9CC0F - 5D171B9A326B7170186B556B - - defaultConfigurationIsVisible - 0 - defaultConfigurationName - Release - isa - XCConfigurationList - - FB1B51B109FA18EE59BC666E - - fileRef - AED58546469E42129793D2EB - isa - PBXBuildFile - - FBA25172F996FCAD1222219C - - fileRef - 526514FC801A87957576E3CD - isa - PBXBuildFile - - FBC20005AFD4FCFC47240369 - - fileRef - D4BF1170DCB1DE7AF085A112 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - FBD7D896586B9E0068FB55DF - - fileRef - BAD8B2814A3FB6D5EFC732EE - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - FBE7B8C08F4802FC84E518AE - - fileRef - 6732078F190FE3A6541908B5 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - FBF2C9963DF0135B4AD36268 - - fileRef - D084BE4E40606CBC76CE60B8 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - FC0366356620DF9861F43225 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseRelationshipEdge.m - path - YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.m - sourceTree - <group> - - FC38383AC75BE48113E0B868 - - fileRef - 0D700C2A0BD0B56B170D7BA0 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - FC4D9E64F3EF821EC3CC9181 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.h - path - Pods-BlogTests-OHHTTPStubs-prefix.pch - sourceTree - <group> - - FC813BAE54124E511519FA2D - - fileRef - 062F7ED90F24410039196758 - isa - PBXBuildFile - - FCE5C9E87FD073D0FF24795B - - fileRef - 504892A7A23057E7857AB508 - isa - PBXBuildFile - - FD338B9F8CF780B08C0757C4 - - fileRef - 0426F1CA8AD4B65620814DF4 - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc - - - FDAD26F8537873C4EBE10B86 - - children - - F48E98A555245C01A80D1139 - 82E4062A9BDB9F51065F0F80 - - isa - PBXGroup - name - UIAlertView - sourceTree - <group> - - FDD93D0B6173305BBF61C92C - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - YapDatabaseFilteredView.m - path - YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m - sourceTree - <group> - - FEEE5F726EDC77D9BF046929 - - includeInIndex - 1 - isa - PBXFileReference - lastKnownFileType - sourcecode.c.objc - name - DDAbstractDatabaseLogger.m - path - Lumberjack/DDAbstractDatabaseLogger.m - sourceTree - <group> - - FEFD8FB2EFC0C6BD03805A23 - - explicitFileType - archive.ar - includeInIndex - 0 - isa - PBXFileReference - path - libPods-Mantle.a - sourceTree - BUILT_PRODUCTS_DIR - - FF26035F0910419CDDCA55CF - - buildActionMask - 2147483647 - files - - 814F508F4D2D5F2496432305 - - isa - PBXFrameworksBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - FF67271E3AC8AC0E3BD9011A - - containerPortal - 359948A64E24BE0C9EDDF8EE - isa - PBXContainerItemProxy - proxyType - 1 - remoteGlobalIDString - 42F4D37A0CEF471792804AC3 - remoteInfo - Pods-BlogTests-libextobjc - - FFAB92700F871A6A2403ACED - - fileRef - C603E25AFF71674FCC071C5B - isa - PBXBuildFile - settings - - COMPILER_FLAGS - -fobjc-arc -DOS_OBJECT_USE_OBJC=0 - - - FFB9F7BDE103B355177B48CD - - buildActionMask - 2147483647 - files - - 6DB1B8271DC40A44A2EA73E4 - C269A9DA884CE9A70DB9CFF2 - 693AE3FEFC8C5C0C2C4811C7 - 78928D183EC6FFF2F458444E - CE47D64D786A3851228DD4B8 - 938C0D7B2B43A11319F0DA32 - 125F562C09B53384674F5F25 - 4D8AFB2005B50CC1CE0E3A3A - 838F21450136BE375CFE6031 - F0DB725FACD906073AD22268 - 926ABD523243BF8158594D8C - A5778933D0ED5B3FA744E028 - 9868DC5282E31D45699FF11B - 8F4804CC2A6289AF20410ECB - BFDB8B8FA6F05B3ED13CF6E7 - 68FD3DD3DE00649A6F854708 - 8110A3A0A2D8A527B681632D - FC38383AC75BE48113E0B868 - D94029E8D4838B9C3D8C311E - 890600ECF89A0DEE79274A8C - 22053307FDF1C16A3DB7B69A - 3480411692A4F653B3E73C38 - 24307A2E70BE8D17F46A4D57 - 85252833972BB6F41B3B6E38 - 40D3E914D38C3D28367514AE - E37F6EDD9146A3BB48351C38 - 4F644E76076FCBD98D2BF7C5 - C0685FC8629461A9EB558777 - EB2C21534F4F113805ADD79F - 7F2F476B65078CECD86A674B - 1F1C8C36532C598F1D8558F5 - 77EF1FF1F96D038A00C272A0 - 03C62DF4FF55BC48C381EDFF - F55BA22691FB8864D4BFE57E - 3490E786050FA5CC50C84CD8 - 0E0CF4D6D7992833ED4BC003 - F8FE99ADB926CF2B33429BD0 - 83209793414FF0DD29D0822A - 9374BBBDAD91927A8F67FE1C - EAC703E0CDA5BADA3E32E586 - 1BA3668BA75A90591EF78E13 - 9CFDB2F70E46B4FB4BD50F1B - 948154E79FAF259EEE86708B - 9D55D25EF97E2865313A8CF8 - 2F80D3CFCCA1A010EF0F415D - E70E53F9FBEB18D70B23BC15 - F2EFFB28FAE3BA4C87EE4EAE - D261294CAA6F2CCE72C03C31 - 9170E1D913BF5BEB10E9BC85 - 99357F9E64220BC943EE8D09 - ED5E2561031FA84CB2242FD6 - E7DC822910C3D0B5174A9F31 - E00F87E916682C9F2FCE40F4 - 13485812D9778A975E6D1984 - - isa - PBXSourcesBuildPhase - runOnlyForDeploymentPostprocessing - 0 - - FFD33E76F2A861FF2B548512 - - children - - A656E90D18D8F78161DC465B - E2C1299E87EE96DA4264103F - 2E4DD1B85CBB0B9B4FE20622 - 0F13A061204FC763FF0D82EA - 14DBC5B4821BA0066AFF2427 - 9C0361391A58A4191337F8B8 - 49DCEDEBD6B53F3D5FB4B231 - - isa - PBXGroup - name - Pods-BlogTests - path - Target Support Files/Pods-BlogTests - sourceTree - <group> - - FFDB6BB64625972F477FE7D4 - - fileRef - 8D23F3922648D498D1C9D9E7 - isa - PBXBuildFile - - - rootObject - 359948A64E24BE0C9EDDF8EE - - +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 007F741F640C13B83FC3CA1F /* MTLModel+NSCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C4461CD210B81105ECC94FC /* MTLModel+NSCoding.h */; }; + 00E2B77D7DE7526303FED558 /* YapDatabaseFilteredViewPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = FB51289DDF2BAD578C69E3F6 /* YapDatabaseFilteredViewPrivate.h */; }; + 016143BC6D3DD64D3F22C198 /* UIActionSheet+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 23282A3CA1331D9C53DF3FF1 /* UIActionSheet+PromiseKit.m */; }; + 01F9D45DD8703DBF1F7838B3 /* YapDatabaseViewMappings.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B1ABD2D7F4C73197567A415 /* YapDatabaseViewMappings.m */; }; + 01FE2CA8DF522F0F52CC1947 /* Pods-YapDatabase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E20BADCCAA8F64DB60774F87 /* Pods-YapDatabase-dummy.m */; }; + 042322EE4E32C952DEC6D631 /* YapDatabaseSearchResultsViewTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 54E67BE54B3CD69F000E68C7 /* YapDatabaseSearchResultsViewTransaction.h */; }; + 0520164F4EAACB63E700E760 /* NSArray+MTLManipulationAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = FF6A683D10BDE0CB84F70833 /* NSArray+MTLManipulationAdditions.h */; }; + 0548F903C52416571F233ACB /* YapDatabaseViewState.h in Headers */ = {isa = PBXBuildFile; fileRef = 67BC595E9ADC903AD5B1CAB9 /* YapDatabaseViewState.h */; }; + 077E9EFBDBD7687F5C6A7E0F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + 0922EFF87E65CCC91A19630D /* CALayer+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = BB818DCDEC16DC09B5A61EDE /* CALayer+PromiseKit.h */; }; + 09A37BECCA96B9D2AB5B4ABE /* MTLValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 541DA7760C886ECCB1EC99AB /* MTLValueTransformer.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 0A017E2DB8F8E9BF3FD9D4CB /* YapDatabaseFullTextSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 36418C93011B28E4AC39E948 /* YapDatabaseFullTextSearch.h */; }; + 0B79A2F178478D54E7B20116 /* MTLModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4839BB3BAB3CCBC31EF39119 /* MTLModel.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 0B87B7852FCB584E75DC8EBA /* YapDatabaseExtensionPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 67F6547022896E78B73719EF /* YapDatabaseExtensionPrivate.h */; }; + 0C6480EDDC730138500282A6 /* YDBCKMappingTableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB0046D4F29BA14814F660A /* YDBCKMappingTableInfo.m */; }; + 0D8062C8C292A738BC28008C /* NSError+MTLModelException.m in Sources */ = {isa = PBXBuildFile; fileRef = 222D48E9A414750043B5EEB9 /* NSError+MTLModelException.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 0E6A82EA647A6DF6672592F3 /* YapDatabaseRelationshipPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DFECAD768B873113696B9B /* YapDatabaseRelationshipPrivate.h */; }; + 0FB116FEE58F45EF3D8D39B0 /* NSURLConnection+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F9773BADAD3556EA01724E5F /* NSURLConnection+PromiseKit.m */; }; + 0FCBC0749E44D41B26E99A59 /* YapDatabaseRelationshipConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 298061D94C1747D18EBF1870 /* YapDatabaseRelationshipConnection.m */; }; + 0FF020F41CBD054A3932C50E /* YapDatabaseViewChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B68E345C0E2426890E84E1E /* YapDatabaseViewChange.h */; }; + 10429102C946DDC613AA2B73 /* NSMethodSignature+EXT.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E904A284D521BF42978D21 /* NSMethodSignature+EXT.h */; }; + 10B5708EA877A4A2AA6AB01B /* UIViewController+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F160F516AD512BB070334E13 /* UIViewController+PromiseKit.m */; }; + 13C003C528DFA9A9F3073B43 /* YapDatabaseViewOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = FF60FCF23C64B8EF6290248E /* YapDatabaseViewOptions.m */; }; + 151A8AC904286D6F6655CB63 /* DDDispatchQueueLogFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F68FA0FF71257A9C104D900 /* DDDispatchQueueLogFormatter.h */; }; + 15E38F9C005EEF2C0AEB43A6 /* YapSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7A32C19352D308D89ACCA2 /* YapSet.h */; }; + 1663D8B78117B111DDEB1F5C /* YapDatabaseSecondaryIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DB9E346F37D09E97D5D5024 /* YapDatabaseSecondaryIndex.m */; }; + 16987B3AF68ACBA047E4CCCA /* YapDatabaseFullTextSearchTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E339181D39B266DEC53CB0A /* YapDatabaseFullTextSearchTransaction.m */; }; + 1759708F65FD92513B8123A3 /* YapDatabaseViewTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 77EBF2AB82C5E726D5955557 /* YapDatabaseViewTypes.m */; }; + 17875094B0CC989BFCD8B70E /* YapDatabaseRelationship.h in Headers */ = {isa = PBXBuildFile; fileRef = 98B7FAB5222CAEB7B6DAF34A /* YapDatabaseRelationship.h */; }; + 1817671FF5B5ABB4BE448EE5 /* YapDatabaseQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 42793E8D5EF5F74F75C7133F /* YapDatabaseQuery.h */; }; + 195C8066B9AEB58966C53D93 /* NSNumber+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = AE3F13BF8B794B85DA895839 /* NSNumber+ObjectiveSugar.h */; }; + 1A7A1E15B61BECFB9808BC9A /* YapDatabaseFilteredViewTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 218711E1E3AE0EA758602433 /* YapDatabaseFilteredViewTransaction.h */; }; + 1BDE430969D5CA035B3BF1ED /* NSDictionary+YapDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 970633A6ABE21363DF9813AF /* NSDictionary+YapDatabase.h */; }; + 1C263643CC5F0B7AE3580082 /* YapDatabaseFullTextSearchSnippetOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CD021900F80A892574D6222 /* YapDatabaseFullTextSearchSnippetOptions.h */; }; + 1C6044CE1649578F58B9961E /* YapDatabaseFilteredViewConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B8840AA2ECE263DC2B6A9F2 /* YapDatabaseFilteredViewConnection.h */; }; + 1D6EA085B3F1D8E194796855 /* YapDatabaseViewPage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0B87635AC4B8480F62651CC0 /* YapDatabaseViewPage.mm */; }; + 1DA95D0C4AB40277C9695D66 /* CALayer+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 732387C0A0D8F6315DBAF1D3 /* CALayer+PromiseKit.m */; }; + 1E40FB2658F7FCEB4C887926 /* YapRowidSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73983E145C98E81D85997F3A /* YapRowidSet.mm */; }; + 1EAAF5F6C2270447EDC29B4C /* YapDatabaseSecondaryIndexConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D12C82CEB238FC89F09433 /* YapDatabaseSecondaryIndexConnection.m */; }; + 2032F4501BB94472C4E5E987 /* YDBCKRecordInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = B092F4D0C3CAAC4D348EC697 /* YDBCKRecordInfo.h */; }; + 20F6230C47EF619D258AAA6E /* YapDatabaseFullTextSearchSnippetOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = B330F7267B36FCBC2B00C4D9 /* YapDatabaseFullTextSearchSnippetOptions.m */; }; + 227BFC390A2E521FE7F3734E /* YapMurmurHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 379D651A460DC2A8298ACD8D /* YapMurmurHash.m */; }; + 253DE4310524B14835EDD135 /* EXTSelectorChecking.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BC7F01BF1D75D1AC8419FFD /* EXTSelectorChecking.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 25CF63C0F42E0B59F461063C /* YapWhitelistBlacklist.m in Sources */ = {isa = PBXBuildFile; fileRef = 41A73849DF4E74AB878B0CD3 /* YapWhitelistBlacklist.m */; }; + 2752EE88E18CCBAAEDDCFE31 /* EXTNil.m in Sources */ = {isa = PBXBuildFile; fileRef = 33B1FD5E0A1F71D2DB7A4045 /* EXTNil.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 2889BBDCCBBCAC20670C9773 /* YDBCKRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 464FC042B0B8068F9A293A27 /* YDBCKRecord.h */; }; + 29484C8A2BA8676F352D7A95 /* EXTConcreteProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FC150542EEEF84BA2377171 /* EXTConcreteProtocol.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 29E2BFFCA3EC5DF8BCA67346 /* NSNotificationCenter+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBE7B841ADBD0B4A2D385B1 /* NSNotificationCenter+PromiseKit.h */; }; + 2BBB77ECFC35DEE6C558AE6C /* YapDatabaseLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = E073214A9A7DC5BC597ED2F1 /* YapDatabaseLogging.h */; }; + 2BDD705BB84F242DE7D12331 /* YapDatabaseConnectionState.m in Sources */ = {isa = PBXBuildFile; fileRef = EE06B170D6BCA9859F133BB4 /* YapDatabaseConnectionState.m */; }; + 2C2079D10688AFB06AE21C50 /* DDContextFilterLogFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = A671BA931388ADC453431004 /* DDContextFilterLogFormatter.h */; }; + 2CE035BB0E9EABEEDB535D2B /* YapDatabaseSearchQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3A85525F0A958E165E21AA /* YapDatabaseSearchQueue.m */; }; + 2CF48C6D94A40236EDD4A38C /* YapDatabaseFullTextSearchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D2E28323CE037741F10AA76 /* YapDatabaseFullTextSearchHandler.m */; }; + 2D613D950823E156A0649855 /* YapDatabaseFullTextSearchConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4B631F0770A1B7F464F804 /* YapDatabaseFullTextSearchConnection.h */; }; + 2E2AF18ADE7C2D7AE07BCA28 /* UIViewController+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = AB58F107E5A70A31EDE1BEEC /* UIViewController+PromiseKit.h */; }; + 2F82FC88A9C51D8697433452 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + 2FBCF11D260057B17D1D2624 /* UIAlertView+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = FFA6E7BBD7D253B6A47ADF7D /* UIAlertView+PromiseKit.m */; }; + 320C12128619516CDC082030 /* YDBCKAttachRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 85813705029C3A752DAAA823 /* YDBCKAttachRequest.h */; }; + 32C5FEBB1261C047CC4B31A8 /* NSArray+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B2FF26957DCEF25790322C1 /* NSArray+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 330376AD9FC5647B9425A3B0 /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 39C01323D5C51429E51640C2 /* metamacros.h */; }; + 3341A093D96DF05AD9D21D97 /* YapDatabaseTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 191AFE1651E58C5183D5EABA /* YapDatabaseTransaction.h */; }; + 3373F8E004411E72320670F8 /* YapCache.h in Headers */ = {isa = PBXBuildFile; fileRef = BA66D04CD4554C01ABA3949C /* YapCache.h */; }; + 3488D27C9CA0EA168116BAFA /* YapDatabaseRelationshipTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = AF2A25E60330846D1464678E /* YapDatabaseRelationshipTransaction.h */; }; + 352E08E3FDF4D74B56768812 /* YapCollectionKey.m in Sources */ = {isa = PBXBuildFile; fileRef = CFAA6AF9DE36D35243D46812 /* YapCollectionKey.m */; }; + 36AD8BB6DFEB3100C6F5A05E /* YapSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B27EF2C3C4ECD3BA8BDACC7 /* YapSet.m */; }; + 36C1FC31D0AAD3ED40FDFBE9 /* EXTSafeCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B694C964F3411D32D5D9EC2 /* EXTSafeCategory.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 3916FA4B485724427DE83EEA /* YapDatabaseSearchQueuePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0015D5E11C9591C68C2AA7 /* YapDatabaseSearchQueuePrivate.h */; }; + 3A37222B52D6C41B7881FD7D /* DDDispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = C6CADBA06D2B54D61C13071C /* DDDispatchQueueLogFormatter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 3BC4660E2071311F3BC496DD /* YapDatabaseFullTextSearchTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9520DCD299B21CD83BACE4DC /* YapDatabaseFullTextSearchTransaction.h */; }; + 3D319303A6F6FA5275CC5B96 /* YDBCKChangeQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A426400B271E4AE2F1E7146 /* YDBCKChangeQueue.h */; }; + 3DD5C902942FD775019A4227 /* NSDictionary+MTLMappingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = BC0AD0DB5BD3BAA7656F3FBD /* NSDictionary+MTLMappingAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 3F5FFF07B90D48BE07F23A12 /* YDBCKRecordTableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F3D7ED2DD5AD411AC38F359 /* YDBCKRecordTableInfo.m */; }; + 4014F479978CCBAAF38F5043 /* EXTSafeCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FA4CF3A513FC48B3E3C895E /* EXTSafeCategory.h */; }; + 401A201D7390B6E45616323C /* UIView+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = EA1A2E1B2C1E611466CFF1DB /* UIView+PromiseKit.m */; }; + 408BA840BE234BBCEE4657B2 /* NSArray+MTLManipulationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 26E8C4E20FEE3BD7F6380212 /* NSArray+MTLManipulationAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 41BE33B30F5C82EE8666985E /* EXTSelectorChecking.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD4A6C5292E0564A337B565 /* EXTSelectorChecking.h */; }; + 421998FE3BFC2D363C2302A6 /* YapDatabaseSecondaryIndexPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E9F1BE2295DAEA08798E24E /* YapDatabaseSecondaryIndexPrivate.h */; }; + 432A3497095D94DB14B3FA64 /* NSMutableArray+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = A8ECA6A42B04B8DC8E455BBA /* NSMutableArray+ObjectiveSugar.h */; }; + 43BAB55883AE12E8D10F32B3 /* YapMurmurHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 82904272BA8DC583C6A88AB1 /* YapMurmurHash.h */; }; + 45AF312832FB7890BA69E217 /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D234E2C31DEA86899A7B1FE /* EXTRuntimeExtensions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 45DF178F4AB951599059E18F /* YapDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F140FD12DD2636983491D18 /* YapDatabaseManager.m */; }; + 45E75AF08365440E05DF6A27 /* YapDatabaseConnectionDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = C44404C283CAF8E032AEDB52 /* YapDatabaseConnectionDefaults.h */; }; + 4783FAD5039BCCCCB31D05BC /* YapDatabaseSearchResultsViewOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = D95922659875A01BCE8989E1 /* YapDatabaseSearchResultsViewOptions.m */; }; + 492DD4001B3CB960C78A6955 /* YapDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAF5CC21626A29058A71E0C /* YapDatabase.m */; }; + 4A2C74107EC836AE28C3A4C4 /* YapDatabaseConnectionDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 378C78B55BAF1450A166FE22 /* YapDatabaseConnectionDefaults.m */; }; + 4A8C4DC9D3A6D067F7AB50D3 /* DDContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 93BF383308911708C6C3AF52 /* DDContextFilterLogFormatter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 4CE40CB723AC8F6873B3F049 /* ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = E50E84F705DE194A41EA38DE /* ObjectiveSugar.h */; }; + 4EADB4960211890DB3952C03 /* NSDictionary+MTLManipulationAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E230DC4FA65315271DA3601E /* NSDictionary+MTLManipulationAdditions.h */; }; + 4F2BE2B87836E66A0FF22BA2 /* NSDictionary+MTLJSONKeyPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 95F805B74D223F0D3DE1553E /* NSDictionary+MTLJSONKeyPath.h */; }; + 4FC5CDD9A4207BA855F3426A /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCDCE9F36E3EBC5A29B744B /* EXTRuntimeExtensions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 50F0D59E8B1F556AA1EBA75B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + 521BE8EE2C0EFD70C0C015BB /* DDMultiFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = EF394EFE94FDB2680DF62AB7 /* DDMultiFormatter.h */; }; + 55EB7C523289BD83B902F4C3 /* DDLog+LOGV.h in Headers */ = {isa = PBXBuildFile; fileRef = 25C089DC8759A07EC36D0B4C /* DDLog+LOGV.h */; }; + 5775AD1714634B6B8FB185A6 /* YapDatabaseViewMappingsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 226FAD15C67A80534E8DE2AE /* YapDatabaseViewMappingsPrivate.h */; }; + 578A5DC4E244E83A5582C354 /* YapDatabaseViewMappings.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C77183C79552BA6C6AEE24E /* YapDatabaseViewMappings.h */; }; + 57D1A997EDA967899749E3BF /* YapDatabaseCloudKitTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B1302321474738DE34D18DB /* YapDatabaseCloudKitTypes.m */; }; + 588F15B1A5358B4582809D2D /* YapDatabaseViewRangeOptionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30BD8CBD2DE257ACAB7C0146 /* YapDatabaseViewRangeOptionsPrivate.h */; }; + 598A95905613C5F4F95111C8 /* YapDatabaseRelationshipOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD617C1BF003FEBB8A82BB5 /* YapDatabaseRelationshipOptions.m */; }; + 59E968FB6F3ED06A45057C62 /* YapDatabaseRelationshipEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = D8108FE7235FAE2EEE1CE5DF /* YapDatabaseRelationshipEdge.h */; }; + 5A22FFF7A64779CCB32C7742 /* YapDatabaseRelationship.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD8F53ED5F94F041D9D9C2A /* YapDatabaseRelationship.m */; }; + 5A299F6087571C13E1FBD38E /* DDAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 049D3124EAC466F7E00E2BD6 /* DDAssert.h */; }; + 5D172D3F19C6F0DD41574744 /* YapDatabaseSecondaryIndexSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C452CCD477CB75D3ADD2088 /* YapDatabaseSecondaryIndexSetup.h */; }; + 5E700451A258E9AAE027AEEC /* YapTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = 33B922ACEFD8FB2BC4833A1D /* YapTouch.m */; }; + 60E6BACBD4D7B705679FD831 /* YapDatabaseFullTextSearchConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 39F8894C5EDD6E45A1385724 /* YapDatabaseFullTextSearchConnection.m */; }; + 62A26E2AECF8B1DA3924B742 /* YDBCKRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = A71F955B195FFE8D69ADC4F9 /* YDBCKRecord.m */; }; + 63848CE3C074E0223BF9EB30 /* YapDatabaseRelationshipEdgePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A2DBD6EA6A916BB7D81BEE42 /* YapDatabaseRelationshipEdgePrivate.h */; }; + 642445434692712D21F794BF /* YapDatabaseExtensionConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BC09E8B3BF40806984238AC /* YapDatabaseExtensionConnection.h */; }; + 653B605B7CD66EA5C65EB7D4 /* MTLTransformerErrorHandling.m in Sources */ = {isa = PBXBuildFile; fileRef = CCFFC1B673E45D3721E35415 /* MTLTransformerErrorHandling.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 6545BFD2C8352927A85B96A7 /* YDBCKChangeRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = AA88F3716FC4CE4FD628976C /* YDBCKChangeRecord.m */; }; + 65D0463F61748C2E67057A2B /* DDASLLogCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = FEA9C7F2213B4A18CE3F8A55 /* DDASLLogCapture.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 65E238651F83DC64FCC5A68B /* EXTSynthesize.h in Headers */ = {isa = PBXBuildFile; fileRef = 97AAD29F3E667A7A2828E22B /* EXTSynthesize.h */; }; + 666458434CBD1A432D86A986 /* YapDatabaseSearchResultsView.h in Headers */ = {isa = PBXBuildFile; fileRef = 623746D45AD677CE15DD7DBA /* YapDatabaseSearchResultsView.h */; }; + 67AEC120F735E4C9658F427E /* YDBCKChangeRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 211B08E1BDD2F7526B0AAEB4 /* YDBCKChangeRecord.h */; }; + 68D08FF487884CFAA1B161EC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + 6A204D28F2D35AE7BB4B305E /* DDTTYLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = CB6117633CD7B0AB1B71A072 /* DDTTYLogger.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 6A7CD4A1AF81FCEBE7D9FA3A /* YapDatabaseStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = D2607C43CFBEE80910AF795A /* YapDatabaseStatement.m */; }; + 6AE192F5D2A27D5E6740C203 /* YapDatabaseSecondaryIndexOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B8ADEDB723845FE9063E19 /* YapDatabaseSecondaryIndexOptions.h */; }; + 6B89D8AE2B78D630331136EB /* YapDatabaseConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC3E2156A7035060FBB2EE5 /* YapDatabaseConnection.m */; }; + 6C7EB29E04993F1A7202F90E /* YapDatabaseLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = CD7DB3EBE1757C105BE9E7E7 /* YapDatabaseLogging.m */; }; + 6D46D5F776CCAAFF8E95C7F1 /* YapDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = CFC0CF29EC6CCF29E933FEBB /* YapDatabase.h */; }; + 6D82369941093072ED61122A /* YapDatabaseOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 79E22E305BB172B57A1F6AF3 /* YapDatabaseOptions.m */; }; + 6E67EF3B831409F405C8B18A /* YapDatabaseFilteredViewConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = BA3462E14B9773EC92BD216B /* YapDatabaseFilteredViewConnection.m */; }; + 710B07FD59BA817928992297 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 35346DE23EDC71509A75E5DE /* Pods-dummy.m */; }; + 71C8205423996C5C100D0356 /* EXTRuntimeExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = AB4B6AE01220CC76558282D0 /* EXTRuntimeExtensions.h */; }; + 72370E4F604C64CCFFD90CFB /* YapCollectionKey.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB461079D742E8FE80BB329 /* YapCollectionKey.h */; }; + 72708245586CF5F647C465D9 /* EXTADT.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ACF347FE23C879FFC4FBDC1 /* EXTADT.h */; }; + 73F7AE8637DFC21688A81168 /* YapDatabasePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9567AFFFCF159BC18CDBF250 /* YapDatabasePrivate.h */; }; + 757AC3E9D775B865B179617E /* YapDatabaseRelationshipTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 677E3D165351EDADAF1DEAE4 /* YapDatabaseRelationshipTransaction.m */; }; + 75DA09355FDF3F5EF07E599F /* YapDatabaseRelationshipOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ADAC96C5DC5F8CE2CB91988 /* YapDatabaseRelationshipOptions.h */; }; + 771F2EB74D50FC1840793908 /* YapDatabaseViewState.m in Sources */ = {isa = PBXBuildFile; fileRef = 92DE0398808EE3044BC02BFD /* YapDatabaseViewState.m */; }; + 7751DAC53A4FD3D86CE7F800 /* YapDatabaseViewTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 27901D26FCE7CDD78108D550 /* YapDatabaseViewTypes.h */; }; + 788B21ADB8CAEBCB70800C49 /* NSMethodSignature+EXT.m in Sources */ = {isa = PBXBuildFile; fileRef = 795994EB10B914CB2F31B83A /* NSMethodSignature+EXT.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 7AD5EB3CE80980538C76EE60 /* NSDictionary+MTLManipulationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B519CC3886D543D37537F70 /* NSDictionary+MTLManipulationAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 7AF502E281E3D1700E2E63B1 /* PMKPromise+Pause.m in Sources */ = {isa = PBXBuildFile; fileRef = BC3DAE43EF1948EAF5E64008 /* PMKPromise+Pause.m */; }; + 7D81FEC7FABBDF36EB05F80E /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 28843410D09F64380AAABB4C /* EXTScope.h */; }; + 7EE9450E970C0068D987E7C8 /* Promise+Pause.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A68B32C08C79F754493B086 /* Promise+Pause.h */; }; + 7EEF49441156BBA4776E0CFB /* NSString+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C6983E041AC3DD0A39EA289 /* NSString+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 7EFC27818D7F8160C33B0785 /* YapDatabaseViewConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 233C073F00562E346946CA48 /* YapDatabaseViewConnection.h */; }; + 80531CBE74FA7E00F097C1C2 /* PMKPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A8A06E2320693C3558C7E8 /* PMKPromise.m */; }; + 80E3EAF64896C59E4A479529 /* NSSet+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = 018D2A00C7370E47231AE5F2 /* NSSet+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 811EF2C649403FFCAD8564D0 /* YapDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AFA93482F18061D8E55B3DA2 /* YapDatabaseManager.h */; }; + 8188C8F7B6373C258FE10EDD /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B19C0796E1F6A6CDE8C5A7 /* EXTScope.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 818D001CE9EE75563B2A3BDC /* YapMemoryTable.h in Headers */ = {isa = PBXBuildFile; fileRef = EF678F55398F2D89F2D97986 /* YapMemoryTable.h */; }; + 82A712D03546462679C7B690 /* YapDatabaseSecondaryIndexHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1519F9E1F9A5DDF901485673 /* YapDatabaseSecondaryIndexHandler.m */; }; + 82DF64283B06A9493951B901 /* DDLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DFA6C642580CF27537C7EDD /* DDLog.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 832E5D12B24ED80B89BE7910 /* Pods-ObjectiveSugar-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 778E2A549A19B203BD56900E /* Pods-ObjectiveSugar-dummy.m */; }; + 83B9463173A6CC39F6067F7D /* OMGHTTPURLRQ.h in Headers */ = {isa = PBXBuildFile; fileRef = E042680B20E99E3C221FED3E /* OMGHTTPURLRQ.h */; }; + 85D6F6032669344117D2E913 /* YDBCKRecordTableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = B71EBDA84B94423D9E8B36AB /* YDBCKRecordTableInfo.h */; }; + 867F4766B9913F355A024D2A /* YapDatabaseViewPageMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 16243F2180E149B4291CEE82 /* YapDatabaseViewPageMetadata.m */; }; + 869B8A95A96C7B5C4863D6A7 /* YDBCKRecordInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = A46AAB95061CCCB8512B8503 /* YDBCKRecordInfo.m */; }; + 87E7195676AD5509CB78A469 /* Pods-PromiseKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCAFD5A7CBE50CA628E4A7C /* Pods-PromiseKit-dummy.m */; }; + 880EB1CA20294A4F96DF3619 /* UIActionSheet+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = AA24F676352AFA0EE4E5E113 /* UIActionSheet+PromiseKit.h */; }; + 8A7FD4AD69A397861B720765 /* YDBCKMergeInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F5AD2E9FF3381CF0FE741B0 /* YDBCKMergeInfo.m */; }; + 8AF21DFF159D03C97F767389 /* YapDatabaseTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = E43DE8999BF4FEEA046D05A9 /* YapDatabaseTransaction.m */; }; + 8C08287B05BADF59BC9A27F4 /* YapDatabaseSearchResultsView.m in Sources */ = {isa = PBXBuildFile; fileRef = DB5C5B70EFD40704327DECE6 /* YapDatabaseSearchResultsView.m */; }; + 8C33CE20A185FAF81BAFC71C /* YapDatabaseCloudKitOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9A0A315A0B36136023FD43 /* YapDatabaseCloudKitOptions.h */; }; + 8E991D483B73B54A5AD3C7CA /* YapDatabaseFilteredViewTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A41CA1721495E7E3164F977A /* YapDatabaseFilteredViewTypes.h */; }; + 8EE0978A86C7C95F00F5586E /* YapDebugDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 15EA72C163D28F9D21EBBD64 /* YapDebugDictionary.h */; }; + 91AFA4BACA84F784268B3CB8 /* DDLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F962B8C1B91A25E1C30259F /* DDLog.h */; }; + 91C8B2B27E9A034588B3EF88 /* DDAbstractDatabaseLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 577A493742D1DA74DF6C6AAA /* DDAbstractDatabaseLogger.h */; }; + 932141A8322B389B5A597598 /* NSInvocation+EXT.h in Headers */ = {isa = PBXBuildFile; fileRef = 873B2AE9D57CDC68F478BB68 /* NSInvocation+EXT.h */; }; + 9442DFDFC1D5DDC3E8E27E32 /* YDBCKMappingTableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 585D8F58416862E30CE2100F /* YDBCKMappingTableInfo.h */; }; + 95A6114176F766454CB39E35 /* YapDatabaseRelationshipEdge.m in Sources */ = {isa = PBXBuildFile; fileRef = 76AD8ACB921EB83B9EBDCECC /* YapDatabaseRelationshipEdge.m */; }; + 97EE89BAFEF587530FD5806D /* MTLReflection.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C066ABBBA534C1EDC86445C /* MTLReflection.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 9862D110987495C2147CB67D /* PMKPromise+When.m in Sources */ = {isa = PBXBuildFile; fileRef = A02712AC709105E1BA43665D /* PMKPromise+When.m */; }; + 9889C4834103CF717AE25F85 /* OMGUserAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC35DBF6201D9E6F7B9B9FE /* OMGUserAgent.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 99763DDB19BD89C370726B40 /* YapDatabaseSearchResultsViewPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 527F3FADF3DEFEFE19A40983 /* YapDatabaseSearchResultsViewPrivate.h */; }; + 9A015EEE94855F115B761022 /* YapDatabaseSecondaryIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BBF307A557D3D6A6544AF4D /* YapDatabaseSecondaryIndex.h */; }; + 9AE9C9F48555491014DA60D1 /* YapDatabaseSecondaryIndexOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = BD0EF077399E6D5896F6D8AA /* YapDatabaseSecondaryIndexOptions.m */; }; + 9B064B773774FC36BAA4ECF7 /* DDASLLogCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = DF8AF42948EE367C3DFDA0E1 /* DDASLLogCapture.h */; }; + 9B3D608EA932B133F05C14E9 /* DDMultiFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = C7C2B0FD8C079D1AF8754E7A /* DDMultiFormatter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 9B4E726A9CFBA1804E58006C /* YapDatabaseQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C344EF728288071F760BF91 /* YapDatabaseQuery.m */; }; + 9C9CD99B7AC0C5047F58E665 /* NSInvocation+EXT.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2F49D5AEA2B91936EAD1E5 /* NSInvocation+EXT.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 9CF68E180A865E8B0551E0B9 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DB40B55180C8778EA99A63 /* QuartzCore.framework */; }; + 9D4F8E7070F187A962389E2A /* YapDatabaseViewChange.m in Sources */ = {isa = PBXBuildFile; fileRef = 40ED6D2073FAD88CA34560E3 /* YapDatabaseViewChange.m */; }; + 9D7ABE00695A5F2F71404F6B /* YapDatabaseViewTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = A0DDA08FE302923759EFC65E /* YapDatabaseViewTransaction.h */; }; + 9F7F76B6614AC583D001AF1E /* YapDatabaseExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C3355E49A449E3E8F15D2D /* YapDatabaseExtension.m */; }; + 9F827C827C5B1F3B64B881A4 /* YapNull.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E3737AAE040ED9E09378C4F /* YapNull.h */; }; + 9FC81B113C5B2450593CAFF4 /* YapDatabaseFullTextSearchPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D61580AF99C69E38468A202 /* YapDatabaseFullTextSearchPrivate.h */; }; + A03CFB6674C6D50980618543 /* extobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = F57D33BA17461FC4DB2C4AB1 /* extobjc.h */; }; + A14F74736E7F517740ED2655 /* YapDatabaseFullTextSearchHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C8F3F9C00DDE31A157431155 /* YapDatabaseFullTextSearchHandler.h */; }; + A160D32C4E861C8B7AC5C622 /* MTLJSONAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = F9977C177F49A8D6C9267A1D /* MTLJSONAdapter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + A3A019CA829952787448DCC7 /* YapDatabaseSecondaryIndexSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 140240C25099B9B13AE8B6B6 /* YapDatabaseSecondaryIndexSetup.m */; }; + A48A2C8985BB8235C28881D1 /* NSDictionary+MTLMappingAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D39B0B478A264DAA4763EDC2 /* NSDictionary+MTLMappingAdditions.h */; }; + A4C43E295FDB5A754D5C1028 /* YapDatabaseCloudKitTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F414F2FC7D7CA984E53B55F /* YapDatabaseCloudKitTransaction.m */; }; + A5F30F988D99A629D45689B9 /* YapDatabaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = 78B7E7E3E3CEABD424391473 /* YapDatabaseView.m */; }; + A5F6A5E22ED6575360B7EAAC /* Promise.h in Headers */ = {isa = PBXBuildFile; fileRef = BD5933E272E6EE292E0C33D2 /* Promise.h */; }; + A6EB25298004319B636896F5 /* YapDatabaseSearchResultsViewConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 91623C099DB8425107F8C2A7 /* YapDatabaseSearchResultsViewConnection.h */; }; + A79E5004C35F179577B45781 /* UIView+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 064D0A7D2038C6CB7E1EBC6C /* UIView+PromiseKit.h */; }; + A7AC56A7BBE4CE9A9F074BF8 /* YapDebugDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = B34A73D81E2AE3A69CD60A07 /* YapDebugDictionary.m */; }; + A7BD315096E8E4B17B0120E0 /* YapDatabaseSearchResultsViewConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = D1908C0156D655B271509DCA /* YapDatabaseSearchResultsViewConnection.m */; }; + A7C6BD25A76358037E50524A /* YapRowidSet.h in Headers */ = {isa = PBXBuildFile; fileRef = FAFE656C1735CF984B4A9516 /* YapRowidSet.h */; }; + A7EFBB9754D81121573FD4B2 /* YapDatabaseViewPage.h in Headers */ = {isa = PBXBuildFile; fileRef = 66C2267BED53B5F74B3EBE9E /* YapDatabaseViewPage.h */; }; + A8B24FFB059A18874701BF78 /* OMGHTTPURLRQ.m in Sources */ = {isa = PBXBuildFile; fileRef = B8C97625D995754F4AE5EE6F /* OMGHTTPURLRQ.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + A8CCDB8D145B76C259B9AF45 /* YapDatabaseCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = FECDD433E148BAC9E1BBE7A8 /* YapDatabaseCloudKit.m */; }; + A8D70A2780EEEC077EBCF277 /* YapDatabaseCloudKitTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C1492C96B48F61928F7462D /* YapDatabaseCloudKitTypes.h */; }; + A8F8A4884FE9B1CECE0E7317 /* OMGFormURLEncode.h in Headers */ = {isa = PBXBuildFile; fileRef = 393E36FA0A8340C5634EA54B /* OMGFormURLEncode.h */; }; + A934DA78F7454CEE51F56D54 /* Promise+Until.h in Headers */ = {isa = PBXBuildFile; fileRef = A83DC410265F0E8DBE0471E4 /* Promise+Until.h */; }; + A95983A98DFA212403A89803 /* YapDatabaseViewRangeOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = B3C9B9343E48BB7331BF0575 /* YapDatabaseViewRangeOptions.m */; }; + A9C42C4B9DCEC58B7D258C5B /* fwd.h in Headers */ = {isa = PBXBuildFile; fileRef = DCEFBC0DEE6FE796145D9AF3 /* fwd.h */; }; + AA69A0887EE492BD9BDE4C89 /* NSSet+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = DF83E6C94BE5FD19AB02262B /* NSSet+ObjectiveSugar.h */; }; + AAB31C1545B766C4DDA66AD6 /* NSObject+MTLComparisonAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 830EE70923D40F5010F65824 /* NSObject+MTLComparisonAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + AAD7ADD57DC7FFF91425EED5 /* NSValueTransformer+MTLInversionAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC11F7D627265A8501537E0 /* NSValueTransformer+MTLInversionAdditions.h */; }; + AADF960EA8CFAE81A5545F87 /* NSArray+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = 11F19D1CDEAD9AD4A38712ED /* NSArray+ObjectiveSugar.h */; }; + AC6121B6549FB1E5ACD23BDC /* YapDatabaseStatement.h in Headers */ = {isa = PBXBuildFile; fileRef = D01C6F97895048507253C51C /* YapDatabaseStatement.h */; }; + AC955706F46D978D624A4042 /* NSDictionary+YapDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 19353E5667112CED32A168BB /* NSDictionary+YapDatabase.m */; }; + ADFA4463B8AC48669C69D0D7 /* NSMutableArray+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4FDCA048BC2592BD999C2325 /* NSMutableArray+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + AE858E85834C1A3D00CEA357 /* YapDatabaseConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F145A9750D2071E0D4A645 /* YapDatabaseConnection.h */; }; + AE8DED488304E93C68B22298 /* YDBCKAttachRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 809BE5D35DC3541EDB1ACB91 /* YDBCKAttachRequest.m */; }; + AF7275254F27FCF36464A98D /* YapTouch.h in Headers */ = {isa = PBXBuildFile; fileRef = 9655DCE99DB0497C2C6CB5FF /* YapTouch.h */; }; + B20DD92CA85553DAE0480A79 /* YapCache.m in Sources */ = {isa = PBXBuildFile; fileRef = AEAD70039FEB949F6DC9BA17 /* YapCache.m */; }; + B21FDBF2CAEFC3FA35ED8548 /* MTLJSONAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6745BDF2258F0EE0BF5B53A7 /* MTLJSONAdapter.h */; }; + B2CD3BBE742A3F540B3775B7 /* YapDatabaseCloudKitConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = FFF5D3C4F49EC8EE45F09176 /* YapDatabaseCloudKitConnection.h */; }; + B2D489B95B7E68A4E7C1645A /* NSURLConnection+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = AED02F4F608383988CF965A6 /* NSURLConnection+PromiseKit.h */; }; + B3190607E5704A86597655FD /* YapDatabaseSearchResultsViewOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = AEB46BFD29DE0CD4B7B7A2D6 /* YapDatabaseSearchResultsViewOptions.h */; }; + B3468F68184BABFE82086721 /* DDFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = E16C596FFE0E449301226A52 /* DDFileLogger.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + B486F91E24012FBC368B42AE /* NSValueTransformer+MTLPredefinedTransformerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 89647C22295AF2D9F9B5D153 /* NSValueTransformer+MTLPredefinedTransformerAdditions.h */; }; + B8356A1C094B5DF289E8A0DD /* YDBCKChangeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C50655820BA698DB18E8A99 /* YDBCKChangeSet.h */; }; + B89B474D5E21568E09E1AC80 /* YapDatabaseFilteredViewTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = C31C2AF8C504FA21C67B4EE3 /* YapDatabaseFilteredViewTransaction.m */; }; + B94A1A9C9E64EEBC0E0FB791 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + B98E04CB6435AF691B9337C4 /* YapDatabaseViewRangeOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = FA99FEC920D17A9370A874D7 /* YapDatabaseViewRangeOptions.h */; }; + B994A1B39274EED3CCCD815B /* EXTRuntimeExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E937AE3A1C38D8F54C36561 /* EXTRuntimeExtensions.h */; }; + BAF4197475FED29DCFD41E75 /* YapDatabaseExtensionConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 530930E2366691003A28ACAF /* YapDatabaseExtensionConnection.m */; }; + BBFB123B31F45583A6226873 /* YapDatabaseString.h in Headers */ = {isa = PBXBuildFile; fileRef = EEFA9F20CDC0489B9FF2158D /* YapDatabaseString.h */; }; + BC34E85B426139ADD687562C /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 5606C5C4729A228E117F081A /* EXTScope.h */; }; + BD4E2884B7C770ADF39269C9 /* YapDatabaseViewTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8360EDC84E469FDFDEA2A793 /* YapDatabaseViewTransaction.m */; }; + BD58D46DE006E347D0A8CF8F /* MTLModel+NSCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F575D8FB8F01EEA9B5FB73 /* MTLModel+NSCoding.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + BD657FF855AFCABB80517E04 /* Mantle.h in Headers */ = {isa = PBXBuildFile; fileRef = CFC6E09D40ED2E8330F67CE7 /* Mantle.h */; }; + BD92C1BE319868938EEF75A6 /* YapDatabaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F74B7ED8EA6675A3DAA5CC3 /* YapDatabaseView.h */; }; + BE230F8A1FC7A33E41052E7C /* PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D050EB04C9B56801B320C98D /* PromiseKit.h */; }; + BE2E97F1B49C0CB29697C7B7 /* YapDatabaseSearchResultsViewTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 898D88518E8A1A7C30C8103D /* YapDatabaseSearchResultsViewTransaction.m */; }; + BFB2DEEDF3C96A2FC04A30FC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + C01520ABB975EC1F519990A6 /* YapDatabaseCloudKitOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E4FD4043D7983E6AB586A3C /* YapDatabaseCloudKitOptions.m */; }; + C0DF33C3B1F095E0AB32AACF /* Promise+When.h in Headers */ = {isa = PBXBuildFile; fileRef = 7FC0141166A22391CD8D2BB1 /* Promise+When.h */; }; + C1B244E6F6578B4A8749EB33 /* YapDatabaseSecondaryIndexHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 25EC6BCE4F2BB316485DAA8A /* YapDatabaseSecondaryIndexHandler.h */; }; + C2FA4ABC9A5E0AA220F3E621 /* YapDatabaseViewConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = B82A9311028BB8DA6159BE61 /* YapDatabaseViewConnection.m */; }; + C392BD90310BF3BF99DD2745 /* YapDatabaseOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 429C432EB6FFB1AB160E76C9 /* YapDatabaseOptions.h */; }; + C39C83FE3FADE1510A868002 /* YapDatabaseViewOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = FB4B5DC70A6F71F7C3B16EAF /* YapDatabaseViewOptions.h */; }; + C3A442C6ADE4D99720B9767C /* DDTTYLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = A8CB40E31FA2BCF3D4969B04 /* DDTTYLogger.h */; }; + C3A73DD52D3D109AA6C420D5 /* NSNumber+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = F021F69423C51843F2109D44 /* NSNumber+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + C3BA828063369FDF99D4CC8A /* YapDatabaseSecondaryIndexTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F1D142C290D595F81684139 /* YapDatabaseSecondaryIndexTransaction.h */; }; + C4C644B6887404BC149A8B43 /* DDAbstractDatabaseLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C51E606823DD7DB43CCBB8C7 /* DDAbstractDatabaseLogger.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + C5AF6E176B29249C7776A6ED /* YapDatabaseFilteredViewTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 3499CC9633BF0107142AAE36 /* YapDatabaseFilteredViewTypes.m */; }; + C75FCEED2025FAE8F2C217FD /* DDFileLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F9E26F8907F5EC2CAD9A07 /* DDFileLogger.h */; }; + C85FABC0B10C4942C61D0146 /* YapDatabaseCloudKitConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C8D2AB466E5562F39FEE98F /* YapDatabaseCloudKitConnection.m */; }; + C9531252D24DE1C6523339B7 /* YapDatabaseViewPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 693340475AB3A927BE818376 /* YapDatabaseViewPrivate.h */; }; + CADB0CD10DF730A884F88967 /* MTLTransformerErrorHandling.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6AC69F457D3E6DA2DCC9F /* MTLTransformerErrorHandling.h */; }; + CB1455E6616C518CA27ECF00 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E41BD2B6A96B44D0E2F4D55 /* UIKit.framework */; }; + CB27A000DB612A4F2201192C /* MTLValueTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = AD8B953D651CD6C7EA93410E /* MTLValueTransformer.h */; }; + CBDCBD5E3EF6096F13821B05 /* YapDatabaseExtensionTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 943A8CD7E9EC1F2C119EE2C5 /* YapDatabaseExtensionTransaction.m */; }; + CC73559157087B8E7B87188B /* PMKPromise+Until.m in Sources */ = {isa = PBXBuildFile; fileRef = F97E9F7A318BA0BF7B1AD3A9 /* PMKPromise+Until.m */; }; + CF78CBACE9DD2EF0BB057941 /* YapDatabaseRelationshipConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 37346860615993B6D14B1505 /* YapDatabaseRelationshipConnection.h */; }; + D0640E0E525F55616D8198C0 /* YapMemoryTable.m in Sources */ = {isa = PBXBuildFile; fileRef = FFEBD2CAE1209534AD2A0251 /* YapMemoryTable.m */; }; + D23A1650CEF6FE495242D9AB /* YDBCKChangeQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = ED16D47F7169C69FA2BFFA30 /* YDBCKChangeQueue.m */; }; + D26A139CF959DBEAE84DD175 /* NSString+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = CD2D886B75F95E1E60330FE0 /* NSString+ObjectiveSugar.h */; }; + D2F95E0D7E114B0146D78664 /* NSValueTransformer+MTLPredefinedTransformerAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A02C304C29888E8EE28253C /* NSValueTransformer+MTLPredefinedTransformerAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + D3F55729DCF03AB1EBC6ABC6 /* OMGUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3C36EC425C070650072F69 /* OMGUserAgent.h */; }; + D4A9346A92F263881EDAF96B /* YapDatabaseSecondaryIndexConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3059BC2BFD3E0EE14EDA3EE7 /* YapDatabaseSecondaryIndexConnection.h */; }; + D508D57DF1A202F8F5532B0A /* YapDatabaseViewPageMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCE72E9834C7D87E07EA4B1 /* YapDatabaseViewPageMetadata.h */; }; + D55615DAE27DE78E582FF8DE /* NSDictionary+ObjectiveSugar.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B155987EF346BEFBB2939E /* NSDictionary+ObjectiveSugar.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + D655CA02A6A708864D065F4C /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4229D06614BF85161F7F48C7 /* EXTKeyPathCoding.h */; }; + D77A951CC523846B3BFB066D /* MTLReflection.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D7CEC56A54507D0D1DCC634 /* MTLReflection.h */; }; + D7ADCAAA669C9E0D3253CBB0 /* NSDictionary+MTLJSONKeyPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 71ECE55FDBB496467636DD3F /* NSDictionary+MTLJSONKeyPath.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + D8986D3C20BAED95DCBAB2CA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + DA7587008ACBD634D98AB935 /* YapDatabaseCloudKitTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B9AA3E91E5A87CCA6AF7284 /* YapDatabaseCloudKitTransaction.h */; }; + DA9AF495356FDF40FB145DC8 /* MTLModel.h in Headers */ = {isa = PBXBuildFile; fileRef = ED15F5B699FE176B7729CC00 /* MTLModel.h */; }; + DBB3E0E7C8472F7BC3E43BE2 /* YapDatabaseSearchQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = BAB7AB561FFF8CAABE6A213A /* YapDatabaseSearchQueue.h */; }; + DEA831D815663A702280BC8E /* NSNotificationCenter+PromiseKit.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A2A2E5887D2D5AF3E69C10 /* NSNotificationCenter+PromiseKit.m */; }; + DEF60348439BF593AF507066 /* YapDatabaseCloudKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E335488B287C642F39B76F3 /* YapDatabaseCloudKit.h */; }; + E0D7FD97CC9C07E3B199E065 /* DDASLLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FC27303CBCF7820CB3BB28 /* DDASLLogger.h */; }; + E1EE55AD8365CEB3F3C6BD70 /* YapDatabaseExtensionTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = C4ABC1EBCD8F9E06FD6243E7 /* YapDatabaseExtensionTransaction.h */; }; + E21870B373BF7A64046907C1 /* NSValueTransformer+MTLInversionAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 770B7CEF5A6D7DFB055CD20A /* NSValueTransformer+MTLInversionAdditions.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + E372D28B6AFDC7B25C55BCD0 /* YDBCKMergeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A2C2877B14E2EE162AAF38 /* YDBCKMergeInfo.h */; }; + E3E2AF8B8A425BE787EEEC70 /* YapWhitelistBlacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FEF2E7E1C06B94B65F0037 /* YapWhitelistBlacklist.h */; }; + E6A9BF282890128E920D87D1 /* YapNull.m in Sources */ = {isa = PBXBuildFile; fileRef = 92A6B214E8BAE20E7830EBF6 /* YapNull.m */; }; + E893FF4B0E5862E46C872EEF /* YapDatabaseRelationshipNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC24886A724046A2EEA0527E /* YapDatabaseRelationshipNode.h */; }; + E94BCD55687A34DAF1C8197E /* NSError+MTLModelException.h in Headers */ = {isa = PBXBuildFile; fileRef = 444C3950B6EDC2FBAC84B5C2 /* NSError+MTLModelException.h */; }; + EB7C2A2DAEFA3E68DD0C2DE5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */; }; + ED294EEDE6517BA9E74A7365 /* Pods-CocoaLumberjack-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B1E4A2F5A4BA3D56C11C31C /* Pods-CocoaLumberjack-dummy.m */; }; + EE3DE12AC4EE185973A24877 /* EXTNil.h in Headers */ = {isa = PBXBuildFile; fileRef = FD04BEC7D7D5EDE1A95CFCF2 /* EXTNil.h */; }; + EE6E499E52B6E402B786236E /* Pods-Mantle-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 61528B964E0994D2C3A334E7 /* Pods-Mantle-dummy.m */; }; + EEB052478D4F1A26E194F4D9 /* OMGFormURLEncode.m in Sources */ = {isa = PBXBuildFile; fileRef = 856C6D9D8B00DCE05FEBD3F8 /* OMGFormURLEncode.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + EF41F3E7ABBEDF3CB01895D4 /* Pods-OMGHTTPURLRQ-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2032AD6C5089FD9A73EDDF44 /* Pods-OMGHTTPURLRQ-dummy.m */; }; + F0096881A27A111D46AF560B /* YapDatabaseConnectionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 398BECB6C509128711E47373 /* YapDatabaseConnectionState.h */; }; + F0735D654F899FD6D0451F81 /* YapDatabaseSecondaryIndexTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A3CD76CF089F0B4A4DC05AA /* YapDatabaseSecondaryIndexTransaction.m */; }; + F1CC9380EC06F12DA48A2B55 /* YapDatabaseFullTextSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 259759D2C4E16388FB517936 /* YapDatabaseFullTextSearch.m */; }; + F1F8B5F0DCD7E1BB86F9F268 /* YapDatabaseExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = B415C757C56A094013194D6E /* YapDatabaseExtension.h */; }; + F21BAEDFCFFD78F99AAF5D08 /* NSObject+MTLComparisonAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E95114A187326AA7BA09991 /* NSObject+MTLComparisonAdditions.h */; }; + F2FEB8480E930EB493DE0659 /* YDBCKChangeSet.m in Sources */ = {isa = PBXBuildFile; fileRef = D069C5A6EC306BF8CCE9612C /* YDBCKChangeSet.m */; }; + F427DCE61C8F9EA1D4FC5304 /* NSDictionary+ObjectiveSugar.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E4958B4B7FEB79FBDA705DC /* NSDictionary+ObjectiveSugar.h */; }; + F55738009B2C2B3B08A4ECE2 /* EXTADT.m in Sources */ = {isa = PBXBuildFile; fileRef = D8349CD6A6F4613205CF624B /* EXTADT.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + F66D0954CE5DF3D3CBE6064D /* Pods-libextobjc-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 60FF2CB42F2E55822A549982 /* Pods-libextobjc-dummy.m */; }; + FA9307DF73CB084B73E6C37D /* UIAlertView+PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D0B475BD00954E981A913A48 /* UIAlertView+PromiseKit.h */; }; + FB0E78F3112B8CDA6E4966EA /* DDASLLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 72FA3543C40DD98F78FFE366 /* DDASLLogger.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + FBE50FADC49004F79110D7CB /* YapDatabaseFilteredView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D197FE7E9E115C89105C2E3 /* YapDatabaseFilteredView.h */; }; + FCEB5D8FAFCFA00E0F3421EA /* EXTConcreteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 616BB0FF4165B82C982B5941 /* EXTConcreteProtocol.h */; }; + FDE4C0DFD591DAE714BDA7E7 /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C215D33080B3C56403E86D1 /* EXTScope.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + FDF798CE4BEFDAFD2FEAF15B /* YapDatabaseViewChangePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CB479279231C151A4E1D042C /* YapDatabaseViewChangePrivate.h */; }; + FE59175526BF6E62CE8BD1C8 /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A0ACBFD4DBCF9C083A947EF0 /* metamacros.h */; }; + FE87CF72EFFD8C0E3D651F40 /* YapDatabaseFilteredView.m in Sources */ = {isa = PBXBuildFile; fileRef = AD9AD9B49306A606929CAAFC /* YapDatabaseFilteredView.m */; }; + FED020E85E05DCA54FEB78C6 /* YapDatabaseCloudKitPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EABFEAAD63289AD2E1AA81BD /* YapDatabaseCloudKitPrivate.h */; }; + FF2A08CCC3BC8A56EA860790 /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = AF15FCEEB59AEB6EAD7CB6C0 /* EXTKeyPathCoding.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00D82167B28EDBC0CE0360E7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = CF9B45FD9AF86E2E19900DCE; + remoteInfo = "Pods-CocoaLumberjack"; + }; + 271961EC9EDF4C3D53181029 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = D28AE1B38101D1F1C6E0C5F8; + remoteInfo = "Pods-PromiseKit"; + }; + 60AC825DD07C67C2D0BEE3D7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E07CFAEA42D65CAAEA16E41F; + remoteInfo = "Pods-Mantle"; + }; + 69468D7EC99149C6126C4960 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E69AB6A68231E7447702085B; + remoteInfo = "Pods-YapDatabase"; + }; + A719335A643249325EF5E776 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE8ABA60CC6A843213B1A2A5; + remoteInfo = "Pods-ObjectiveSugar"; + }; + AE72A8C8E16B6C2CBEF3E467 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = C23F805F74372C3575165115; + remoteInfo = "Pods-OMGHTTPURLRQ"; + }; + B42A508AF0C6A295F0A9BE44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = CF9B45FD9AF86E2E19900DCE; + remoteInfo = "Pods-CocoaLumberjack"; + }; + C359C5D028BCD0B811FBE7B7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E44FCF643CAFD65D52CD0816; + remoteInfo = "Pods-libextobjc"; + }; + E0C5B5108183021FAB914320 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F9B1CC588BECD991E0E4093E /* Project object */; + proxyType = 1; + remoteGlobalIDString = C23F805F74372C3575165115; + remoteInfo = "Pods-OMGHTTPURLRQ"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 018D2A00C7370E47231AE5F2 /* NSSet+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSSet+ObjectiveSugar.m"; path = "Classes/NSSet+ObjectiveSugar.m"; sourceTree = ""; }; + 034632FE082BA6B4D7AB738B /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 049D3124EAC466F7E00E2BD6 /* DDAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDAssert.h; path = Lumberjack/DDAssert.h; sourceTree = ""; }; + 064D0A7D2038C6CB7E1EBC6C /* UIView+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+PromiseKit.h"; path = "objc/UIView+PromiseKit.h"; sourceTree = ""; }; + 0AB9D3ED0DF727B5B73580DB /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.release.xcconfig; sourceTree = ""; }; + 0B87635AC4B8480F62651CC0 /* YapDatabaseViewPage.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = YapDatabaseViewPage.mm; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm; sourceTree = ""; }; + 0B9AA3E91E5A87CCA6AF7284 /* YapDatabaseCloudKitTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKitTransaction.h; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h; sourceTree = ""; }; + 0C50655820BA698DB18E8A99 /* YDBCKChangeSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKChangeSet.h; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h; sourceTree = ""; }; + 0D197FE7E9E115C89105C2E3 /* YapDatabaseFilteredView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFilteredView.h; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h; sourceTree = ""; }; + 0D234E2C31DEA86899A7B1FE /* EXTRuntimeExtensions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTRuntimeExtensions.m; path = extobjc/EXTRuntimeExtensions.m; sourceTree = ""; }; + 0D2E28323CE037741F10AA76 /* YapDatabaseFullTextSearchHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFullTextSearchHandler.m; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.m; sourceTree = ""; }; + 0F140FD12DD2636983491D18 /* YapDatabaseManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseManager.m; path = YapDatabase/Internal/YapDatabaseManager.m; sourceTree = ""; }; + 0F3C36EC425C070650072F69 /* OMGUserAgent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = OMGUserAgent.h; sourceTree = ""; }; + 0F3D7ED2DD5AD411AC38F359 /* YDBCKRecordTableInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKRecordTableInfo.m; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.m; sourceTree = ""; }; + 0F414F2FC7D7CA984E53B55F /* YapDatabaseCloudKitTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseCloudKitTransaction.m; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.m; sourceTree = ""; }; + 0F5AD2E9FF3381CF0FE741B0 /* YDBCKMergeInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKMergeInfo.m; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.m; sourceTree = ""; }; + 11F19D1CDEAD9AD4A38712ED /* NSArray+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+ObjectiveSugar.h"; path = "Classes/NSArray+ObjectiveSugar.h"; sourceTree = ""; }; + 140240C25099B9B13AE8B6B6 /* YapDatabaseSecondaryIndexSetup.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndexSetup.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m; sourceTree = ""; }; + 1519F9E1F9A5DDF901485673 /* YapDatabaseSecondaryIndexHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndexHandler.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.m; sourceTree = ""; }; + 15EA72C163D28F9D21EBBD64 /* YapDebugDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDebugDictionary.h; path = YapDatabase/Internal/YapDebugDictionary.h; sourceTree = ""; }; + 16243F2180E149B4291CEE82 /* YapDatabaseViewPageMetadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewPageMetadata.m; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m; sourceTree = ""; }; + 182E835896B42F7724C8001B /* Pods-OMGHTTPURLRQ-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-OMGHTTPURLRQ-prefix.pch"; sourceTree = ""; }; + 191AFE1651E58C5183D5EABA /* YapDatabaseTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseTransaction.h; path = YapDatabase/YapDatabaseTransaction.h; sourceTree = ""; }; + 19353E5667112CED32A168BB /* NSDictionary+YapDatabase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+YapDatabase.m"; path = "YapDatabase/Internal/NSDictionary+YapDatabase.m"; sourceTree = ""; }; + 1AC11F7D627265A8501537E0 /* NSValueTransformer+MTLInversionAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSValueTransformer+MTLInversionAdditions.h"; path = "Mantle/NSValueTransformer+MTLInversionAdditions.h"; sourceTree = ""; }; + 1C215D33080B3C56403E86D1 /* EXTScope.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTScope.m; path = extobjc/EXTScope.m; sourceTree = ""; }; + 1C6983E041AC3DD0A39EA289 /* NSString+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+ObjectiveSugar.m"; path = "Classes/NSString+ObjectiveSugar.m"; sourceTree = ""; }; + 1C8D2AB466E5562F39FEE98F /* YapDatabaseCloudKitConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseCloudKitConnection.m; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.m; sourceTree = ""; }; + 1CD021900F80A892574D6222 /* YapDatabaseFullTextSearchSnippetOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearchSnippetOptions.h; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h; sourceTree = ""; }; + 1F74B7ED8EA6675A3DAA5CC3 /* YapDatabaseView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseView.h; path = YapDatabase/Extensions/Views/YapDatabaseView.h; sourceTree = ""; }; + 1FAD246F6E917E2633C2F061 /* Pods-libextobjc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-libextobjc.xcconfig"; sourceTree = ""; }; + 2032AD6C5089FD9A73EDDF44 /* Pods-OMGHTTPURLRQ-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-OMGHTTPURLRQ-dummy.m"; sourceTree = ""; }; + 20DAD4D7329DBAED28944D46 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; + 211B08E1BDD2F7526B0AAEB4 /* YDBCKChangeRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKChangeRecord.h; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h; sourceTree = ""; }; + 218711E1E3AE0EA758602433 /* YapDatabaseFilteredViewTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFilteredViewTransaction.h; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h; sourceTree = ""; }; + 222D48E9A414750043B5EEB9 /* NSError+MTLModelException.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+MTLModelException.m"; path = "Mantle/NSError+MTLModelException.m"; sourceTree = ""; }; + 226FAD15C67A80534E8DE2AE /* YapDatabaseViewMappingsPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewMappingsPrivate.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h; sourceTree = ""; }; + 23282A3CA1331D9C53DF3FF1 /* UIActionSheet+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActionSheet+PromiseKit.m"; path = "objc/UIActionSheet+PromiseKit.m"; sourceTree = ""; }; + 233C073F00562E346946CA48 /* YapDatabaseViewConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewConnection.h; path = YapDatabase/Extensions/Views/YapDatabaseViewConnection.h; sourceTree = ""; }; + 259759D2C4E16388FB517936 /* YapDatabaseFullTextSearch.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFullTextSearch.m; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m; sourceTree = ""; }; + 25C089DC8759A07EC36D0B4C /* DDLog+LOGV.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DDLog+LOGV.h"; path = "Lumberjack/DDLog+LOGV.h"; sourceTree = ""; }; + 25EC6BCE4F2BB316485DAA8A /* YapDatabaseSecondaryIndexHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexHandler.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h; sourceTree = ""; }; + 26E8C4E20FEE3BD7F6380212 /* NSArray+MTLManipulationAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MTLManipulationAdditions.m"; path = "Mantle/NSArray+MTLManipulationAdditions.m"; sourceTree = ""; }; + 27901D26FCE7CDD78108D550 /* YapDatabaseViewTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewTypes.h; path = YapDatabase/Extensions/Views/YapDatabaseViewTypes.h; sourceTree = ""; }; + 27A2C2877B14E2EE162AAF38 /* YDBCKMergeInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKMergeInfo.h; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h; sourceTree = ""; }; + 27F9E26F8907F5EC2CAD9A07 /* DDFileLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDFileLogger.h; path = Lumberjack/DDFileLogger.h; sourceTree = ""; }; + 28843410D09F64380AAABB4C /* EXTScope.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTScope.h; path = extobjc/EXTScope.h; sourceTree = ""; }; + 298061D94C1747D18EBF1870 /* YapDatabaseRelationshipConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseRelationshipConnection.m; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m; sourceTree = ""; }; + 29FD34E6503B42BB4D26ACEE /* Pods-CocoaLumberjack.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CocoaLumberjack.xcconfig"; sourceTree = ""; }; + 2A68B32C08C79F754493B086 /* Promise+Pause.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Promise+Pause.h"; path = "objc/PromiseKit/Promise+Pause.h"; sourceTree = ""; }; + 2C3A85525F0A958E165E21AA /* YapDatabaseSearchQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSearchQueue.m; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueue.m; sourceTree = ""; }; + 2F68FA0FF71257A9C104D900 /* DDDispatchQueueLogFormatter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDDispatchQueueLogFormatter.h; path = Lumberjack/Extensions/DDDispatchQueueLogFormatter.h; sourceTree = ""; }; + 3059BC2BFD3E0EE14EDA3EE7 /* YapDatabaseSecondaryIndexConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexConnection.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h; sourceTree = ""; }; + 30BD8CBD2DE257ACAB7C0146 /* YapDatabaseViewRangeOptionsPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewRangeOptionsPrivate.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h; sourceTree = ""; }; + 30C27A01F64B94B091704EA6 /* Pods-OMGHTTPURLRQ.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-OMGHTTPURLRQ.xcconfig"; sourceTree = ""; }; + 33B1FD5E0A1F71D2DB7A4045 /* EXTNil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTNil.m; path = extobjc/EXTNil.m; sourceTree = ""; }; + 33B922ACEFD8FB2BC4833A1D /* YapTouch.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapTouch.m; path = YapDatabase/Internal/YapTouch.m; sourceTree = ""; }; + 3499CC9633BF0107142AAE36 /* YapDatabaseFilteredViewTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFilteredViewTypes.m; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.m; sourceTree = ""; }; + 34C3355E49A449E3E8F15D2D /* YapDatabaseExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseExtension.m; path = YapDatabase/Extensions/Protocol/YapDatabaseExtension.m; sourceTree = ""; }; + 34F575D8FB8F01EEA9B5FB73 /* MTLModel+NSCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MTLModel+NSCoding.m"; path = "Mantle/MTLModel+NSCoding.m"; sourceTree = ""; }; + 35346DE23EDC71509A75E5DE /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; + 36418C93011B28E4AC39E948 /* YapDatabaseFullTextSearch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearch.h; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h; sourceTree = ""; }; + 37346860615993B6D14B1505 /* YapDatabaseRelationshipConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipConnection.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h; sourceTree = ""; }; + 378C78B55BAF1450A166FE22 /* YapDatabaseConnectionDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseConnectionDefaults.m; path = YapDatabase/Internal/YapDatabaseConnectionDefaults.m; sourceTree = ""; }; + 379D651A460DC2A8298ACD8D /* YapMurmurHash.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapMurmurHash.m; path = YapDatabase/Utilities/YapMurmurHash.m; sourceTree = ""; }; + 393E36FA0A8340C5634EA54B /* OMGFormURLEncode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = OMGFormURLEncode.h; sourceTree = ""; }; + 398BECB6C509128711E47373 /* YapDatabaseConnectionState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseConnectionState.h; path = YapDatabase/Internal/YapDatabaseConnectionState.h; sourceTree = ""; }; + 39C01323D5C51429E51640C2 /* metamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = metamacros.h; path = extobjc/metamacros.h; sourceTree = ""; }; + 39F8894C5EDD6E45A1385724 /* YapDatabaseFullTextSearchConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFullTextSearchConnection.m; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m; sourceTree = ""; }; + 3A02C304C29888E8EE28253C /* NSValueTransformer+MTLPredefinedTransformerAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSValueTransformer+MTLPredefinedTransformerAdditions.m"; path = "Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m"; sourceTree = ""; }; + 3B8840AA2ECE263DC2B6A9F2 /* YapDatabaseFilteredViewConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFilteredViewConnection.h; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h; sourceTree = ""; }; + 3BC09E8B3BF40806984238AC /* YapDatabaseExtensionConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseExtensionConnection.h; path = YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h; sourceTree = ""; }; + 3C344EF728288071F760BF91 /* YapDatabaseQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseQuery.m; path = YapDatabase/Utilities/YapDatabaseQuery.m; sourceTree = ""; }; + 3C4461CD210B81105ECC94FC /* MTLModel+NSCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MTLModel+NSCoding.h"; path = "Mantle/MTLModel+NSCoding.h"; sourceTree = ""; }; + 3C452CCD477CB75D3ADD2088 /* YapDatabaseSecondaryIndexSetup.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexSetup.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h; sourceTree = ""; }; + 3D7A32C19352D308D89ACCA2 /* YapSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapSet.h; path = YapDatabase/Utilities/YapSet.h; sourceTree = ""; }; + 3E3737AAE040ED9E09378C4F /* YapNull.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapNull.h; path = YapDatabase/Internal/YapNull.h; sourceTree = ""; }; + 3E41BD2B6A96B44D0E2F4D55 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 3E937AE3A1C38D8F54C36561 /* EXTRuntimeExtensions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTRuntimeExtensions.h; path = extobjc/EXTRuntimeExtensions.h; sourceTree = ""; }; + 40B2610168FCD43954EC68F3 /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; + 40ED6D2073FAD88CA34560E3 /* YapDatabaseViewChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewChange.m; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m; sourceTree = ""; }; + 41A73849DF4E74AB878B0CD3 /* YapWhitelistBlacklist.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapWhitelistBlacklist.m; path = YapDatabase/Utilities/YapWhitelistBlacklist.m; sourceTree = ""; }; + 41D6C93E8EAFA752B9501ADA /* Pods-YapDatabase.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-YapDatabase.xcconfig"; sourceTree = ""; }; + 4229D06614BF85161F7F48C7 /* EXTKeyPathCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTKeyPathCoding.h; path = extobjc/EXTKeyPathCoding.h; sourceTree = ""; }; + 42793E8D5EF5F74F75C7133F /* YapDatabaseQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseQuery.h; path = YapDatabase/Utilities/YapDatabaseQuery.h; sourceTree = ""; }; + 429C432EB6FFB1AB160E76C9 /* YapDatabaseOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseOptions.h; path = YapDatabase/YapDatabaseOptions.h; sourceTree = ""; }; + 444C3950B6EDC2FBAC84B5C2 /* NSError+MTLModelException.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+MTLModelException.h"; path = "Mantle/NSError+MTLModelException.h"; sourceTree = ""; }; + 464FC042B0B8068F9A293A27 /* YDBCKRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKRecord.h; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h; sourceTree = ""; }; + 4839BB3BAB3CCBC31EF39119 /* MTLModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MTLModel.m; path = Mantle/MTLModel.m; sourceTree = ""; }; + 4AB0046D4F29BA14814F660A /* YDBCKMappingTableInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKMappingTableInfo.m; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.m; sourceTree = ""; }; + 4B519CC3886D543D37537F70 /* NSDictionary+MTLManipulationAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+MTLManipulationAdditions.m"; path = "Mantle/NSDictionary+MTLManipulationAdditions.m"; sourceTree = ""; }; + 4CC3E2156A7035060FBB2EE5 /* YapDatabaseConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseConnection.m; path = YapDatabase/YapDatabaseConnection.m; sourceTree = ""; }; + 4DB9E346F37D09E97D5D5024 /* YapDatabaseSecondaryIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndex.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m; sourceTree = ""; }; + 4DFA6C642580CF27537C7EDD /* DDLog.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDLog.m; path = Lumberjack/DDLog.m; sourceTree = ""; }; + 4E9F1BE2295DAEA08798E24E /* YapDatabaseSecondaryIndexPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexPrivate.h; path = YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h; sourceTree = ""; }; + 4FDCA048BC2592BD999C2325 /* NSMutableArray+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableArray+ObjectiveSugar.m"; path = "Classes/NSMutableArray+ObjectiveSugar.m"; sourceTree = ""; }; + 527F3FADF3DEFEFE19A40983 /* YapDatabaseSearchResultsViewPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchResultsViewPrivate.h; path = YapDatabase/Extensions/SearchResults/Internal/YapDatabaseSearchResultsViewPrivate.h; sourceTree = ""; }; + 530930E2366691003A28ACAF /* YapDatabaseExtensionConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseExtensionConnection.m; path = YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m; sourceTree = ""; }; + 541DA7760C886ECCB1EC99AB /* MTLValueTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MTLValueTransformer.m; path = Mantle/MTLValueTransformer.m; sourceTree = ""; }; + 54E67BE54B3CD69F000E68C7 /* YapDatabaseSearchResultsViewTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchResultsViewTransaction.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.h; sourceTree = ""; }; + 54F2BBA18BAA51ECCE2A1EB1 /* libPods-Mantle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Mantle.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5606C5C4729A228E117F081A /* EXTScope.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTScope.h; path = Mantle/extobjc/EXTScope.h; sourceTree = ""; }; + 577A493742D1DA74DF6C6AAA /* DDAbstractDatabaseLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDAbstractDatabaseLogger.h; path = Lumberjack/DDAbstractDatabaseLogger.h; sourceTree = ""; }; + 585D8F58416862E30CE2100F /* YDBCKMappingTableInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKMappingTableInfo.h; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h; sourceTree = ""; }; + 58D8A9E45BDA2141FC71B1B0 /* Pods-ObjectiveSugar.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ObjectiveSugar.xcconfig"; sourceTree = ""; }; + 5B694C964F3411D32D5D9EC2 /* EXTSafeCategory.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTSafeCategory.m; path = extobjc/EXTSafeCategory.m; sourceTree = ""; }; + 5D7CEC56A54507D0D1DCC634 /* MTLReflection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MTLReflection.h; path = Mantle/MTLReflection.h; sourceTree = ""; }; + 5FA4CF3A513FC48B3E3C895E /* EXTSafeCategory.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTSafeCategory.h; path = extobjc/EXTSafeCategory.h; sourceTree = ""; }; + 60FF2CB42F2E55822A549982 /* Pods-libextobjc-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-libextobjc-dummy.m"; sourceTree = ""; }; + 61528B964E0994D2C3A334E7 /* Pods-Mantle-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Mantle-dummy.m"; sourceTree = ""; }; + 616BB0FF4165B82C982B5941 /* EXTConcreteProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTConcreteProtocol.h; path = extobjc/EXTConcreteProtocol.h; sourceTree = ""; }; + 623746D45AD677CE15DD7DBA /* YapDatabaseSearchResultsView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchResultsView.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h; sourceTree = ""; }; + 64CF785843553EDFA9975F03 /* Pods-CocoaLumberjack-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CocoaLumberjack-prefix.pch"; sourceTree = ""; }; + 65562BCE6AF0C3554AA9DFEF /* Pods-PromiseKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PromiseKit.xcconfig"; sourceTree = ""; }; + 66B186B0967FA2758B671D03 /* Pods-environment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-environment.h"; sourceTree = ""; }; + 66C2267BED53B5F74B3EBE9E /* YapDatabaseViewPage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewPage.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h; sourceTree = ""; }; + 6745BDF2258F0EE0BF5B53A7 /* MTLJSONAdapter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MTLJSONAdapter.h; path = Mantle/MTLJSONAdapter.h; sourceTree = ""; }; + 677E3D165351EDADAF1DEAE4 /* YapDatabaseRelationshipTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseRelationshipTransaction.m; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m; sourceTree = ""; }; + 67BC595E9ADC903AD5B1CAB9 /* YapDatabaseViewState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewState.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.h; sourceTree = ""; }; + 67F6547022896E78B73719EF /* YapDatabaseExtensionPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseExtensionPrivate.h; path = YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h; sourceTree = ""; }; + 693340475AB3A927BE818376 /* YapDatabaseViewPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewPrivate.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h; sourceTree = ""; }; + 6A426400B271E4AE2F1E7146 /* YDBCKChangeQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKChangeQueue.h; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h; sourceTree = ""; }; + 6ACF347FE23C879FFC4FBDC1 /* EXTADT.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTADT.h; path = extobjc/EXTADT.h; sourceTree = ""; }; + 6ADAC96C5DC5F8CE2CB91988 /* YapDatabaseRelationshipOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipOptions.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h; sourceTree = ""; }; + 6B1302321474738DE34D18DB /* YapDatabaseCloudKitTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseCloudKitTypes.m; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.m; sourceTree = ""; }; + 6B9B4F309426DA09B38A7B98 /* libPods-ObjectiveSugar.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ObjectiveSugar.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C066ABBBA534C1EDC86445C /* MTLReflection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MTLReflection.m; path = Mantle/MTLReflection.m; sourceTree = ""; }; + 6D61580AF99C69E38468A202 /* YapDatabaseFullTextSearchPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearchPrivate.h; path = YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h; sourceTree = ""; }; + 6FC150542EEEF84BA2377171 /* EXTConcreteProtocol.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTConcreteProtocol.m; path = extobjc/EXTConcreteProtocol.m; sourceTree = ""; }; + 70B155987EF346BEFBB2939E /* NSDictionary+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+ObjectiveSugar.m"; path = "Classes/NSDictionary+ObjectiveSugar.m"; sourceTree = ""; }; + 71A8A06E2320693C3558C7E8 /* PMKPromise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = PMKPromise.m; path = objc/PMKPromise.m; sourceTree = ""; }; + 71ECE55FDBB496467636DD3F /* NSDictionary+MTLJSONKeyPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+MTLJSONKeyPath.m"; path = "Mantle/NSDictionary+MTLJSONKeyPath.m"; sourceTree = ""; }; + 72FA3543C40DD98F78FFE366 /* DDASLLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDASLLogger.m; path = Lumberjack/DDASLLogger.m; sourceTree = ""; }; + 732387C0A0D8F6315DBAF1D3 /* CALayer+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+PromiseKit.m"; path = "objc/CALayer+PromiseKit.m"; sourceTree = ""; }; + 73983E145C98E81D85997F3A /* YapRowidSet.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = YapRowidSet.mm; path = YapDatabase/Internal/YapRowidSet.mm; sourceTree = ""; }; + 73B8ADEDB723845FE9063E19 /* YapDatabaseSecondaryIndexOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexOptions.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h; sourceTree = ""; }; + 73DB40B55180C8778EA99A63 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 75B19C0796E1F6A6CDE8C5A7 /* EXTScope.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTScope.m; path = Mantle/extobjc/EXTScope.m; sourceTree = ""; }; + 76AD8ACB921EB83B9EBDCECC /* YapDatabaseRelationshipEdge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseRelationshipEdge.m; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.m; sourceTree = ""; }; + 770B7CEF5A6D7DFB055CD20A /* NSValueTransformer+MTLInversionAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSValueTransformer+MTLInversionAdditions.m"; path = "Mantle/NSValueTransformer+MTLInversionAdditions.m"; sourceTree = ""; }; + 778E2A549A19B203BD56900E /* Pods-ObjectiveSugar-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ObjectiveSugar-dummy.m"; sourceTree = ""; }; + 77EBF2AB82C5E726D5955557 /* YapDatabaseViewTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewTypes.m; path = YapDatabase/Extensions/Views/YapDatabaseViewTypes.m; sourceTree = ""; }; + 78B7E7E3E3CEABD424391473 /* YapDatabaseView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseView.m; path = YapDatabase/Extensions/Views/YapDatabaseView.m; sourceTree = ""; }; + 795994EB10B914CB2F31B83A /* NSMethodSignature+EXT.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMethodSignature+EXT.m"; path = "extobjc/NSMethodSignature+EXT.m"; sourceTree = ""; }; + 79E22E305BB172B57A1F6AF3 /* YapDatabaseOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseOptions.m; path = YapDatabase/YapDatabaseOptions.m; sourceTree = ""; }; + 7B1E4A2F5A4BA3D56C11C31C /* Pods-CocoaLumberjack-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CocoaLumberjack-dummy.m"; sourceTree = ""; }; + 7B27EF2C3C4ECD3BA8BDACC7 /* YapSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapSet.m; path = YapDatabase/Utilities/YapSet.m; sourceTree = ""; }; + 7B2FF26957DCEF25790322C1 /* NSArray+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+ObjectiveSugar.m"; path = "Classes/NSArray+ObjectiveSugar.m"; sourceTree = ""; }; + 7C77183C79552BA6C6AEE24E /* YapDatabaseViewMappings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewMappings.h; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h; sourceTree = ""; }; + 7E339181D39B266DEC53CB0A /* YapDatabaseFullTextSearchTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFullTextSearchTransaction.m; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m; sourceTree = ""; }; + 7E95114A187326AA7BA09991 /* NSObject+MTLComparisonAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MTLComparisonAdditions.h"; path = "Mantle/NSObject+MTLComparisonAdditions.h"; sourceTree = ""; }; + 7FC0141166A22391CD8D2BB1 /* Promise+When.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Promise+When.h"; path = "objc/PromiseKit/Promise+When.h"; sourceTree = ""; }; + 809BE5D35DC3541EDB1ACB91 /* YDBCKAttachRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKAttachRequest.m; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.m; sourceTree = ""; }; + 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 82904272BA8DC583C6A88AB1 /* YapMurmurHash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapMurmurHash.h; path = YapDatabase/Utilities/YapMurmurHash.h; sourceTree = ""; }; + 830EE70923D40F5010F65824 /* NSObject+MTLComparisonAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MTLComparisonAdditions.m"; path = "Mantle/NSObject+MTLComparisonAdditions.m"; sourceTree = ""; }; + 8360EDC84E469FDFDEA2A793 /* YapDatabaseViewTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewTransaction.m; path = YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m; sourceTree = ""; }; + 84FEF2E7E1C06B94B65F0037 /* YapWhitelistBlacklist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapWhitelistBlacklist.h; path = YapDatabase/Utilities/YapWhitelistBlacklist.h; sourceTree = ""; }; + 856C6D9D8B00DCE05FEBD3F8 /* OMGFormURLEncode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = OMGFormURLEncode.m; sourceTree = ""; }; + 85813705029C3A752DAAA823 /* YDBCKAttachRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKAttachRequest.h; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h; sourceTree = ""; }; + 86ADEBF61A25C443E7790CC4 /* libPods-OMGHTTPURLRQ.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OMGHTTPURLRQ.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 873B2AE9D57CDC68F478BB68 /* NSInvocation+EXT.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSInvocation+EXT.h"; path = "extobjc/NSInvocation+EXT.h"; sourceTree = ""; }; + 89647C22295AF2D9F9B5D153 /* NSValueTransformer+MTLPredefinedTransformerAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSValueTransformer+MTLPredefinedTransformerAdditions.h"; path = "Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h"; sourceTree = ""; }; + 898D88518E8A1A7C30C8103D /* YapDatabaseSearchResultsViewTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSearchResultsViewTransaction.m; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m; sourceTree = ""; }; + 8A3CD76CF089F0B4A4DC05AA /* YapDatabaseSecondaryIndexTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndexTransaction.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m; sourceTree = ""; }; + 8B68E345C0E2426890E84E1E /* YapDatabaseViewChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewChange.h; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h; sourceTree = ""; }; + 8BC7F01BF1D75D1AC8419FFD /* EXTSelectorChecking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTSelectorChecking.m; path = extobjc/EXTSelectorChecking.m; sourceTree = ""; }; + 8C1492C96B48F61928F7462D /* YapDatabaseCloudKitTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKitTypes.h; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h; sourceTree = ""; }; + 8E05CB045EEEBD1BE3D085A8 /* Pods-PromiseKit-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PromiseKit-Private.xcconfig"; sourceTree = ""; }; + 8E4958B4B7FEB79FBDA705DC /* NSDictionary+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+ObjectiveSugar.h"; path = "Classes/NSDictionary+ObjectiveSugar.h"; sourceTree = ""; }; + 8F1D142C290D595F81684139 /* YapDatabaseSecondaryIndexTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndexTransaction.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h; sourceTree = ""; }; + 91623C099DB8425107F8C2A7 /* YapDatabaseSearchResultsViewConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchResultsViewConnection.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.h; sourceTree = ""; }; + 91805095FBEE932AED95AE42 /* libPods-YapDatabase.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-YapDatabase.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 92A6B214E8BAE20E7830EBF6 /* YapNull.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapNull.m; path = YapDatabase/Internal/YapNull.m; sourceTree = ""; }; + 92DE0398808EE3044BC02BFD /* YapDatabaseViewState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewState.m; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m; sourceTree = ""; }; + 93BF383308911708C6C3AF52 /* DDContextFilterLogFormatter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDContextFilterLogFormatter.m; path = Lumberjack/Extensions/DDContextFilterLogFormatter.m; sourceTree = ""; }; + 93F145A9750D2071E0D4A645 /* YapDatabaseConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseConnection.h; path = YapDatabase/YapDatabaseConnection.h; sourceTree = ""; }; + 943A8CD7E9EC1F2C119EE2C5 /* YapDatabaseExtensionTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseExtensionTransaction.m; path = YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m; sourceTree = ""; }; + 94B5688717AC26757392BD42 /* Pods-ObjectiveSugar-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ObjectiveSugar-Private.xcconfig"; sourceTree = ""; }; + 94DFECAD768B873113696B9B /* YapDatabaseRelationshipPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipPrivate.h; path = YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h; sourceTree = ""; }; + 9520DCD299B21CD83BACE4DC /* YapDatabaseFullTextSearchTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearchTransaction.h; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h; sourceTree = ""; }; + 9567AFFFCF159BC18CDBF250 /* YapDatabasePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabasePrivate.h; path = YapDatabase/Internal/YapDatabasePrivate.h; sourceTree = ""; }; + 95F805B74D223F0D3DE1553E /* NSDictionary+MTLJSONKeyPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+MTLJSONKeyPath.h"; path = "Mantle/NSDictionary+MTLJSONKeyPath.h"; sourceTree = ""; }; + 9655DCE99DB0497C2C6CB5FF /* YapTouch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapTouch.h; path = YapDatabase/Internal/YapTouch.h; sourceTree = ""; }; + 970633A6ABE21363DF9813AF /* NSDictionary+YapDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+YapDatabase.h"; path = "YapDatabase/Internal/NSDictionary+YapDatabase.h"; sourceTree = ""; }; + 97AAD29F3E667A7A2828E22B /* EXTSynthesize.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTSynthesize.h; path = extobjc/EXTSynthesize.h; sourceTree = ""; }; + 98B7FAB5222CAEB7B6DAF34A /* YapDatabaseRelationship.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationship.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h; sourceTree = ""; }; + 98E1245800E1ED8EBFE5CAF4 /* libPods-CocoaLumberjack.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CocoaLumberjack.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9AD8F53ED5F94F041D9D9C2A /* YapDatabaseRelationship.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseRelationship.m; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationship.m; sourceTree = ""; }; + 9B1ABD2D7F4C73197567A415 /* YapDatabaseViewMappings.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewMappings.m; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m; sourceTree = ""; }; + 9BBF307A557D3D6A6544AF4D /* YapDatabaseSecondaryIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSecondaryIndex.h; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h; sourceTree = ""; }; + 9CD32733E73D6D9420AB496F /* Pods-Mantle-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Mantle-Private.xcconfig"; sourceTree = ""; }; + 9E335488B287C642F39B76F3 /* YapDatabaseCloudKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKit.h; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h; sourceTree = ""; }; + 9E4FD4043D7983E6AB586A3C /* YapDatabaseCloudKitOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseCloudKitOptions.m; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.m; sourceTree = ""; }; + 9F962B8C1B91A25E1C30259F /* DDLog.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDLog.h; path = Lumberjack/DDLog.h; sourceTree = ""; }; + A02712AC709105E1BA43665D /* PMKPromise+When.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "PMKPromise+When.m"; path = "objc/PMKPromise+When.m"; sourceTree = ""; }; + A0ACBFD4DBCF9C083A947EF0 /* metamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = metamacros.h; path = Mantle/extobjc/metamacros.h; sourceTree = ""; }; + A0DDA08FE302923759EFC65E /* YapDatabaseViewTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewTransaction.h; path = YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h; sourceTree = ""; }; + A2DBD6EA6A916BB7D81BEE42 /* YapDatabaseRelationshipEdgePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipEdgePrivate.h; path = YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipEdgePrivate.h; sourceTree = ""; }; + A3E9E153CBCF907078D67591 /* Pods-libextobjc-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-libextobjc-Private.xcconfig"; sourceTree = ""; }; + A41CA1721495E7E3164F977A /* YapDatabaseFilteredViewTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFilteredViewTypes.h; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h; sourceTree = ""; }; + A46AAB95061CCCB8512B8503 /* YDBCKRecordInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKRecordInfo.m; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.m; sourceTree = ""; }; + A671BA931388ADC453431004 /* DDContextFilterLogFormatter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDContextFilterLogFormatter.h; path = Lumberjack/Extensions/DDContextFilterLogFormatter.h; sourceTree = ""; }; + A71F955B195FFE8D69ADC4F9 /* YDBCKRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKRecord.m; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.m; sourceTree = ""; }; + A7D12C82CEB238FC89F09433 /* YapDatabaseSecondaryIndexConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndexConnection.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m; sourceTree = ""; }; + A7D6AC69F457D3E6DA2DCC9F /* MTLTransformerErrorHandling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MTLTransformerErrorHandling.h; path = Mantle/MTLTransformerErrorHandling.h; sourceTree = ""; }; + A83DC410265F0E8DBE0471E4 /* Promise+Until.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Promise+Until.h"; path = "objc/PromiseKit/Promise+Until.h"; sourceTree = ""; }; + A8CB40E31FA2BCF3D4969B04 /* DDTTYLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDTTYLogger.h; path = Lumberjack/DDTTYLogger.h; sourceTree = ""; }; + A8ECA6A42B04B8DC8E455BBA /* NSMutableArray+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+ObjectiveSugar.h"; path = "Classes/NSMutableArray+ObjectiveSugar.h"; sourceTree = ""; }; + A9B880ED0C270A8EC1241DDA /* Pods-OMGHTTPURLRQ-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-OMGHTTPURLRQ-Private.xcconfig"; sourceTree = ""; }; + AA1BCDAB7233FEBA142D9EA5 /* Pods-ObjectiveSugar-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ObjectiveSugar-prefix.pch"; sourceTree = ""; }; + AA24F676352AFA0EE4E5E113 /* UIActionSheet+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActionSheet+PromiseKit.h"; path = "objc/UIActionSheet+PromiseKit.h"; sourceTree = ""; }; + AA88F3716FC4CE4FD628976C /* YDBCKChangeRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKChangeRecord.m; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.m; sourceTree = ""; }; + AB4B6AE01220CC76558282D0 /* EXTRuntimeExtensions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTRuntimeExtensions.h; path = Mantle/extobjc/EXTRuntimeExtensions.h; sourceTree = ""; }; + AB58F107E5A70A31EDE1BEEC /* UIViewController+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+PromiseKit.h"; path = "objc/UIViewController+PromiseKit.h"; sourceTree = ""; }; + AD8B953D651CD6C7EA93410E /* MTLValueTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MTLValueTransformer.h; path = Mantle/MTLValueTransformer.h; sourceTree = ""; }; + AD9AD9B49306A606929CAAFC /* YapDatabaseFilteredView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFilteredView.m; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m; sourceTree = ""; }; + AE3F13BF8B794B85DA895839 /* NSNumber+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNumber+ObjectiveSugar.h"; path = "Classes/NSNumber+ObjectiveSugar.h"; sourceTree = ""; }; + AE9C02BF613830CC309CAA26 /* Pods-libextobjc-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-libextobjc-prefix.pch"; sourceTree = ""; }; + AEAD70039FEB949F6DC9BA17 /* YapCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapCache.m; path = YapDatabase/Utilities/YapCache.m; sourceTree = ""; }; + AEB46BFD29DE0CD4B7B7A2D6 /* YapDatabaseSearchResultsViewOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchResultsViewOptions.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h; sourceTree = ""; }; + AED02F4F608383988CF965A6 /* NSURLConnection+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLConnection+PromiseKit.h"; path = "objc/NSURLConnection+PromiseKit.h"; sourceTree = ""; }; + AF15FCEEB59AEB6EAD7CB6C0 /* EXTKeyPathCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTKeyPathCoding.h; path = Mantle/extobjc/EXTKeyPathCoding.h; sourceTree = ""; }; + AF2A25E60330846D1464678E /* YapDatabaseRelationshipTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipTransaction.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h; sourceTree = ""; }; + AFA93482F18061D8E55B3DA2 /* YapDatabaseManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseManager.h; path = YapDatabase/Internal/YapDatabaseManager.h; sourceTree = ""; }; + AFAF5CC21626A29058A71E0C /* YapDatabase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabase.m; path = YapDatabase/YapDatabase.m; sourceTree = ""; }; + AFBE7B841ADBD0B4A2D385B1 /* NSNotificationCenter+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNotificationCenter+PromiseKit.h"; path = "objc/NSNotificationCenter+PromiseKit.h"; sourceTree = ""; }; + B092F4D0C3CAAC4D348EC697 /* YDBCKRecordInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKRecordInfo.h; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h; sourceTree = ""; }; + B330F7267B36FCBC2B00C4D9 /* YapDatabaseFullTextSearchSnippetOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFullTextSearchSnippetOptions.m; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m; sourceTree = ""; }; + B34A73D81E2AE3A69CD60A07 /* YapDebugDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDebugDictionary.m; path = YapDatabase/Internal/YapDebugDictionary.m; sourceTree = ""; }; + B34E3A4413395661C93D46D6 /* Pods-YapDatabase-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-YapDatabase-Private.xcconfig"; sourceTree = ""; }; + B3A2A2E5887D2D5AF3E69C10 /* NSNotificationCenter+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNotificationCenter+PromiseKit.m"; path = "objc/NSNotificationCenter+PromiseKit.m"; sourceTree = ""; }; + B3C9B9343E48BB7331BF0575 /* YapDatabaseViewRangeOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewRangeOptions.m; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m; sourceTree = ""; }; + B415C757C56A094013194D6E /* YapDatabaseExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseExtension.h; path = YapDatabase/Extensions/Protocol/YapDatabaseExtension.h; sourceTree = ""; }; + B71EBDA84B94423D9E8B36AB /* YDBCKRecordTableInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YDBCKRecordTableInfo.h; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h; sourceTree = ""; }; + B7E184741559D494AB0E33F1 /* libPods-PromiseKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PromiseKit.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B82A9311028BB8DA6159BE61 /* YapDatabaseViewConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewConnection.m; path = YapDatabase/Extensions/Views/YapDatabaseViewConnection.m; sourceTree = ""; }; + B8C97625D995754F4AE5EE6F /* OMGHTTPURLRQ.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = OMGHTTPURLRQ.m; sourceTree = ""; }; + BA3462E14B9773EC92BD216B /* YapDatabaseFilteredViewConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFilteredViewConnection.m; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m; sourceTree = ""; }; + BA66D04CD4554C01ABA3949C /* YapCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapCache.h; path = YapDatabase/Utilities/YapCache.h; sourceTree = ""; }; + BAB7AB561FFF8CAABE6A213A /* YapDatabaseSearchQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchQueue.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueue.h; sourceTree = ""; }; + BB818DCDEC16DC09B5A61EDE /* CALayer+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+PromiseKit.h"; path = "objc/CALayer+PromiseKit.h"; sourceTree = ""; }; + BC0AD0DB5BD3BAA7656F3FBD /* NSDictionary+MTLMappingAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+MTLMappingAdditions.m"; path = "Mantle/NSDictionary+MTLMappingAdditions.m"; sourceTree = ""; }; + BC24886A724046A2EEA0527E /* YapDatabaseRelationshipNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipNode.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h; sourceTree = ""; }; + BC3DAE43EF1948EAF5E64008 /* PMKPromise+Pause.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "PMKPromise+Pause.m"; path = "objc/PMKPromise+Pause.m"; sourceTree = ""; }; + BD0EF077399E6D5896F6D8AA /* YapDatabaseSecondaryIndexOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSecondaryIndexOptions.m; path = YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m; sourceTree = ""; }; + BD45A1F343C7E4249DCD9F3A /* Pods-PromiseKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PromiseKit-prefix.pch"; sourceTree = ""; }; + BD5933E272E6EE292E0C33D2 /* Promise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Promise.h; path = objc/PromiseKit/Promise.h; sourceTree = ""; }; + BE4B631F0770A1B7F464F804 /* YapDatabaseFullTextSearchConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearchConnection.h; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h; sourceTree = ""; }; + C31C2AF8C504FA21C67B4EE3 /* YapDatabaseFilteredViewTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseFilteredViewTransaction.m; path = YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m; sourceTree = ""; }; + C44404C283CAF8E032AEDB52 /* YapDatabaseConnectionDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseConnectionDefaults.h; path = YapDatabase/Internal/YapDatabaseConnectionDefaults.h; sourceTree = ""; }; + C4ABC1EBCD8F9E06FD6243E7 /* YapDatabaseExtensionTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseExtensionTransaction.h; path = YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h; sourceTree = ""; }; + C51E606823DD7DB43CCBB8C7 /* DDAbstractDatabaseLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDAbstractDatabaseLogger.m; path = Lumberjack/DDAbstractDatabaseLogger.m; sourceTree = ""; }; + C6CADBA06D2B54D61C13071C /* DDDispatchQueueLogFormatter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDDispatchQueueLogFormatter.m; path = Lumberjack/Extensions/DDDispatchQueueLogFormatter.m; sourceTree = ""; }; + C7C2B0FD8C079D1AF8754E7A /* DDMultiFormatter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDMultiFormatter.m; path = Lumberjack/Extensions/DDMultiFormatter.m; sourceTree = ""; }; + C8F3F9C00DDE31A157431155 /* YapDatabaseFullTextSearchHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFullTextSearchHandler.h; path = YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h; sourceTree = ""; }; + C9E904A284D521BF42978D21 /* NSMethodSignature+EXT.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMethodSignature+EXT.h"; path = "extobjc/NSMethodSignature+EXT.h"; sourceTree = ""; }; + CB479279231C151A4E1D042C /* YapDatabaseViewChangePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewChangePrivate.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h; sourceTree = ""; }; + CB6117633CD7B0AB1B71A072 /* DDTTYLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDTTYLogger.m; path = Lumberjack/DDTTYLogger.m; sourceTree = ""; }; + CCCAFD5A7CBE50CA628E4A7C /* Pods-PromiseKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PromiseKit-dummy.m"; sourceTree = ""; }; + CCCDCE9F36E3EBC5A29B744B /* EXTRuntimeExtensions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTRuntimeExtensions.m; path = Mantle/extobjc/EXTRuntimeExtensions.m; sourceTree = ""; }; + CCFFC1B673E45D3721E35415 /* MTLTransformerErrorHandling.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MTLTransformerErrorHandling.m; path = Mantle/MTLTransformerErrorHandling.m; sourceTree = ""; }; + CD2D886B75F95E1E60330FE0 /* NSString+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+ObjectiveSugar.h"; path = "Classes/NSString+ObjectiveSugar.h"; sourceTree = ""; }; + CD7DB3EBE1757C105BE9E7E7 /* YapDatabaseLogging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseLogging.m; path = YapDatabase/Internal/YapDatabaseLogging.m; sourceTree = ""; }; + CDCE72E9834C7D87E07EA4B1 /* YapDatabaseViewPageMetadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewPageMetadata.h; path = YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h; sourceTree = ""; }; + CE26A56044F7DE04692327A4 /* Pods-YapDatabase-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-YapDatabase-prefix.pch"; sourceTree = ""; }; + CFAA6AF9DE36D35243D46812 /* YapCollectionKey.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapCollectionKey.m; path = YapDatabase/Utilities/YapCollectionKey.m; sourceTree = ""; }; + CFC0CF29EC6CCF29E933FEBB /* YapDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabase.h; path = YapDatabase/YapDatabase.h; sourceTree = ""; }; + CFC6E09D40ED2E8330F67CE7 /* Mantle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Mantle.h; path = Mantle/Mantle.h; sourceTree = ""; }; + D01C6F97895048507253C51C /* YapDatabaseStatement.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseStatement.h; path = YapDatabase/Internal/YapDatabaseStatement.h; sourceTree = ""; }; + D050EB04C9B56801B320C98D /* PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PromiseKit.h; path = objc/PromiseKit.h; sourceTree = ""; }; + D069C5A6EC306BF8CCE9612C /* YDBCKChangeSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKChangeSet.m; path = YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.m; sourceTree = ""; }; + D0B475BD00954E981A913A48 /* UIAlertView+PromiseKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIAlertView+PromiseKit.h"; path = "objc/UIAlertView+PromiseKit.h"; sourceTree = ""; }; + D0FC27303CBCF7820CB3BB28 /* DDASLLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDASLLogger.h; path = Lumberjack/DDASLLogger.h; sourceTree = ""; }; + D1908C0156D655B271509DCA /* YapDatabaseSearchResultsViewConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSearchResultsViewConnection.m; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m; sourceTree = ""; }; + D1AADC7C1CF987010AA2DA67 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.debug.xcconfig; sourceTree = ""; }; + D2607C43CFBEE80910AF795A /* YapDatabaseStatement.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseStatement.m; path = YapDatabase/Internal/YapDatabaseStatement.m; sourceTree = ""; }; + D39B0B478A264DAA4763EDC2 /* NSDictionary+MTLMappingAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+MTLMappingAdditions.h"; path = "Mantle/NSDictionary+MTLMappingAdditions.h"; sourceTree = ""; }; + D5EC2ACE8C0A18E9E2B5C587 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D8108FE7235FAE2EEE1CE5DF /* YapDatabaseRelationshipEdge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseRelationshipEdge.h; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h; sourceTree = ""; }; + D8349CD6A6F4613205CF624B /* EXTADT.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTADT.m; path = extobjc/EXTADT.m; sourceTree = ""; }; + D95922659875A01BCE8989E1 /* YapDatabaseSearchResultsViewOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSearchResultsViewOptions.m; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.m; sourceTree = ""; }; + DB5C5B70EFD40704327DECE6 /* YapDatabaseSearchResultsView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseSearchResultsView.m; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m; sourceTree = ""; }; + DB980FE9DC5711F4CC4349BF /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; + DC0015D5E11C9591C68C2AA7 /* YapDatabaseSearchQueuePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseSearchQueuePrivate.h; path = YapDatabase/Extensions/SearchResults/YapDatabaseSearchQueuePrivate.h; sourceTree = ""; }; + DCD4A6C5292E0564A337B565 /* EXTSelectorChecking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTSelectorChecking.h; path = extobjc/EXTSelectorChecking.h; sourceTree = ""; }; + DCEFBC0DEE6FE796145D9AF3 /* fwd.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fwd.h; path = objc/PromiseKit/fwd.h; sourceTree = ""; }; + DD2F49D5AEA2B91936EAD1E5 /* NSInvocation+EXT.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSInvocation+EXT.m"; path = "extobjc/NSInvocation+EXT.m"; sourceTree = ""; }; + DD9A0A315A0B36136023FD43 /* YapDatabaseCloudKitOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKitOptions.h; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h; sourceTree = ""; }; + DF83E6C94BE5FD19AB02262B /* NSSet+ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSSet+ObjectiveSugar.h"; path = "Classes/NSSet+ObjectiveSugar.h"; sourceTree = ""; }; + DF8AF42948EE367C3DFDA0E1 /* DDASLLogCapture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDASLLogCapture.h; path = Lumberjack/DDASLLogCapture.h; sourceTree = ""; }; + E042680B20E99E3C221FED3E /* OMGHTTPURLRQ.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = OMGHTTPURLRQ.h; sourceTree = ""; }; + E073214A9A7DC5BC597ED2F1 /* YapDatabaseLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseLogging.h; path = YapDatabase/Internal/YapDatabaseLogging.h; sourceTree = ""; }; + E16C596FFE0E449301226A52 /* DDFileLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDFileLogger.m; path = Lumberjack/DDFileLogger.m; sourceTree = ""; }; + E20BADCCAA8F64DB60774F87 /* Pods-YapDatabase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-YapDatabase-dummy.m"; sourceTree = ""; }; + E230DC4FA65315271DA3601E /* NSDictionary+MTLManipulationAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+MTLManipulationAdditions.h"; path = "Mantle/NSDictionary+MTLManipulationAdditions.h"; sourceTree = ""; }; + E43DE8999BF4FEEA046D05A9 /* YapDatabaseTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseTransaction.m; path = YapDatabase/YapDatabaseTransaction.m; sourceTree = ""; }; + E50E84F705DE194A41EA38DE /* ObjectiveSugar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ObjectiveSugar.h; path = Classes/ObjectiveSugar.h; sourceTree = ""; }; + EA1A2E1B2C1E611466CFF1DB /* UIView+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+PromiseKit.m"; path = "objc/UIView+PromiseKit.m"; sourceTree = ""; }; + EABFEAAD63289AD2E1AA81BD /* YapDatabaseCloudKitPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKitPrivate.h; path = YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h; sourceTree = ""; }; + EC5FE41A058526C6C1557CF5 /* Pods-CocoaLumberjack-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CocoaLumberjack-Private.xcconfig"; sourceTree = ""; }; + ED15F5B699FE176B7729CC00 /* MTLModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MTLModel.h; path = Mantle/MTLModel.h; sourceTree = ""; }; + ED16D47F7169C69FA2BFFA30 /* YDBCKChangeQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YDBCKChangeQueue.m; path = YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.m; sourceTree = ""; }; + EE06B170D6BCA9859F133BB4 /* YapDatabaseConnectionState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseConnectionState.m; path = YapDatabase/Internal/YapDatabaseConnectionState.m; sourceTree = ""; }; + EEB461079D742E8FE80BB329 /* YapCollectionKey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapCollectionKey.h; path = YapDatabase/Utilities/YapCollectionKey.h; sourceTree = ""; }; + EEFA9F20CDC0489B9FF2158D /* YapDatabaseString.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseString.h; path = YapDatabase/Internal/YapDatabaseString.h; sourceTree = ""; }; + EF394EFE94FDB2680DF62AB7 /* DDMultiFormatter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DDMultiFormatter.h; path = Lumberjack/Extensions/DDMultiFormatter.h; sourceTree = ""; }; + EF678F55398F2D89F2D97986 /* YapMemoryTable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapMemoryTable.h; path = YapDatabase/Internal/YapMemoryTable.h; sourceTree = ""; }; + F021F69423C51843F2109D44 /* NSNumber+ObjectiveSugar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+ObjectiveSugar.m"; path = "Classes/NSNumber+ObjectiveSugar.m"; sourceTree = ""; }; + F0FFEFCB3225AC4CDE931ED9 /* libPods-libextobjc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-libextobjc.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F160F516AD512BB070334E13 /* UIViewController+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+PromiseKit.m"; path = "objc/UIViewController+PromiseKit.m"; sourceTree = ""; }; + F57D33BA17461FC4DB2C4AB1 /* extobjc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = extobjc.h; path = extobjc/extobjc.h; sourceTree = ""; }; + F94C4590C2F189B9D882194F /* Pods-Mantle-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Mantle-prefix.pch"; sourceTree = ""; }; + F9773BADAD3556EA01724E5F /* NSURLConnection+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLConnection+PromiseKit.m"; path = "objc/NSURLConnection+PromiseKit.m"; sourceTree = ""; }; + F97E9F7A318BA0BF7B1AD3A9 /* PMKPromise+Until.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "PMKPromise+Until.m"; path = "objc/PMKPromise+Until.m"; sourceTree = ""; }; + F9977C177F49A8D6C9267A1D /* MTLJSONAdapter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MTLJSONAdapter.m; path = Mantle/MTLJSONAdapter.m; sourceTree = ""; }; + F9E49E2C555599D386E94FF3 /* Pods-Mantle.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Mantle.xcconfig"; sourceTree = ""; }; + FA99FEC920D17A9370A874D7 /* YapDatabaseViewRangeOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewRangeOptions.h; path = YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h; sourceTree = ""; }; + FAC35DBF6201D9E6F7B9B9FE /* OMGUserAgent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = OMGUserAgent.m; sourceTree = ""; }; + FAFE656C1735CF984B4A9516 /* YapRowidSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapRowidSet.h; path = YapDatabase/Internal/YapRowidSet.h; sourceTree = ""; }; + FB4B5DC70A6F71F7C3B16EAF /* YapDatabaseViewOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseViewOptions.h; path = YapDatabase/Extensions/Views/YapDatabaseViewOptions.h; sourceTree = ""; }; + FB51289DDF2BAD578C69E3F6 /* YapDatabaseFilteredViewPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseFilteredViewPrivate.h; path = YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h; sourceTree = ""; }; + FD04BEC7D7D5EDE1A95CFCF2 /* EXTNil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTNil.h; path = extobjc/EXTNil.h; sourceTree = ""; }; + FEA9C7F2213B4A18CE3F8A55 /* DDASLLogCapture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DDASLLogCapture.m; path = Lumberjack/DDASLLogCapture.m; sourceTree = ""; }; + FECDD433E148BAC9E1BBE7A8 /* YapDatabaseCloudKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseCloudKit.m; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.m; sourceTree = ""; }; + FF60FCF23C64B8EF6290248E /* YapDatabaseViewOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseViewOptions.m; path = YapDatabase/Extensions/Views/YapDatabaseViewOptions.m; sourceTree = ""; }; + FF6A683D10BDE0CB84F70833 /* NSArray+MTLManipulationAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MTLManipulationAdditions.h"; path = "Mantle/NSArray+MTLManipulationAdditions.h"; sourceTree = ""; }; + FFA6E7BBD7D253B6A47ADF7D /* UIAlertView+PromiseKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIAlertView+PromiseKit.m"; path = "objc/UIAlertView+PromiseKit.m"; sourceTree = ""; }; + FFD617C1BF003FEBB8A82BB5 /* YapDatabaseRelationshipOptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapDatabaseRelationshipOptions.m; path = YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.m; sourceTree = ""; }; + FFEBD2CAE1209534AD2A0251 /* YapMemoryTable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YapMemoryTable.m; path = YapDatabase/Internal/YapMemoryTable.m; sourceTree = ""; }; + FFF5D3C4F49EC8EE45F09176 /* YapDatabaseCloudKitConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YapDatabaseCloudKitConnection.h; path = YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 07BA57F619E6995B6FF41FCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EB7C2A2DAEFA3E68DD0C2DE5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 50EF8235C660795300D3C750 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 077E9EFBDBD7687F5C6A7E0F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5907F8DEB1C3AADFE58A64DB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BFB2DEEDF3C96A2FC04A30FC /* Foundation.framework in Frameworks */, + 9CF68E180A865E8B0551E0B9 /* QuartzCore.framework in Frameworks */, + CB1455E6616C518CA27ECF00 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 605F016960980B15B666F00B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B94A1A9C9E64EEBC0E0FB791 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7F8DDB4F5A15193E98B3AE9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68D08FF487884CFAA1B161EC /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 99586F1B341DFD410CA72329 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D8986D3C20BAED95DCBAB2CA /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB960CBED6D636F4558EB79F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F82FC88A9C51D8697433452 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F44EE40154153E69CC172EFE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 50F0D59E8B1F556AA1EBA75B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 129A50DF2D5C73BA61120049 /* Pods */ = { + isa = PBXGroup; + children = ( + 228E02EF08814AEEEBB4402F /* CocoaLumberjack */, + 73967CEDB63B7B96F6C97171 /* Mantle */, + B55FE904DF16347B2CCF08D9 /* OMGHTTPURLRQ */, + 98D87F078312B8A2D799CD06 /* ObjectiveSugar */, + 8232B3F9374E16FAD26ADA6C /* PromiseKit */, + E77BC3004709522231B9A3A7 /* YapDatabase */, + F94C6298F4350625D74DEC55 /* libextobjc */, + ); + name = Pods; + sourceTree = ""; + }; + 197710253A473BCEDEEA045D /* EXTKeyPathCoding */ = { + isa = PBXGroup; + children = ( + 4229D06614BF85161F7F48C7 /* EXTKeyPathCoding.h */, + ); + name = EXTKeyPathCoding; + sourceTree = ""; + }; + 228E02EF08814AEEEBB4402F /* CocoaLumberjack */ = { + isa = PBXGroup; + children = ( + 66B4EFE713C1C64D2F90149D /* Core */, + B76FC93E405A2239B749E365 /* Extensions */, + 3C1D764F9AE6797FE2E0FF29 /* Support Files */, + ); + path = CocoaLumberjack; + sourceTree = ""; + }; + 23444A35BA3865636D8C53FD /* Promise */ = { + isa = PBXGroup; + children = ( + 71A8A06E2320693C3558C7E8 /* PMKPromise.m */, + BD5933E272E6EE292E0C33D2 /* Promise.h */, + D050EB04C9B56801B320C98D /* PromiseKit.h */, + DCEFBC0DEE6FE796145D9AF3 /* fwd.h */, + ); + name = Promise; + sourceTree = ""; + }; + 2530F16707A39B9D978B568C /* Support Files */ = { + isa = PBXGroup; + children = ( + 1FAD246F6E917E2633C2F061 /* Pods-libextobjc.xcconfig */, + A3E9E153CBCF907078D67591 /* Pods-libextobjc-Private.xcconfig */, + 60FF2CB42F2E55822A549982 /* Pods-libextobjc-dummy.m */, + AE9C02BF613830CC309CAA26 /* Pods-libextobjc-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-libextobjc"; + sourceTree = ""; + }; + 26BA8D3FBD606C102457F80D /* Support Files */ = { + isa = PBXGroup; + children = ( + F9E49E2C555599D386E94FF3 /* Pods-Mantle.xcconfig */, + 9CD32733E73D6D9420AB496F /* Pods-Mantle-Private.xcconfig */, + 61528B964E0994D2C3A334E7 /* Pods-Mantle-dummy.m */, + F94C4590C2F189B9D882194F /* Pods-Mantle-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-Mantle"; + sourceTree = ""; + }; + 2DDEABEFA4E29C8617DC1E9D /* Support Files */ = { + isa = PBXGroup; + children = ( + 58D8A9E45BDA2141FC71B1B0 /* Pods-ObjectiveSugar.xcconfig */, + 94B5688717AC26757392BD42 /* Pods-ObjectiveSugar-Private.xcconfig */, + 778E2A549A19B203BD56900E /* Pods-ObjectiveSugar-dummy.m */, + AA1BCDAB7233FEBA142D9EA5 /* Pods-ObjectiveSugar-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-ObjectiveSugar"; + sourceTree = ""; + }; + 2EF157D06A207BCF3F34C94B /* CALayer */ = { + isa = PBXGroup; + children = ( + BB818DCDEC16DC09B5A61EDE /* CALayer+PromiseKit.h */, + 732387C0A0D8F6315DBAF1D3 /* CALayer+PromiseKit.m */, + ); + name = CALayer; + sourceTree = ""; + }; + 31FE578ADB933F9C0E6AE6C1 /* EXTConcreteProtocol */ = { + isa = PBXGroup; + children = ( + 616BB0FF4165B82C982B5941 /* EXTConcreteProtocol.h */, + 6FC150542EEEF84BA2377171 /* EXTConcreteProtocol.m */, + ); + name = EXTConcreteProtocol; + sourceTree = ""; + }; + 3A575A4CC5F646C90AE59401 /* Support Files */ = { + isa = PBXGroup; + children = ( + 41D6C93E8EAFA752B9501ADA /* Pods-YapDatabase.xcconfig */, + B34E3A4413395661C93D46D6 /* Pods-YapDatabase-Private.xcconfig */, + E20BADCCAA8F64DB60774F87 /* Pods-YapDatabase-dummy.m */, + CE26A56044F7DE04692327A4 /* Pods-YapDatabase-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-YapDatabase"; + sourceTree = ""; + }; + 3C1D764F9AE6797FE2E0FF29 /* Support Files */ = { + isa = PBXGroup; + children = ( + 29FD34E6503B42BB4D26ACEE /* Pods-CocoaLumberjack.xcconfig */, + EC5FE41A058526C6C1557CF5 /* Pods-CocoaLumberjack-Private.xcconfig */, + 7B1E4A2F5A4BA3D56C11C31C /* Pods-CocoaLumberjack-dummy.m */, + 64CF785843553EDFA9975F03 /* Pods-CocoaLumberjack-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-CocoaLumberjack"; + sourceTree = ""; + }; + 4369A685C7EA75C90E2C6158 /* RQ */ = { + isa = PBXGroup; + children = ( + E042680B20E99E3C221FED3E /* OMGHTTPURLRQ.h */, + B8C97625D995754F4AE5EE6F /* OMGHTTPURLRQ.m */, + ); + name = RQ; + sourceTree = ""; + }; + 445529437F87883F4B44E46E /* Pods */ = { + isa = PBXGroup; + children = ( + 40B2610168FCD43954EC68F3 /* Pods-acknowledgements.markdown */, + 20DAD4D7329DBAED28944D46 /* Pods-acknowledgements.plist */, + 35346DE23EDC71509A75E5DE /* Pods-dummy.m */, + 66B186B0967FA2758B671D03 /* Pods-environment.h */, + DB980FE9DC5711F4CC4349BF /* Pods-resources.sh */, + D1AADC7C1CF987010AA2DA67 /* Pods.debug.xcconfig */, + 0AB9D3ED0DF727B5B73580DB /* Pods.release.xcconfig */, + ); + name = Pods; + path = "Target Support Files/Pods"; + sourceTree = ""; + }; + 49CDBAD1E229662ACB81F85A /* NSMethodSignature+EXT */ = { + isa = PBXGroup; + children = ( + C9E904A284D521BF42978D21 /* NSMethodSignature+EXT.h */, + 795994EB10B914CB2F31B83A /* NSMethodSignature+EXT.m */, + ); + name = "NSMethodSignature+EXT"; + sourceTree = ""; + }; + 4CC267C09BF26CEB8381B4E5 = { + isa = PBXGroup; + children = ( + 034632FE082BA6B4D7AB738B /* Podfile */, + FB7FBED3BE8315A274BAED0D /* Frameworks */, + 129A50DF2D5C73BA61120049 /* Pods */, + C298FAA417022E57229C936B /* Products */, + CB5A0FBCC6C4D8B128E1FCD5 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 5986E34C39BF6666F575AC27 /* EXTNil */ = { + isa = PBXGroup; + children = ( + FD04BEC7D7D5EDE1A95CFCF2 /* EXTNil.h */, + 33B1FD5E0A1F71D2DB7A4045 /* EXTNil.m */, + ); + name = EXTNil; + sourceTree = ""; + }; + 66B4EFE713C1C64D2F90149D /* Core */ = { + isa = PBXGroup; + children = ( + DF8AF42948EE367C3DFDA0E1 /* DDASLLogCapture.h */, + FEA9C7F2213B4A18CE3F8A55 /* DDASLLogCapture.m */, + D0FC27303CBCF7820CB3BB28 /* DDASLLogger.h */, + 72FA3543C40DD98F78FFE366 /* DDASLLogger.m */, + 577A493742D1DA74DF6C6AAA /* DDAbstractDatabaseLogger.h */, + C51E606823DD7DB43CCBB8C7 /* DDAbstractDatabaseLogger.m */, + 049D3124EAC466F7E00E2BD6 /* DDAssert.h */, + 27F9E26F8907F5EC2CAD9A07 /* DDFileLogger.h */, + E16C596FFE0E449301226A52 /* DDFileLogger.m */, + 9F962B8C1B91A25E1C30259F /* DDLog.h */, + 4DFA6C642580CF27537C7EDD /* DDLog.m */, + 25C089DC8759A07EC36D0B4C /* DDLog+LOGV.h */, + A8CB40E31FA2BCF3D4969B04 /* DDTTYLogger.h */, + CB6117633CD7B0AB1B71A072 /* DDTTYLogger.m */, + ); + name = Core; + sourceTree = ""; + }; + 689643CE85BCDE849DD5CAC6 /* EXTSelectorChecking */ = { + isa = PBXGroup; + children = ( + DCD4A6C5292E0564A337B565 /* EXTSelectorChecking.h */, + 8BC7F01BF1D75D1AC8419FFD /* EXTSelectorChecking.m */, + ); + name = EXTSelectorChecking; + sourceTree = ""; + }; + 6A7567528A1118CB9CDC535F /* EXTSafeCategory */ = { + isa = PBXGroup; + children = ( + 5FA4CF3A513FC48B3E3C895E /* EXTSafeCategory.h */, + 5B694C964F3411D32D5D9EC2 /* EXTSafeCategory.m */, + ); + name = EXTSafeCategory; + sourceTree = ""; + }; + 6ACFEBAFBDAF962C5D97E336 /* NSURLConnection */ = { + isa = PBXGroup; + children = ( + AED02F4F608383988CF965A6 /* NSURLConnection+PromiseKit.h */, + F9773BADAD3556EA01724E5F /* NSURLConnection+PromiseKit.m */, + ); + name = NSURLConnection; + sourceTree = ""; + }; + 6C83FF2C5989EF0EED432ADE /* Pause */ = { + isa = PBXGroup; + children = ( + BC3DAE43EF1948EAF5E64008 /* PMKPromise+Pause.m */, + 2A68B32C08C79F754493B086 /* Promise+Pause.h */, + ); + name = Pause; + sourceTree = ""; + }; + 73967CEDB63B7B96F6C97171 /* Mantle */ = { + isa = PBXGroup; + children = ( + 6745BDF2258F0EE0BF5B53A7 /* MTLJSONAdapter.h */, + F9977C177F49A8D6C9267A1D /* MTLJSONAdapter.m */, + ED15F5B699FE176B7729CC00 /* MTLModel.h */, + 4839BB3BAB3CCBC31EF39119 /* MTLModel.m */, + 3C4461CD210B81105ECC94FC /* MTLModel+NSCoding.h */, + 34F575D8FB8F01EEA9B5FB73 /* MTLModel+NSCoding.m */, + 5D7CEC56A54507D0D1DCC634 /* MTLReflection.h */, + 6C066ABBBA534C1EDC86445C /* MTLReflection.m */, + A7D6AC69F457D3E6DA2DCC9F /* MTLTransformerErrorHandling.h */, + CCFFC1B673E45D3721E35415 /* MTLTransformerErrorHandling.m */, + AD8B953D651CD6C7EA93410E /* MTLValueTransformer.h */, + 541DA7760C886ECCB1EC99AB /* MTLValueTransformer.m */, + CFC6E09D40ED2E8330F67CE7 /* Mantle.h */, + FF6A683D10BDE0CB84F70833 /* NSArray+MTLManipulationAdditions.h */, + 26E8C4E20FEE3BD7F6380212 /* NSArray+MTLManipulationAdditions.m */, + 95F805B74D223F0D3DE1553E /* NSDictionary+MTLJSONKeyPath.h */, + 71ECE55FDBB496467636DD3F /* NSDictionary+MTLJSONKeyPath.m */, + E230DC4FA65315271DA3601E /* NSDictionary+MTLManipulationAdditions.h */, + 4B519CC3886D543D37537F70 /* NSDictionary+MTLManipulationAdditions.m */, + D39B0B478A264DAA4763EDC2 /* NSDictionary+MTLMappingAdditions.h */, + BC0AD0DB5BD3BAA7656F3FBD /* NSDictionary+MTLMappingAdditions.m */, + 444C3950B6EDC2FBAC84B5C2 /* NSError+MTLModelException.h */, + 222D48E9A414750043B5EEB9 /* NSError+MTLModelException.m */, + 7E95114A187326AA7BA09991 /* NSObject+MTLComparisonAdditions.h */, + 830EE70923D40F5010F65824 /* NSObject+MTLComparisonAdditions.m */, + 1AC11F7D627265A8501537E0 /* NSValueTransformer+MTLInversionAdditions.h */, + 770B7CEF5A6D7DFB055CD20A /* NSValueTransformer+MTLInversionAdditions.m */, + 89647C22295AF2D9F9B5D153 /* NSValueTransformer+MTLPredefinedTransformerAdditions.h */, + 3A02C304C29888E8EE28253C /* NSValueTransformer+MTLPredefinedTransformerAdditions.m */, + 26BA8D3FBD606C102457F80D /* Support Files */, + FA0D6E5BA4091B0AEF746B3A /* extobjc */, + ); + path = Mantle; + sourceTree = ""; + }; + 79001AEB7760A931CC579F39 /* UIAlertView */ = { + isa = PBXGroup; + children = ( + D0B475BD00954E981A913A48 /* UIAlertView+PromiseKit.h */, + FFA6E7BBD7D253B6A47ADF7D /* UIAlertView+PromiseKit.m */, + ); + name = UIAlertView; + sourceTree = ""; + }; + 8232B3F9374E16FAD26ADA6C /* PromiseKit */ = { + isa = PBXGroup; + children = ( + 2EF157D06A207BCF3F34C94B /* CALayer */, + D9C00804B89E4483381EF800 /* NSNotificationCenter */, + 6ACFEBAFBDAF962C5D97E336 /* NSURLConnection */, + 6C83FF2C5989EF0EED432ADE /* Pause */, + 23444A35BA3865636D8C53FD /* Promise */, + FB8CA06449C6CF0C5030B5CE /* Support Files */, + D2E301A6F88A308641544A72 /* UIActionSheet */, + 79001AEB7760A931CC579F39 /* UIAlertView */, + B6D57206BCB4AA3DA9265DC1 /* UIView */, + D35A6F5191E3CD2FF4A190F2 /* UIViewController */, + B77287EA88C044CAA7FE30EF /* Until */, + A21FBF4DA5DCCACAEF16D5EE /* When */, + ); + path = PromiseKit; + sourceTree = ""; + }; + 960EC9174CF39510AC2B08A4 /* Support Files */ = { + isa = PBXGroup; + children = ( + 30C27A01F64B94B091704EA6 /* Pods-OMGHTTPURLRQ.xcconfig */, + A9B880ED0C270A8EC1241DDA /* Pods-OMGHTTPURLRQ-Private.xcconfig */, + 2032AD6C5089FD9A73EDDF44 /* Pods-OMGHTTPURLRQ-dummy.m */, + 182E835896B42F7724C8001B /* Pods-OMGHTTPURLRQ-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-OMGHTTPURLRQ"; + sourceTree = ""; + }; + 98D87F078312B8A2D799CD06 /* ObjectiveSugar */ = { + isa = PBXGroup; + children = ( + 11F19D1CDEAD9AD4A38712ED /* NSArray+ObjectiveSugar.h */, + 7B2FF26957DCEF25790322C1 /* NSArray+ObjectiveSugar.m */, + 8E4958B4B7FEB79FBDA705DC /* NSDictionary+ObjectiveSugar.h */, + 70B155987EF346BEFBB2939E /* NSDictionary+ObjectiveSugar.m */, + A8ECA6A42B04B8DC8E455BBA /* NSMutableArray+ObjectiveSugar.h */, + 4FDCA048BC2592BD999C2325 /* NSMutableArray+ObjectiveSugar.m */, + AE3F13BF8B794B85DA895839 /* NSNumber+ObjectiveSugar.h */, + F021F69423C51843F2109D44 /* NSNumber+ObjectiveSugar.m */, + DF83E6C94BE5FD19AB02262B /* NSSet+ObjectiveSugar.h */, + 018D2A00C7370E47231AE5F2 /* NSSet+ObjectiveSugar.m */, + CD2D886B75F95E1E60330FE0 /* NSString+ObjectiveSugar.h */, + 1C6983E041AC3DD0A39EA289 /* NSString+ObjectiveSugar.m */, + E50E84F705DE194A41EA38DE /* ObjectiveSugar.h */, + 2DDEABEFA4E29C8617DC1E9D /* Support Files */, + ); + path = ObjectiveSugar; + sourceTree = ""; + }; + A21FBF4DA5DCCACAEF16D5EE /* When */ = { + isa = PBXGroup; + children = ( + A02712AC709105E1BA43665D /* PMKPromise+When.m */, + 7FC0141166A22391CD8D2BB1 /* Promise+When.h */, + ); + name = When; + sourceTree = ""; + }; + A30C79677BB33966911F11E3 /* EXTADT */ = { + isa = PBXGroup; + children = ( + 6ACF347FE23C879FFC4FBDC1 /* EXTADT.h */, + D8349CD6A6F4613205CF624B /* EXTADT.m */, + ); + name = EXTADT; + sourceTree = ""; + }; + B55FE904DF16347B2CCF08D9 /* OMGHTTPURLRQ */ = { + isa = PBXGroup; + children = ( + FC057C84507BD628E2892BB7 /* FormURLEncode */, + 4369A685C7EA75C90E2C6158 /* RQ */, + 960EC9174CF39510AC2B08A4 /* Support Files */, + F91988D750BF5197173957A9 /* UserAgent */, + ); + path = OMGHTTPURLRQ; + sourceTree = ""; + }; + B6D57206BCB4AA3DA9265DC1 /* UIView */ = { + isa = PBXGroup; + children = ( + 064D0A7D2038C6CB7E1EBC6C /* UIView+PromiseKit.h */, + EA1A2E1B2C1E611466CFF1DB /* UIView+PromiseKit.m */, + ); + name = UIView; + sourceTree = ""; + }; + B76FC93E405A2239B749E365 /* Extensions */ = { + isa = PBXGroup; + children = ( + A671BA931388ADC453431004 /* DDContextFilterLogFormatter.h */, + 93BF383308911708C6C3AF52 /* DDContextFilterLogFormatter.m */, + 2F68FA0FF71257A9C104D900 /* DDDispatchQueueLogFormatter.h */, + C6CADBA06D2B54D61C13071C /* DDDispatchQueueLogFormatter.m */, + EF394EFE94FDB2680DF62AB7 /* DDMultiFormatter.h */, + C7C2B0FD8C079D1AF8754E7A /* DDMultiFormatter.m */, + ); + name = Extensions; + sourceTree = ""; + }; + B77287EA88C044CAA7FE30EF /* Until */ = { + isa = PBXGroup; + children = ( + F97E9F7A318BA0BF7B1AD3A9 /* PMKPromise+Until.m */, + A83DC410265F0E8DBE0471E4 /* Promise+Until.h */, + ); + name = Until; + sourceTree = ""; + }; + BC928FF99557E36D3241A52B /* RuntimeExtensions */ = { + isa = PBXGroup; + children = ( + 3E937AE3A1C38D8F54C36561 /* EXTRuntimeExtensions.h */, + 0D234E2C31DEA86899A7B1FE /* EXTRuntimeExtensions.m */, + 39C01323D5C51429E51640C2 /* metamacros.h */, + ); + name = RuntimeExtensions; + sourceTree = ""; + }; + C298FAA417022E57229C936B /* Products */ = { + isa = PBXGroup; + children = ( + D5EC2ACE8C0A18E9E2B5C587 /* libPods.a */, + 98E1245800E1ED8EBFE5CAF4 /* libPods-CocoaLumberjack.a */, + 54F2BBA18BAA51ECCE2A1EB1 /* libPods-Mantle.a */, + 86ADEBF61A25C443E7790CC4 /* libPods-OMGHTTPURLRQ.a */, + 6B9B4F309426DA09B38A7B98 /* libPods-ObjectiveSugar.a */, + B7E184741559D494AB0E33F1 /* libPods-PromiseKit.a */, + 91805095FBEE932AED95AE42 /* libPods-YapDatabase.a */, + F0FFEFCB3225AC4CDE931ED9 /* libPods-libextobjc.a */, + ); + name = Products; + sourceTree = ""; + }; + CB5A0FBCC6C4D8B128E1FCD5 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 445529437F87883F4B44E46E /* Pods */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + D2B9308C50B8B3E00E504332 /* EXTSynthesize */ = { + isa = PBXGroup; + children = ( + 97AAD29F3E667A7A2828E22B /* EXTSynthesize.h */, + ); + name = EXTSynthesize; + sourceTree = ""; + }; + D2E301A6F88A308641544A72 /* UIActionSheet */ = { + isa = PBXGroup; + children = ( + AA24F676352AFA0EE4E5E113 /* UIActionSheet+PromiseKit.h */, + 23282A3CA1331D9C53DF3FF1 /* UIActionSheet+PromiseKit.m */, + ); + name = UIActionSheet; + sourceTree = ""; + }; + D35A6F5191E3CD2FF4A190F2 /* UIViewController */ = { + isa = PBXGroup; + children = ( + AB58F107E5A70A31EDE1BEEC /* UIViewController+PromiseKit.h */, + F160F516AD512BB070334E13 /* UIViewController+PromiseKit.m */, + ); + name = UIViewController; + sourceTree = ""; + }; + D3E81B6B2A5EB45056699C69 /* UmbrellaHeader */ = { + isa = PBXGroup; + children = ( + F57D33BA17461FC4DB2C4AB1 /* extobjc.h */, + ); + name = UmbrellaHeader; + sourceTree = ""; + }; + D9C00804B89E4483381EF800 /* NSNotificationCenter */ = { + isa = PBXGroup; + children = ( + AFBE7B841ADBD0B4A2D385B1 /* NSNotificationCenter+PromiseKit.h */, + B3A2A2E5887D2D5AF3E69C10 /* NSNotificationCenter+PromiseKit.m */, + ); + name = NSNotificationCenter; + sourceTree = ""; + }; + E53C4CFBF9387FE98C64BE6D /* iOS */ = { + isa = PBXGroup; + children = ( + 80D8C05C2F6B81E4B10FBFE4 /* Foundation.framework */, + 73DB40B55180C8778EA99A63 /* QuartzCore.framework */, + 3E41BD2B6A96B44D0E2F4D55 /* UIKit.framework */, + ); + name = iOS; + sourceTree = ""; + }; + E77BC3004709522231B9A3A7 /* YapDatabase */ = { + isa = PBXGroup; + children = ( + 3A575A4CC5F646C90AE59401 /* Support Files */, + F27AF0765A190E31D80CFA7A /* common */, + ); + path = YapDatabase; + sourceTree = ""; + }; + F27AF0765A190E31D80CFA7A /* common */ = { + isa = PBXGroup; + children = ( + 970633A6ABE21363DF9813AF /* NSDictionary+YapDatabase.h */, + 19353E5667112CED32A168BB /* NSDictionary+YapDatabase.m */, + 85813705029C3A752DAAA823 /* YDBCKAttachRequest.h */, + 809BE5D35DC3541EDB1ACB91 /* YDBCKAttachRequest.m */, + 6A426400B271E4AE2F1E7146 /* YDBCKChangeQueue.h */, + ED16D47F7169C69FA2BFFA30 /* YDBCKChangeQueue.m */, + 211B08E1BDD2F7526B0AAEB4 /* YDBCKChangeRecord.h */, + AA88F3716FC4CE4FD628976C /* YDBCKChangeRecord.m */, + 0C50655820BA698DB18E8A99 /* YDBCKChangeSet.h */, + D069C5A6EC306BF8CCE9612C /* YDBCKChangeSet.m */, + 585D8F58416862E30CE2100F /* YDBCKMappingTableInfo.h */, + 4AB0046D4F29BA14814F660A /* YDBCKMappingTableInfo.m */, + 27A2C2877B14E2EE162AAF38 /* YDBCKMergeInfo.h */, + 0F5AD2E9FF3381CF0FE741B0 /* YDBCKMergeInfo.m */, + 464FC042B0B8068F9A293A27 /* YDBCKRecord.h */, + A71F955B195FFE8D69ADC4F9 /* YDBCKRecord.m */, + B092F4D0C3CAAC4D348EC697 /* YDBCKRecordInfo.h */, + A46AAB95061CCCB8512B8503 /* YDBCKRecordInfo.m */, + B71EBDA84B94423D9E8B36AB /* YDBCKRecordTableInfo.h */, + 0F3D7ED2DD5AD411AC38F359 /* YDBCKRecordTableInfo.m */, + BA66D04CD4554C01ABA3949C /* YapCache.h */, + AEAD70039FEB949F6DC9BA17 /* YapCache.m */, + EEB461079D742E8FE80BB329 /* YapCollectionKey.h */, + CFAA6AF9DE36D35243D46812 /* YapCollectionKey.m */, + CFC0CF29EC6CCF29E933FEBB /* YapDatabase.h */, + AFAF5CC21626A29058A71E0C /* YapDatabase.m */, + 9E335488B287C642F39B76F3 /* YapDatabaseCloudKit.h */, + FECDD433E148BAC9E1BBE7A8 /* YapDatabaseCloudKit.m */, + FFF5D3C4F49EC8EE45F09176 /* YapDatabaseCloudKitConnection.h */, + 1C8D2AB466E5562F39FEE98F /* YapDatabaseCloudKitConnection.m */, + DD9A0A315A0B36136023FD43 /* YapDatabaseCloudKitOptions.h */, + 9E4FD4043D7983E6AB586A3C /* YapDatabaseCloudKitOptions.m */, + EABFEAAD63289AD2E1AA81BD /* YapDatabaseCloudKitPrivate.h */, + 0B9AA3E91E5A87CCA6AF7284 /* YapDatabaseCloudKitTransaction.h */, + 0F414F2FC7D7CA984E53B55F /* YapDatabaseCloudKitTransaction.m */, + 8C1492C96B48F61928F7462D /* YapDatabaseCloudKitTypes.h */, + 6B1302321474738DE34D18DB /* YapDatabaseCloudKitTypes.m */, + 93F145A9750D2071E0D4A645 /* YapDatabaseConnection.h */, + 4CC3E2156A7035060FBB2EE5 /* YapDatabaseConnection.m */, + C44404C283CAF8E032AEDB52 /* YapDatabaseConnectionDefaults.h */, + 378C78B55BAF1450A166FE22 /* YapDatabaseConnectionDefaults.m */, + 398BECB6C509128711E47373 /* YapDatabaseConnectionState.h */, + EE06B170D6BCA9859F133BB4 /* YapDatabaseConnectionState.m */, + B415C757C56A094013194D6E /* YapDatabaseExtension.h */, + 34C3355E49A449E3E8F15D2D /* YapDatabaseExtension.m */, + 3BC09E8B3BF40806984238AC /* YapDatabaseExtensionConnection.h */, + 530930E2366691003A28ACAF /* YapDatabaseExtensionConnection.m */, + 67F6547022896E78B73719EF /* YapDatabaseExtensionPrivate.h */, + C4ABC1EBCD8F9E06FD6243E7 /* YapDatabaseExtensionTransaction.h */, + 943A8CD7E9EC1F2C119EE2C5 /* YapDatabaseExtensionTransaction.m */, + 0D197FE7E9E115C89105C2E3 /* YapDatabaseFilteredView.h */, + AD9AD9B49306A606929CAAFC /* YapDatabaseFilteredView.m */, + 3B8840AA2ECE263DC2B6A9F2 /* YapDatabaseFilteredViewConnection.h */, + BA3462E14B9773EC92BD216B /* YapDatabaseFilteredViewConnection.m */, + FB51289DDF2BAD578C69E3F6 /* YapDatabaseFilteredViewPrivate.h */, + 218711E1E3AE0EA758602433 /* YapDatabaseFilteredViewTransaction.h */, + C31C2AF8C504FA21C67B4EE3 /* YapDatabaseFilteredViewTransaction.m */, + A41CA1721495E7E3164F977A /* YapDatabaseFilteredViewTypes.h */, + 3499CC9633BF0107142AAE36 /* YapDatabaseFilteredViewTypes.m */, + 36418C93011B28E4AC39E948 /* YapDatabaseFullTextSearch.h */, + 259759D2C4E16388FB517936 /* YapDatabaseFullTextSearch.m */, + BE4B631F0770A1B7F464F804 /* YapDatabaseFullTextSearchConnection.h */, + 39F8894C5EDD6E45A1385724 /* YapDatabaseFullTextSearchConnection.m */, + C8F3F9C00DDE31A157431155 /* YapDatabaseFullTextSearchHandler.h */, + 0D2E28323CE037741F10AA76 /* YapDatabaseFullTextSearchHandler.m */, + 6D61580AF99C69E38468A202 /* YapDatabaseFullTextSearchPrivate.h */, + 1CD021900F80A892574D6222 /* YapDatabaseFullTextSearchSnippetOptions.h */, + B330F7267B36FCBC2B00C4D9 /* YapDatabaseFullTextSearchSnippetOptions.m */, + 9520DCD299B21CD83BACE4DC /* YapDatabaseFullTextSearchTransaction.h */, + 7E339181D39B266DEC53CB0A /* YapDatabaseFullTextSearchTransaction.m */, + E073214A9A7DC5BC597ED2F1 /* YapDatabaseLogging.h */, + CD7DB3EBE1757C105BE9E7E7 /* YapDatabaseLogging.m */, + AFA93482F18061D8E55B3DA2 /* YapDatabaseManager.h */, + 0F140FD12DD2636983491D18 /* YapDatabaseManager.m */, + 429C432EB6FFB1AB160E76C9 /* YapDatabaseOptions.h */, + 79E22E305BB172B57A1F6AF3 /* YapDatabaseOptions.m */, + 9567AFFFCF159BC18CDBF250 /* YapDatabasePrivate.h */, + 42793E8D5EF5F74F75C7133F /* YapDatabaseQuery.h */, + 3C344EF728288071F760BF91 /* YapDatabaseQuery.m */, + 98B7FAB5222CAEB7B6DAF34A /* YapDatabaseRelationship.h */, + 9AD8F53ED5F94F041D9D9C2A /* YapDatabaseRelationship.m */, + 37346860615993B6D14B1505 /* YapDatabaseRelationshipConnection.h */, + 298061D94C1747D18EBF1870 /* YapDatabaseRelationshipConnection.m */, + D8108FE7235FAE2EEE1CE5DF /* YapDatabaseRelationshipEdge.h */, + 76AD8ACB921EB83B9EBDCECC /* YapDatabaseRelationshipEdge.m */, + A2DBD6EA6A916BB7D81BEE42 /* YapDatabaseRelationshipEdgePrivate.h */, + BC24886A724046A2EEA0527E /* YapDatabaseRelationshipNode.h */, + 6ADAC96C5DC5F8CE2CB91988 /* YapDatabaseRelationshipOptions.h */, + FFD617C1BF003FEBB8A82BB5 /* YapDatabaseRelationshipOptions.m */, + 94DFECAD768B873113696B9B /* YapDatabaseRelationshipPrivate.h */, + AF2A25E60330846D1464678E /* YapDatabaseRelationshipTransaction.h */, + 677E3D165351EDADAF1DEAE4 /* YapDatabaseRelationshipTransaction.m */, + BAB7AB561FFF8CAABE6A213A /* YapDatabaseSearchQueue.h */, + 2C3A85525F0A958E165E21AA /* YapDatabaseSearchQueue.m */, + DC0015D5E11C9591C68C2AA7 /* YapDatabaseSearchQueuePrivate.h */, + 623746D45AD677CE15DD7DBA /* YapDatabaseSearchResultsView.h */, + DB5C5B70EFD40704327DECE6 /* YapDatabaseSearchResultsView.m */, + 91623C099DB8425107F8C2A7 /* YapDatabaseSearchResultsViewConnection.h */, + D1908C0156D655B271509DCA /* YapDatabaseSearchResultsViewConnection.m */, + AEB46BFD29DE0CD4B7B7A2D6 /* YapDatabaseSearchResultsViewOptions.h */, + D95922659875A01BCE8989E1 /* YapDatabaseSearchResultsViewOptions.m */, + 527F3FADF3DEFEFE19A40983 /* YapDatabaseSearchResultsViewPrivate.h */, + 54E67BE54B3CD69F000E68C7 /* YapDatabaseSearchResultsViewTransaction.h */, + 898D88518E8A1A7C30C8103D /* YapDatabaseSearchResultsViewTransaction.m */, + 9BBF307A557D3D6A6544AF4D /* YapDatabaseSecondaryIndex.h */, + 4DB9E346F37D09E97D5D5024 /* YapDatabaseSecondaryIndex.m */, + 3059BC2BFD3E0EE14EDA3EE7 /* YapDatabaseSecondaryIndexConnection.h */, + A7D12C82CEB238FC89F09433 /* YapDatabaseSecondaryIndexConnection.m */, + 25EC6BCE4F2BB316485DAA8A /* YapDatabaseSecondaryIndexHandler.h */, + 1519F9E1F9A5DDF901485673 /* YapDatabaseSecondaryIndexHandler.m */, + 73B8ADEDB723845FE9063E19 /* YapDatabaseSecondaryIndexOptions.h */, + BD0EF077399E6D5896F6D8AA /* YapDatabaseSecondaryIndexOptions.m */, + 4E9F1BE2295DAEA08798E24E /* YapDatabaseSecondaryIndexPrivate.h */, + 3C452CCD477CB75D3ADD2088 /* YapDatabaseSecondaryIndexSetup.h */, + 140240C25099B9B13AE8B6B6 /* YapDatabaseSecondaryIndexSetup.m */, + 8F1D142C290D595F81684139 /* YapDatabaseSecondaryIndexTransaction.h */, + 8A3CD76CF089F0B4A4DC05AA /* YapDatabaseSecondaryIndexTransaction.m */, + D01C6F97895048507253C51C /* YapDatabaseStatement.h */, + D2607C43CFBEE80910AF795A /* YapDatabaseStatement.m */, + EEFA9F20CDC0489B9FF2158D /* YapDatabaseString.h */, + 191AFE1651E58C5183D5EABA /* YapDatabaseTransaction.h */, + E43DE8999BF4FEEA046D05A9 /* YapDatabaseTransaction.m */, + 1F74B7ED8EA6675A3DAA5CC3 /* YapDatabaseView.h */, + 78B7E7E3E3CEABD424391473 /* YapDatabaseView.m */, + 8B68E345C0E2426890E84E1E /* YapDatabaseViewChange.h */, + 40ED6D2073FAD88CA34560E3 /* YapDatabaseViewChange.m */, + CB479279231C151A4E1D042C /* YapDatabaseViewChangePrivate.h */, + 233C073F00562E346946CA48 /* YapDatabaseViewConnection.h */, + B82A9311028BB8DA6159BE61 /* YapDatabaseViewConnection.m */, + 7C77183C79552BA6C6AEE24E /* YapDatabaseViewMappings.h */, + 9B1ABD2D7F4C73197567A415 /* YapDatabaseViewMappings.m */, + 226FAD15C67A80534E8DE2AE /* YapDatabaseViewMappingsPrivate.h */, + FB4B5DC70A6F71F7C3B16EAF /* YapDatabaseViewOptions.h */, + FF60FCF23C64B8EF6290248E /* YapDatabaseViewOptions.m */, + 66C2267BED53B5F74B3EBE9E /* YapDatabaseViewPage.h */, + 0B87635AC4B8480F62651CC0 /* YapDatabaseViewPage.mm */, + CDCE72E9834C7D87E07EA4B1 /* YapDatabaseViewPageMetadata.h */, + 16243F2180E149B4291CEE82 /* YapDatabaseViewPageMetadata.m */, + 693340475AB3A927BE818376 /* YapDatabaseViewPrivate.h */, + FA99FEC920D17A9370A874D7 /* YapDatabaseViewRangeOptions.h */, + B3C9B9343E48BB7331BF0575 /* YapDatabaseViewRangeOptions.m */, + 30BD8CBD2DE257ACAB7C0146 /* YapDatabaseViewRangeOptionsPrivate.h */, + 67BC595E9ADC903AD5B1CAB9 /* YapDatabaseViewState.h */, + 92DE0398808EE3044BC02BFD /* YapDatabaseViewState.m */, + A0DDA08FE302923759EFC65E /* YapDatabaseViewTransaction.h */, + 8360EDC84E469FDFDEA2A793 /* YapDatabaseViewTransaction.m */, + 27901D26FCE7CDD78108D550 /* YapDatabaseViewTypes.h */, + 77EBF2AB82C5E726D5955557 /* YapDatabaseViewTypes.m */, + 15EA72C163D28F9D21EBBD64 /* YapDebugDictionary.h */, + B34A73D81E2AE3A69CD60A07 /* YapDebugDictionary.m */, + EF678F55398F2D89F2D97986 /* YapMemoryTable.h */, + FFEBD2CAE1209534AD2A0251 /* YapMemoryTable.m */, + 82904272BA8DC583C6A88AB1 /* YapMurmurHash.h */, + 379D651A460DC2A8298ACD8D /* YapMurmurHash.m */, + 3E3737AAE040ED9E09378C4F /* YapNull.h */, + 92A6B214E8BAE20E7830EBF6 /* YapNull.m */, + FAFE656C1735CF984B4A9516 /* YapRowidSet.h */, + 73983E145C98E81D85997F3A /* YapRowidSet.mm */, + 3D7A32C19352D308D89ACCA2 /* YapSet.h */, + 7B27EF2C3C4ECD3BA8BDACC7 /* YapSet.m */, + 9655DCE99DB0497C2C6CB5FF /* YapTouch.h */, + 33B922ACEFD8FB2BC4833A1D /* YapTouch.m */, + 84FEF2E7E1C06B94B65F0037 /* YapWhitelistBlacklist.h */, + 41A73849DF4E74AB878B0CD3 /* YapWhitelistBlacklist.m */, + ); + name = common; + sourceTree = ""; + }; + F81829AEBF796ED1E3975450 /* NSInvocation+EXT */ = { + isa = PBXGroup; + children = ( + 873B2AE9D57CDC68F478BB68 /* NSInvocation+EXT.h */, + DD2F49D5AEA2B91936EAD1E5 /* NSInvocation+EXT.m */, + ); + name = "NSInvocation+EXT"; + sourceTree = ""; + }; + F91988D750BF5197173957A9 /* UserAgent */ = { + isa = PBXGroup; + children = ( + 0F3C36EC425C070650072F69 /* OMGUserAgent.h */, + FAC35DBF6201D9E6F7B9B9FE /* OMGUserAgent.m */, + ); + name = UserAgent; + sourceTree = ""; + }; + F92CF05BC048EBC88B194D62 /* EXTScope */ = { + isa = PBXGroup; + children = ( + 28843410D09F64380AAABB4C /* EXTScope.h */, + 1C215D33080B3C56403E86D1 /* EXTScope.m */, + ); + name = EXTScope; + sourceTree = ""; + }; + F94C6298F4350625D74DEC55 /* libextobjc */ = { + isa = PBXGroup; + children = ( + A30C79677BB33966911F11E3 /* EXTADT */, + 31FE578ADB933F9C0E6AE6C1 /* EXTConcreteProtocol */, + 197710253A473BCEDEEA045D /* EXTKeyPathCoding */, + 5986E34C39BF6666F575AC27 /* EXTNil */, + 6A7567528A1118CB9CDC535F /* EXTSafeCategory */, + F92CF05BC048EBC88B194D62 /* EXTScope */, + 689643CE85BCDE849DD5CAC6 /* EXTSelectorChecking */, + D2B9308C50B8B3E00E504332 /* EXTSynthesize */, + F81829AEBF796ED1E3975450 /* NSInvocation+EXT */, + 49CDBAD1E229662ACB81F85A /* NSMethodSignature+EXT */, + BC928FF99557E36D3241A52B /* RuntimeExtensions */, + 2530F16707A39B9D978B568C /* Support Files */, + D3E81B6B2A5EB45056699C69 /* UmbrellaHeader */, + ); + path = libextobjc; + sourceTree = ""; + }; + FA0D6E5BA4091B0AEF746B3A /* extobjc */ = { + isa = PBXGroup; + children = ( + AF15FCEEB59AEB6EAD7CB6C0 /* EXTKeyPathCoding.h */, + AB4B6AE01220CC76558282D0 /* EXTRuntimeExtensions.h */, + CCCDCE9F36E3EBC5A29B744B /* EXTRuntimeExtensions.m */, + 5606C5C4729A228E117F081A /* EXTScope.h */, + 75B19C0796E1F6A6CDE8C5A7 /* EXTScope.m */, + A0ACBFD4DBCF9C083A947EF0 /* metamacros.h */, + ); + name = extobjc; + sourceTree = ""; + }; + FB7FBED3BE8315A274BAED0D /* Frameworks */ = { + isa = PBXGroup; + children = ( + E53C4CFBF9387FE98C64BE6D /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + FB8CA06449C6CF0C5030B5CE /* Support Files */ = { + isa = PBXGroup; + children = ( + 65562BCE6AF0C3554AA9DFEF /* Pods-PromiseKit.xcconfig */, + 8E05CB045EEEBD1BE3D085A8 /* Pods-PromiseKit-Private.xcconfig */, + CCCAFD5A7CBE50CA628E4A7C /* Pods-PromiseKit-dummy.m */, + BD45A1F343C7E4249DCD9F3A /* Pods-PromiseKit-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Pods-PromiseKit"; + sourceTree = ""; + }; + FC057C84507BD628E2892BB7 /* FormURLEncode */ = { + isa = PBXGroup; + children = ( + 393E36FA0A8340C5634EA54B /* OMGFormURLEncode.h */, + 856C6D9D8B00DCE05FEBD3F8 /* OMGFormURLEncode.m */, + ); + name = FormURLEncode; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 705D19813EDA91CD54C90EBA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B064B773774FC36BAA4ECF7 /* DDASLLogCapture.h in Headers */, + E0D7FD97CC9C07E3B199E065 /* DDASLLogger.h in Headers */, + 91C8B2B27E9A034588B3EF88 /* DDAbstractDatabaseLogger.h in Headers */, + 5A299F6087571C13E1FBD38E /* DDAssert.h in Headers */, + 2C2079D10688AFB06AE21C50 /* DDContextFilterLogFormatter.h in Headers */, + 151A8AC904286D6F6655CB63 /* DDDispatchQueueLogFormatter.h in Headers */, + C75FCEED2025FAE8F2C217FD /* DDFileLogger.h in Headers */, + 55EB7C523289BD83B902F4C3 /* DDLog+LOGV.h in Headers */, + 91AFA4BACA84F784268B3CB8 /* DDLog.h in Headers */, + 521BE8EE2C0EFD70C0C015BB /* DDMultiFormatter.h in Headers */, + C3A442C6ADE4D99720B9767C /* DDTTYLogger.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C1BBEA77B0A63DDC983D8310 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0922EFF87E65CCC91A19630D /* CALayer+PromiseKit.h in Headers */, + 29E2BFFCA3EC5DF8BCA67346 /* NSNotificationCenter+PromiseKit.h in Headers */, + B2D489B95B7E68A4E7C1645A /* NSURLConnection+PromiseKit.h in Headers */, + 7EE9450E970C0068D987E7C8 /* Promise+Pause.h in Headers */, + A934DA78F7454CEE51F56D54 /* Promise+Until.h in Headers */, + C0DF33C3B1F095E0AB32AACF /* Promise+When.h in Headers */, + A5F6A5E22ED6575360B7EAAC /* Promise.h in Headers */, + BE230F8A1FC7A33E41052E7C /* PromiseKit.h in Headers */, + 880EB1CA20294A4F96DF3619 /* UIActionSheet+PromiseKit.h in Headers */, + FA9307DF73CB084B73E6C37D /* UIAlertView+PromiseKit.h in Headers */, + A79E5004C35F179577B45781 /* UIView+PromiseKit.h in Headers */, + 2E2AF18ADE7C2D7AE07BCA28 /* UIViewController+PromiseKit.h in Headers */, + A9C42C4B9DCEC58B7D258C5B /* fwd.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CA369D21F8B692DF3088390E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A8F8A4884FE9B1CECE0E7317 /* OMGFormURLEncode.h in Headers */, + 83B9463173A6CC39F6067F7D /* OMGHTTPURLRQ.h in Headers */, + D3F55729DCF03AB1EBC6ABC6 /* OMGUserAgent.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D865429142CC0CD3732D8050 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1BDE430969D5CA035B3BF1ED /* NSDictionary+YapDatabase.h in Headers */, + 320C12128619516CDC082030 /* YDBCKAttachRequest.h in Headers */, + 3D319303A6F6FA5275CC5B96 /* YDBCKChangeQueue.h in Headers */, + 67AEC120F735E4C9658F427E /* YDBCKChangeRecord.h in Headers */, + B8356A1C094B5DF289E8A0DD /* YDBCKChangeSet.h in Headers */, + 9442DFDFC1D5DDC3E8E27E32 /* YDBCKMappingTableInfo.h in Headers */, + E372D28B6AFDC7B25C55BCD0 /* YDBCKMergeInfo.h in Headers */, + 2889BBDCCBBCAC20670C9773 /* YDBCKRecord.h in Headers */, + 2032F4501BB94472C4E5E987 /* YDBCKRecordInfo.h in Headers */, + 85D6F6032669344117D2E913 /* YDBCKRecordTableInfo.h in Headers */, + 3373F8E004411E72320670F8 /* YapCache.h in Headers */, + 72370E4F604C64CCFFD90CFB /* YapCollectionKey.h in Headers */, + 6D46D5F776CCAAFF8E95C7F1 /* YapDatabase.h in Headers */, + DEF60348439BF593AF507066 /* YapDatabaseCloudKit.h in Headers */, + B2CD3BBE742A3F540B3775B7 /* YapDatabaseCloudKitConnection.h in Headers */, + 8C33CE20A185FAF81BAFC71C /* YapDatabaseCloudKitOptions.h in Headers */, + FED020E85E05DCA54FEB78C6 /* YapDatabaseCloudKitPrivate.h in Headers */, + DA7587008ACBD634D98AB935 /* YapDatabaseCloudKitTransaction.h in Headers */, + A8D70A2780EEEC077EBCF277 /* YapDatabaseCloudKitTypes.h in Headers */, + AE858E85834C1A3D00CEA357 /* YapDatabaseConnection.h in Headers */, + 45E75AF08365440E05DF6A27 /* YapDatabaseConnectionDefaults.h in Headers */, + F0096881A27A111D46AF560B /* YapDatabaseConnectionState.h in Headers */, + F1F8B5F0DCD7E1BB86F9F268 /* YapDatabaseExtension.h in Headers */, + 642445434692712D21F794BF /* YapDatabaseExtensionConnection.h in Headers */, + 0B87B7852FCB584E75DC8EBA /* YapDatabaseExtensionPrivate.h in Headers */, + E1EE55AD8365CEB3F3C6BD70 /* YapDatabaseExtensionTransaction.h in Headers */, + FBE50FADC49004F79110D7CB /* YapDatabaseFilteredView.h in Headers */, + 1C6044CE1649578F58B9961E /* YapDatabaseFilteredViewConnection.h in Headers */, + 00E2B77D7DE7526303FED558 /* YapDatabaseFilteredViewPrivate.h in Headers */, + 1A7A1E15B61BECFB9808BC9A /* YapDatabaseFilteredViewTransaction.h in Headers */, + 8E991D483B73B54A5AD3C7CA /* YapDatabaseFilteredViewTypes.h in Headers */, + 0A017E2DB8F8E9BF3FD9D4CB /* YapDatabaseFullTextSearch.h in Headers */, + 2D613D950823E156A0649855 /* YapDatabaseFullTextSearchConnection.h in Headers */, + A14F74736E7F517740ED2655 /* YapDatabaseFullTextSearchHandler.h in Headers */, + 9FC81B113C5B2450593CAFF4 /* YapDatabaseFullTextSearchPrivate.h in Headers */, + 1C263643CC5F0B7AE3580082 /* YapDatabaseFullTextSearchSnippetOptions.h in Headers */, + 3BC4660E2071311F3BC496DD /* YapDatabaseFullTextSearchTransaction.h in Headers */, + 2BBB77ECFC35DEE6C558AE6C /* YapDatabaseLogging.h in Headers */, + 811EF2C649403FFCAD8564D0 /* YapDatabaseManager.h in Headers */, + C392BD90310BF3BF99DD2745 /* YapDatabaseOptions.h in Headers */, + 73F7AE8637DFC21688A81168 /* YapDatabasePrivate.h in Headers */, + 1817671FF5B5ABB4BE448EE5 /* YapDatabaseQuery.h in Headers */, + 17875094B0CC989BFCD8B70E /* YapDatabaseRelationship.h in Headers */, + CF78CBACE9DD2EF0BB057941 /* YapDatabaseRelationshipConnection.h in Headers */, + 59E968FB6F3ED06A45057C62 /* YapDatabaseRelationshipEdge.h in Headers */, + 63848CE3C074E0223BF9EB30 /* YapDatabaseRelationshipEdgePrivate.h in Headers */, + E893FF4B0E5862E46C872EEF /* YapDatabaseRelationshipNode.h in Headers */, + 75DA09355FDF3F5EF07E599F /* YapDatabaseRelationshipOptions.h in Headers */, + 0E6A82EA647A6DF6672592F3 /* YapDatabaseRelationshipPrivate.h in Headers */, + 3488D27C9CA0EA168116BAFA /* YapDatabaseRelationshipTransaction.h in Headers */, + DBB3E0E7C8472F7BC3E43BE2 /* YapDatabaseSearchQueue.h in Headers */, + 3916FA4B485724427DE83EEA /* YapDatabaseSearchQueuePrivate.h in Headers */, + 666458434CBD1A432D86A986 /* YapDatabaseSearchResultsView.h in Headers */, + A6EB25298004319B636896F5 /* YapDatabaseSearchResultsViewConnection.h in Headers */, + B3190607E5704A86597655FD /* YapDatabaseSearchResultsViewOptions.h in Headers */, + 99763DDB19BD89C370726B40 /* YapDatabaseSearchResultsViewPrivate.h in Headers */, + 042322EE4E32C952DEC6D631 /* YapDatabaseSearchResultsViewTransaction.h in Headers */, + 9A015EEE94855F115B761022 /* YapDatabaseSecondaryIndex.h in Headers */, + D4A9346A92F263881EDAF96B /* YapDatabaseSecondaryIndexConnection.h in Headers */, + C1B244E6F6578B4A8749EB33 /* YapDatabaseSecondaryIndexHandler.h in Headers */, + 6AE192F5D2A27D5E6740C203 /* YapDatabaseSecondaryIndexOptions.h in Headers */, + 421998FE3BFC2D363C2302A6 /* YapDatabaseSecondaryIndexPrivate.h in Headers */, + 5D172D3F19C6F0DD41574744 /* YapDatabaseSecondaryIndexSetup.h in Headers */, + C3BA828063369FDF99D4CC8A /* YapDatabaseSecondaryIndexTransaction.h in Headers */, + AC6121B6549FB1E5ACD23BDC /* YapDatabaseStatement.h in Headers */, + BBFB123B31F45583A6226873 /* YapDatabaseString.h in Headers */, + 3341A093D96DF05AD9D21D97 /* YapDatabaseTransaction.h in Headers */, + BD92C1BE319868938EEF75A6 /* YapDatabaseView.h in Headers */, + 0FF020F41CBD054A3932C50E /* YapDatabaseViewChange.h in Headers */, + FDF798CE4BEFDAFD2FEAF15B /* YapDatabaseViewChangePrivate.h in Headers */, + 7EFC27818D7F8160C33B0785 /* YapDatabaseViewConnection.h in Headers */, + 578A5DC4E244E83A5582C354 /* YapDatabaseViewMappings.h in Headers */, + 5775AD1714634B6B8FB185A6 /* YapDatabaseViewMappingsPrivate.h in Headers */, + C39C83FE3FADE1510A868002 /* YapDatabaseViewOptions.h in Headers */, + A7EFBB9754D81121573FD4B2 /* YapDatabaseViewPage.h in Headers */, + D508D57DF1A202F8F5532B0A /* YapDatabaseViewPageMetadata.h in Headers */, + C9531252D24DE1C6523339B7 /* YapDatabaseViewPrivate.h in Headers */, + B98E04CB6435AF691B9337C4 /* YapDatabaseViewRangeOptions.h in Headers */, + 588F15B1A5358B4582809D2D /* YapDatabaseViewRangeOptionsPrivate.h in Headers */, + 0548F903C52416571F233ACB /* YapDatabaseViewState.h in Headers */, + 9D7ABE00695A5F2F71404F6B /* YapDatabaseViewTransaction.h in Headers */, + 7751DAC53A4FD3D86CE7F800 /* YapDatabaseViewTypes.h in Headers */, + 8EE0978A86C7C95F00F5586E /* YapDebugDictionary.h in Headers */, + 818D001CE9EE75563B2A3BDC /* YapMemoryTable.h in Headers */, + 43BAB55883AE12E8D10F32B3 /* YapMurmurHash.h in Headers */, + 9F827C827C5B1F3B64B881A4 /* YapNull.h in Headers */, + A7C6BD25A76358037E50524A /* YapRowidSet.h in Headers */, + 15E38F9C005EEF2C0AEB43A6 /* YapSet.h in Headers */, + AF7275254F27FCF36464A98D /* YapTouch.h in Headers */, + E3E2AF8B8A425BE787EEEC70 /* YapWhitelistBlacklist.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1B7F19ED99A0F2BF0F608D6 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AADF960EA8CFAE81A5545F87 /* NSArray+ObjectiveSugar.h in Headers */, + F427DCE61C8F9EA1D4FC5304 /* NSDictionary+ObjectiveSugar.h in Headers */, + 432A3497095D94DB14B3FA64 /* NSMutableArray+ObjectiveSugar.h in Headers */, + 195C8066B9AEB58966C53D93 /* NSNumber+ObjectiveSugar.h in Headers */, + AA69A0887EE492BD9BDE4C89 /* NSSet+ObjectiveSugar.h in Headers */, + D26A139CF959DBEAE84DD175 /* NSString+ObjectiveSugar.h in Headers */, + 4CE40CB723AC8F6873B3F049 /* ObjectiveSugar.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EFEB25AF10AA5061E329BE28 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 72708245586CF5F647C465D9 /* EXTADT.h in Headers */, + FCEB5D8FAFCFA00E0F3421EA /* EXTConcreteProtocol.h in Headers */, + D655CA02A6A708864D065F4C /* EXTKeyPathCoding.h in Headers */, + EE3DE12AC4EE185973A24877 /* EXTNil.h in Headers */, + B994A1B39274EED3CCCD815B /* EXTRuntimeExtensions.h in Headers */, + 4014F479978CCBAAF38F5043 /* EXTSafeCategory.h in Headers */, + 7D81FEC7FABBDF36EB05F80E /* EXTScope.h in Headers */, + 41BE33B30F5C82EE8666985E /* EXTSelectorChecking.h in Headers */, + 65E238651F83DC64FCC5A68B /* EXTSynthesize.h in Headers */, + 932141A8322B389B5A597598 /* NSInvocation+EXT.h in Headers */, + 10429102C946DDC613AA2B73 /* NSMethodSignature+EXT.h in Headers */, + A03CFB6674C6D50980618543 /* extobjc.h in Headers */, + 330376AD9FC5647B9425A3B0 /* metamacros.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FAB5EF4083772043146AA67A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FF2A08CCC3BC8A56EA860790 /* EXTKeyPathCoding.h in Headers */, + 71C8205423996C5C100D0356 /* EXTRuntimeExtensions.h in Headers */, + BC34E85B426139ADD687562C /* EXTScope.h in Headers */, + B21FDBF2CAEFC3FA35ED8548 /* MTLJSONAdapter.h in Headers */, + 007F741F640C13B83FC3CA1F /* MTLModel+NSCoding.h in Headers */, + DA9AF495356FDF40FB145DC8 /* MTLModel.h in Headers */, + D77A951CC523846B3BFB066D /* MTLReflection.h in Headers */, + CADB0CD10DF730A884F88967 /* MTLTransformerErrorHandling.h in Headers */, + CB27A000DB612A4F2201192C /* MTLValueTransformer.h in Headers */, + BD657FF855AFCABB80517E04 /* Mantle.h in Headers */, + 0520164F4EAACB63E700E760 /* NSArray+MTLManipulationAdditions.h in Headers */, + 4F2BE2B87836E66A0FF22BA2 /* NSDictionary+MTLJSONKeyPath.h in Headers */, + 4EADB4960211890DB3952C03 /* NSDictionary+MTLManipulationAdditions.h in Headers */, + A48A2C8985BB8235C28881D1 /* NSDictionary+MTLMappingAdditions.h in Headers */, + E94BCD55687A34DAF1C8197E /* NSError+MTLModelException.h in Headers */, + F21BAEDFCFFD78F99AAF5D08 /* NSObject+MTLComparisonAdditions.h in Headers */, + AAD7ADD57DC7FFF91425EED5 /* NSValueTransformer+MTLInversionAdditions.h in Headers */, + B486F91E24012FBC368B42AE /* NSValueTransformer+MTLPredefinedTransformerAdditions.h in Headers */, + FE59175526BF6E62CE8BD1C8 /* metamacros.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 93C89E0ADF6524A2DF3F1D47 /* Pods */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9FDEACBA2B7339CE7CE89A00 /* Build configuration list for PBXNativeTarget "Pods" */; + buildPhases = ( + E8B0F41EA89322EB9A77651E /* Sources */, + 7F8DDB4F5A15193E98B3AE9B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + A6860A262D7040732CC1FB3F /* PBXTargetDependency */, + 5CF0FF7D92736727167CD361 /* PBXTargetDependency */, + CDEDC0B2BD19EB03B2F34C64 /* PBXTargetDependency */, + C7BA397D622C47960AC88486 /* PBXTargetDependency */, + 9D5A0FF616310CAD4835A066 /* PBXTargetDependency */, + 7AB8FCF6639391B7785CD1FD /* PBXTargetDependency */, + 803C1038B32A0CAFDB7F6702 /* PBXTargetDependency */, + ); + name = Pods; + productName = Pods; + productReference = D5EC2ACE8C0A18E9E2B5C587 /* libPods.a */; + productType = "com.apple.product-type.library.static"; + }; + C23F805F74372C3575165115 /* Pods-OMGHTTPURLRQ */ = { + isa = PBXNativeTarget; + buildConfigurationList = 524D3C584B40E04FE63D92A3 /* Build configuration list for PBXNativeTarget "Pods-OMGHTTPURLRQ" */; + buildPhases = ( + 8485F4C71D7FBBEDA557EFBA /* Sources */, + F44EE40154153E69CC172EFE /* Frameworks */, + CA369D21F8B692DF3088390E /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-OMGHTTPURLRQ"; + productName = "Pods-OMGHTTPURLRQ"; + productReference = 86ADEBF61A25C443E7790CC4 /* libPods-OMGHTTPURLRQ.a */; + productType = "com.apple.product-type.library.static"; + }; + CF9B45FD9AF86E2E19900DCE /* Pods-CocoaLumberjack */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0D24342F6CEF33797C4ADC79 /* Build configuration list for PBXNativeTarget "Pods-CocoaLumberjack" */; + buildPhases = ( + 951FEED83AA6DEE200808A77 /* Sources */, + 605F016960980B15B666F00B /* Frameworks */, + 705D19813EDA91CD54C90EBA /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-CocoaLumberjack"; + productName = "Pods-CocoaLumberjack"; + productReference = 98E1245800E1ED8EBFE5CAF4 /* libPods-CocoaLumberjack.a */; + productType = "com.apple.product-type.library.static"; + }; + D28AE1B38101D1F1C6E0C5F8 /* Pods-PromiseKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6E3DADF5121CDBB3E527FE73 /* Build configuration list for PBXNativeTarget "Pods-PromiseKit" */; + buildPhases = ( + B4C2D3765B85F4383837FB43 /* Sources */, + 5907F8DEB1C3AADFE58A64DB /* Frameworks */, + C1BBEA77B0A63DDC983D8310 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + C2D69B831DDEB42C9846F36A /* PBXTargetDependency */, + ); + name = "Pods-PromiseKit"; + productName = "Pods-PromiseKit"; + productReference = B7E184741559D494AB0E33F1 /* libPods-PromiseKit.a */; + productType = "com.apple.product-type.library.static"; + }; + DE8ABA60CC6A843213B1A2A5 /* Pods-ObjectiveSugar */ = { + isa = PBXNativeTarget; + buildConfigurationList = E97BCB73FB8666F4E9BD0CFF /* Build configuration list for PBXNativeTarget "Pods-ObjectiveSugar" */; + buildPhases = ( + 65C93C3BBD5A4FAD6B37372F /* Sources */, + 07BA57F619E6995B6FF41FCE /* Frameworks */, + E1B7F19ED99A0F2BF0F608D6 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-ObjectiveSugar"; + productName = "Pods-ObjectiveSugar"; + productReference = 6B9B4F309426DA09B38A7B98 /* libPods-ObjectiveSugar.a */; + productType = "com.apple.product-type.library.static"; + }; + E07CFAEA42D65CAAEA16E41F /* Pods-Mantle */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5A646E7C6B6361D0BD253DBB /* Build configuration list for PBXNativeTarget "Pods-Mantle" */; + buildPhases = ( + EFEB4FA8AAB22A704174E5C9 /* Sources */, + 50EF8235C660795300D3C750 /* Frameworks */, + FAB5EF4083772043146AA67A /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-Mantle"; + productName = "Pods-Mantle"; + productReference = 54F2BBA18BAA51ECCE2A1EB1 /* libPods-Mantle.a */; + productType = "com.apple.product-type.library.static"; + }; + E44FCF643CAFD65D52CD0816 /* Pods-libextobjc */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0FC0760EE52095811C8F006B /* Build configuration list for PBXNativeTarget "Pods-libextobjc" */; + buildPhases = ( + 85C700556FE9B59B022CF6B8 /* Sources */, + DB960CBED6D636F4558EB79F /* Frameworks */, + EFEB25AF10AA5061E329BE28 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Pods-libextobjc"; + productName = "Pods-libextobjc"; + productReference = F0FFEFCB3225AC4CDE931ED9 /* libPods-libextobjc.a */; + productType = "com.apple.product-type.library.static"; + }; + E69AB6A68231E7447702085B /* Pods-YapDatabase */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6DF6998DE9A507AC6E73BD05 /* Build configuration list for PBXNativeTarget "Pods-YapDatabase" */; + buildPhases = ( + AC94C14EE70CEB37B9676398 /* Sources */, + 99586F1B341DFD410CA72329 /* Frameworks */, + D865429142CC0CD3732D8050 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + 1D932FD8EDC635795F8B2601 /* PBXTargetDependency */, + ); + name = "Pods-YapDatabase"; + productName = "Pods-YapDatabase"; + productReference = 91805095FBEE932AED95AE42 /* libPods-YapDatabase.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F9B1CC588BECD991E0E4093E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; + buildConfigurationList = 86B2228CCC142E4F4EB57B63 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4CC267C09BF26CEB8381B4E5; + productRefGroup = C298FAA417022E57229C936B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 93C89E0ADF6524A2DF3F1D47 /* Pods */, + CF9B45FD9AF86E2E19900DCE /* Pods-CocoaLumberjack */, + E07CFAEA42D65CAAEA16E41F /* Pods-Mantle */, + C23F805F74372C3575165115 /* Pods-OMGHTTPURLRQ */, + DE8ABA60CC6A843213B1A2A5 /* Pods-ObjectiveSugar */, + D28AE1B38101D1F1C6E0C5F8 /* Pods-PromiseKit */, + E69AB6A68231E7447702085B /* Pods-YapDatabase */, + E44FCF643CAFD65D52CD0816 /* Pods-libextobjc */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 65C93C3BBD5A4FAD6B37372F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 32C5FEBB1261C047CC4B31A8 /* NSArray+ObjectiveSugar.m in Sources */, + D55615DAE27DE78E582FF8DE /* NSDictionary+ObjectiveSugar.m in Sources */, + ADFA4463B8AC48669C69D0D7 /* NSMutableArray+ObjectiveSugar.m in Sources */, + C3A73DD52D3D109AA6C420D5 /* NSNumber+ObjectiveSugar.m in Sources */, + 80E3EAF64896C59E4A479529 /* NSSet+ObjectiveSugar.m in Sources */, + 7EEF49441156BBA4776E0CFB /* NSString+ObjectiveSugar.m in Sources */, + 832E5D12B24ED80B89BE7910 /* Pods-ObjectiveSugar-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8485F4C71D7FBBEDA557EFBA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EEB052478D4F1A26E194F4D9 /* OMGFormURLEncode.m in Sources */, + A8B24FFB059A18874701BF78 /* OMGHTTPURLRQ.m in Sources */, + 9889C4834103CF717AE25F85 /* OMGUserAgent.m in Sources */, + EF41F3E7ABBEDF3CB01895D4 /* Pods-OMGHTTPURLRQ-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 85C700556FE9B59B022CF6B8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F55738009B2C2B3B08A4ECE2 /* EXTADT.m in Sources */, + 29484C8A2BA8676F352D7A95 /* EXTConcreteProtocol.m in Sources */, + 2752EE88E18CCBAAEDDCFE31 /* EXTNil.m in Sources */, + 45AF312832FB7890BA69E217 /* EXTRuntimeExtensions.m in Sources */, + 36C1FC31D0AAD3ED40FDFBE9 /* EXTSafeCategory.m in Sources */, + FDE4C0DFD591DAE714BDA7E7 /* EXTScope.m in Sources */, + 253DE4310524B14835EDD135 /* EXTSelectorChecking.m in Sources */, + 9C9CD99B7AC0C5047F58E665 /* NSInvocation+EXT.m in Sources */, + 788B21ADB8CAEBCB70800C49 /* NSMethodSignature+EXT.m in Sources */, + F66D0954CE5DF3D3CBE6064D /* Pods-libextobjc-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 951FEED83AA6DEE200808A77 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 65D0463F61748C2E67057A2B /* DDASLLogCapture.m in Sources */, + FB0E78F3112B8CDA6E4966EA /* DDASLLogger.m in Sources */, + C4C644B6887404BC149A8B43 /* DDAbstractDatabaseLogger.m in Sources */, + 4A8C4DC9D3A6D067F7AB50D3 /* DDContextFilterLogFormatter.m in Sources */, + 3A37222B52D6C41B7881FD7D /* DDDispatchQueueLogFormatter.m in Sources */, + B3468F68184BABFE82086721 /* DDFileLogger.m in Sources */, + 82DF64283B06A9493951B901 /* DDLog.m in Sources */, + 9B3D608EA932B133F05C14E9 /* DDMultiFormatter.m in Sources */, + 6A204D28F2D35AE7BB4B305E /* DDTTYLogger.m in Sources */, + ED294EEDE6517BA9E74A7365 /* Pods-CocoaLumberjack-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AC94C14EE70CEB37B9676398 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC955706F46D978D624A4042 /* NSDictionary+YapDatabase.m in Sources */, + 01FE2CA8DF522F0F52CC1947 /* Pods-YapDatabase-dummy.m in Sources */, + AE8DED488304E93C68B22298 /* YDBCKAttachRequest.m in Sources */, + D23A1650CEF6FE495242D9AB /* YDBCKChangeQueue.m in Sources */, + 6545BFD2C8352927A85B96A7 /* YDBCKChangeRecord.m in Sources */, + F2FEB8480E930EB493DE0659 /* YDBCKChangeSet.m in Sources */, + 0C6480EDDC730138500282A6 /* YDBCKMappingTableInfo.m in Sources */, + 8A7FD4AD69A397861B720765 /* YDBCKMergeInfo.m in Sources */, + 62A26E2AECF8B1DA3924B742 /* YDBCKRecord.m in Sources */, + 869B8A95A96C7B5C4863D6A7 /* YDBCKRecordInfo.m in Sources */, + 3F5FFF07B90D48BE07F23A12 /* YDBCKRecordTableInfo.m in Sources */, + B20DD92CA85553DAE0480A79 /* YapCache.m in Sources */, + 352E08E3FDF4D74B56768812 /* YapCollectionKey.m in Sources */, + 492DD4001B3CB960C78A6955 /* YapDatabase.m in Sources */, + A8CCDB8D145B76C259B9AF45 /* YapDatabaseCloudKit.m in Sources */, + C85FABC0B10C4942C61D0146 /* YapDatabaseCloudKitConnection.m in Sources */, + C01520ABB975EC1F519990A6 /* YapDatabaseCloudKitOptions.m in Sources */, + A4C43E295FDB5A754D5C1028 /* YapDatabaseCloudKitTransaction.m in Sources */, + 57D1A997EDA967899749E3BF /* YapDatabaseCloudKitTypes.m in Sources */, + 6B89D8AE2B78D630331136EB /* YapDatabaseConnection.m in Sources */, + 4A2C74107EC836AE28C3A4C4 /* YapDatabaseConnectionDefaults.m in Sources */, + 2BDD705BB84F242DE7D12331 /* YapDatabaseConnectionState.m in Sources */, + 9F7F76B6614AC583D001AF1E /* YapDatabaseExtension.m in Sources */, + BAF4197475FED29DCFD41E75 /* YapDatabaseExtensionConnection.m in Sources */, + CBDCBD5E3EF6096F13821B05 /* YapDatabaseExtensionTransaction.m in Sources */, + FE87CF72EFFD8C0E3D651F40 /* YapDatabaseFilteredView.m in Sources */, + 6E67EF3B831409F405C8B18A /* YapDatabaseFilteredViewConnection.m in Sources */, + B89B474D5E21568E09E1AC80 /* YapDatabaseFilteredViewTransaction.m in Sources */, + C5AF6E176B29249C7776A6ED /* YapDatabaseFilteredViewTypes.m in Sources */, + F1CC9380EC06F12DA48A2B55 /* YapDatabaseFullTextSearch.m in Sources */, + 60E6BACBD4D7B705679FD831 /* YapDatabaseFullTextSearchConnection.m in Sources */, + 2CF48C6D94A40236EDD4A38C /* YapDatabaseFullTextSearchHandler.m in Sources */, + 20F6230C47EF619D258AAA6E /* YapDatabaseFullTextSearchSnippetOptions.m in Sources */, + 16987B3AF68ACBA047E4CCCA /* YapDatabaseFullTextSearchTransaction.m in Sources */, + 6C7EB29E04993F1A7202F90E /* YapDatabaseLogging.m in Sources */, + 45DF178F4AB951599059E18F /* YapDatabaseManager.m in Sources */, + 6D82369941093072ED61122A /* YapDatabaseOptions.m in Sources */, + 9B4E726A9CFBA1804E58006C /* YapDatabaseQuery.m in Sources */, + 5A22FFF7A64779CCB32C7742 /* YapDatabaseRelationship.m in Sources */, + 0FCBC0749E44D41B26E99A59 /* YapDatabaseRelationshipConnection.m in Sources */, + 95A6114176F766454CB39E35 /* YapDatabaseRelationshipEdge.m in Sources */, + 598A95905613C5F4F95111C8 /* YapDatabaseRelationshipOptions.m in Sources */, + 757AC3E9D775B865B179617E /* YapDatabaseRelationshipTransaction.m in Sources */, + 2CE035BB0E9EABEEDB535D2B /* YapDatabaseSearchQueue.m in Sources */, + 8C08287B05BADF59BC9A27F4 /* YapDatabaseSearchResultsView.m in Sources */, + A7BD315096E8E4B17B0120E0 /* YapDatabaseSearchResultsViewConnection.m in Sources */, + 4783FAD5039BCCCCB31D05BC /* YapDatabaseSearchResultsViewOptions.m in Sources */, + BE2E97F1B49C0CB29697C7B7 /* YapDatabaseSearchResultsViewTransaction.m in Sources */, + 1663D8B78117B111DDEB1F5C /* YapDatabaseSecondaryIndex.m in Sources */, + 1EAAF5F6C2270447EDC29B4C /* YapDatabaseSecondaryIndexConnection.m in Sources */, + 82A712D03546462679C7B690 /* YapDatabaseSecondaryIndexHandler.m in Sources */, + 9AE9C9F48555491014DA60D1 /* YapDatabaseSecondaryIndexOptions.m in Sources */, + A3A019CA829952787448DCC7 /* YapDatabaseSecondaryIndexSetup.m in Sources */, + F0735D654F899FD6D0451F81 /* YapDatabaseSecondaryIndexTransaction.m in Sources */, + 6A7CD4A1AF81FCEBE7D9FA3A /* YapDatabaseStatement.m in Sources */, + 8AF21DFF159D03C97F767389 /* YapDatabaseTransaction.m in Sources */, + A5F30F988D99A629D45689B9 /* YapDatabaseView.m in Sources */, + 9D4F8E7070F187A962389E2A /* YapDatabaseViewChange.m in Sources */, + C2FA4ABC9A5E0AA220F3E621 /* YapDatabaseViewConnection.m in Sources */, + 01F9D45DD8703DBF1F7838B3 /* YapDatabaseViewMappings.m in Sources */, + 13C003C528DFA9A9F3073B43 /* YapDatabaseViewOptions.m in Sources */, + 1D6EA085B3F1D8E194796855 /* YapDatabaseViewPage.mm in Sources */, + 867F4766B9913F355A024D2A /* YapDatabaseViewPageMetadata.m in Sources */, + A95983A98DFA212403A89803 /* YapDatabaseViewRangeOptions.m in Sources */, + 771F2EB74D50FC1840793908 /* YapDatabaseViewState.m in Sources */, + BD4E2884B7C770ADF39269C9 /* YapDatabaseViewTransaction.m in Sources */, + 1759708F65FD92513B8123A3 /* YapDatabaseViewTypes.m in Sources */, + A7AC56A7BBE4CE9A9F074BF8 /* YapDebugDictionary.m in Sources */, + D0640E0E525F55616D8198C0 /* YapMemoryTable.m in Sources */, + 227BFC390A2E521FE7F3734E /* YapMurmurHash.m in Sources */, + E6A9BF282890128E920D87D1 /* YapNull.m in Sources */, + 1E40FB2658F7FCEB4C887926 /* YapRowidSet.mm in Sources */, + 36AD8BB6DFEB3100C6F5A05E /* YapSet.m in Sources */, + 5E700451A258E9AAE027AEEC /* YapTouch.m in Sources */, + 25CF63C0F42E0B59F461063C /* YapWhitelistBlacklist.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B4C2D3765B85F4383837FB43 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1DA95D0C4AB40277C9695D66 /* CALayer+PromiseKit.m in Sources */, + DEA831D815663A702280BC8E /* NSNotificationCenter+PromiseKit.m in Sources */, + 0FB116FEE58F45EF3D8D39B0 /* NSURLConnection+PromiseKit.m in Sources */, + 7AF502E281E3D1700E2E63B1 /* PMKPromise+Pause.m in Sources */, + CC73559157087B8E7B87188B /* PMKPromise+Until.m in Sources */, + 9862D110987495C2147CB67D /* PMKPromise+When.m in Sources */, + 80531CBE74FA7E00F097C1C2 /* PMKPromise.m in Sources */, + 87E7195676AD5509CB78A469 /* Pods-PromiseKit-dummy.m in Sources */, + 016143BC6D3DD64D3F22C198 /* UIActionSheet+PromiseKit.m in Sources */, + 2FBCF11D260057B17D1D2624 /* UIAlertView+PromiseKit.m in Sources */, + 401A201D7390B6E45616323C /* UIView+PromiseKit.m in Sources */, + 10B5708EA877A4A2AA6AB01B /* UIViewController+PromiseKit.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8B0F41EA89322EB9A77651E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 710B07FD59BA817928992297 /* Pods-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EFEB4FA8AAB22A704174E5C9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4FC5CDD9A4207BA855F3426A /* EXTRuntimeExtensions.m in Sources */, + 8188C8F7B6373C258FE10EDD /* EXTScope.m in Sources */, + A160D32C4E861C8B7AC5C622 /* MTLJSONAdapter.m in Sources */, + BD58D46DE006E347D0A8CF8F /* MTLModel+NSCoding.m in Sources */, + 0B79A2F178478D54E7B20116 /* MTLModel.m in Sources */, + 97EE89BAFEF587530FD5806D /* MTLReflection.m in Sources */, + 653B605B7CD66EA5C65EB7D4 /* MTLTransformerErrorHandling.m in Sources */, + 09A37BECCA96B9D2AB5B4ABE /* MTLValueTransformer.m in Sources */, + 408BA840BE234BBCEE4657B2 /* NSArray+MTLManipulationAdditions.m in Sources */, + D7ADCAAA669C9E0D3253CBB0 /* NSDictionary+MTLJSONKeyPath.m in Sources */, + 7AD5EB3CE80980538C76EE60 /* NSDictionary+MTLManipulationAdditions.m in Sources */, + 3DD5C902942FD775019A4227 /* NSDictionary+MTLMappingAdditions.m in Sources */, + 0D8062C8C292A738BC28008C /* NSError+MTLModelException.m in Sources */, + AAB31C1545B766C4DDA66AD6 /* NSObject+MTLComparisonAdditions.m in Sources */, + E21870B373BF7A64046907C1 /* NSValueTransformer+MTLInversionAdditions.m in Sources */, + D2F95E0D7E114B0146D78664 /* NSValueTransformer+MTLPredefinedTransformerAdditions.m in Sources */, + EE6E499E52B6E402B786236E /* Pods-Mantle-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1D932FD8EDC635795F8B2601 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-CocoaLumberjack"; + target = CF9B45FD9AF86E2E19900DCE /* Pods-CocoaLumberjack */; + targetProxy = 00D82167B28EDBC0CE0360E7 /* PBXContainerItemProxy */; + }; + 5CF0FF7D92736727167CD361 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-Mantle"; + target = E07CFAEA42D65CAAEA16E41F /* Pods-Mantle */; + targetProxy = 60AC825DD07C67C2D0BEE3D7 /* PBXContainerItemProxy */; + }; + 7AB8FCF6639391B7785CD1FD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-YapDatabase"; + target = E69AB6A68231E7447702085B /* Pods-YapDatabase */; + targetProxy = 69468D7EC99149C6126C4960 /* PBXContainerItemProxy */; + }; + 803C1038B32A0CAFDB7F6702 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-libextobjc"; + target = E44FCF643CAFD65D52CD0816 /* Pods-libextobjc */; + targetProxy = C359C5D028BCD0B811FBE7B7 /* PBXContainerItemProxy */; + }; + 9D5A0FF616310CAD4835A066 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-PromiseKit"; + target = D28AE1B38101D1F1C6E0C5F8 /* Pods-PromiseKit */; + targetProxy = 271961EC9EDF4C3D53181029 /* PBXContainerItemProxy */; + }; + A6860A262D7040732CC1FB3F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-CocoaLumberjack"; + target = CF9B45FD9AF86E2E19900DCE /* Pods-CocoaLumberjack */; + targetProxy = B42A508AF0C6A295F0A9BE44 /* PBXContainerItemProxy */; + }; + C2D69B831DDEB42C9846F36A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-OMGHTTPURLRQ"; + target = C23F805F74372C3575165115 /* Pods-OMGHTTPURLRQ */; + targetProxy = AE72A8C8E16B6C2CBEF3E467 /* PBXContainerItemProxy */; + }; + C7BA397D622C47960AC88486 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-ObjectiveSugar"; + target = DE8ABA60CC6A843213B1A2A5 /* Pods-ObjectiveSugar */; + targetProxy = A719335A643249325EF5E776 /* PBXContainerItemProxy */; + }; + CDEDC0B2BD19EB03B2F34C64 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-OMGHTTPURLRQ"; + target = C23F805F74372C3575165115 /* Pods-OMGHTTPURLRQ */; + targetProxy = E0C5B5108183021FAB914320 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 07D00665FFEBBAFC2359B6BA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9CD32733E73D6D9420AB496F /* Pods-Mantle-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-Mantle/Pods-Mantle-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 17A9E90DBBA1BFE40540789E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B34E3A4413395661C93D46D6 /* Pods-YapDatabase-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-YapDatabase/Pods-YapDatabase-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 195A9B94C32B8CE33D76B77E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC5FE41A058526C6C1557CF5 /* Pods-CocoaLumberjack-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 59F2C902EFED48CA2B92FE5D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8E05CB045EEEBD1BE3D085A8 /* Pods-PromiseKit-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-PromiseKit/Pods-PromiseKit-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 5D97A2E48DB5C1B296F568C2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 94B5688717AC26757392BD42 /* Pods-ObjectiveSugar-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 691B7107805041391A6D5109 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 94B5688717AC26757392BD42 /* Pods-ObjectiveSugar-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 6CC8DA3134EA60EABB1F3257 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A3E9E153CBCF907078D67591 /* Pods-libextobjc-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-libextobjc/Pods-libextobjc-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 7A44F5716DAF157A50C689A4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EC5FE41A058526C6C1557CF5 /* Pods-CocoaLumberjack-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 7C557C41BC69AD1DC6B2F817 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A9B880ED0C270A8EC1241DDA /* Pods-OMGHTTPURLRQ-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 819DC20F5AE6C1F20C4B8244 /* 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; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 96C984BA7E5489858E4BDAAF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0AB9D3ED0DF727B5B73580DB /* Pods.release.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + AA0AA0AE4ADD089C2C1A5FD0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9CD32733E73D6D9420AB496F /* Pods-Mantle-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-Mantle/Pods-Mantle-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + B40FECD59E0C2400F3589347 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B34E3A4413395661C93D46D6 /* Pods-YapDatabase-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-YapDatabase/Pods-YapDatabase-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + BE00F9B93060A6596813E24A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D1AADC7C1CF987010AA2DA67 /* Pods.debug.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + BE7AFB7F414855C5614FB337 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A3E9E153CBCF907078D67591 /* Pods-libextobjc-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-libextobjc/Pods-libextobjc-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + E5707069E791C112C982EBAF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A9B880ED0C270A8EC1241DDA /* Pods-OMGHTTPURLRQ-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + EFCF393C5D701B8089A0DA38 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8E05CB045EEEBD1BE3D085A8 /* Pods-PromiseKit-Private.xcconfig */; + buildSettings = { + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/Pods-PromiseKit/Pods-PromiseKit-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; + F5A1D574FD9A31FB2CCF071F /* 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; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + 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; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + ONLY_ACTIVE_ARCH = YES; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0D24342F6CEF33797C4ADC79 /* Build configuration list for PBXNativeTarget "Pods-CocoaLumberjack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 195A9B94C32B8CE33D76B77E /* Debug */, + 7A44F5716DAF157A50C689A4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0FC0760EE52095811C8F006B /* Build configuration list for PBXNativeTarget "Pods-libextobjc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6CC8DA3134EA60EABB1F3257 /* Debug */, + BE7AFB7F414855C5614FB337 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 524D3C584B40E04FE63D92A3 /* Build configuration list for PBXNativeTarget "Pods-OMGHTTPURLRQ" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E5707069E791C112C982EBAF /* Debug */, + 7C557C41BC69AD1DC6B2F817 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5A646E7C6B6361D0BD253DBB /* Build configuration list for PBXNativeTarget "Pods-Mantle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 07D00665FFEBBAFC2359B6BA /* Debug */, + AA0AA0AE4ADD089C2C1A5FD0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6DF6998DE9A507AC6E73BD05 /* Build configuration list for PBXNativeTarget "Pods-YapDatabase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 17A9E90DBBA1BFE40540789E /* Debug */, + B40FECD59E0C2400F3589347 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6E3DADF5121CDBB3E527FE73 /* Build configuration list for PBXNativeTarget "Pods-PromiseKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 59F2C902EFED48CA2B92FE5D /* Debug */, + EFCF393C5D701B8089A0DA38 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 86B2228CCC142E4F4EB57B63 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F5A1D574FD9A31FB2CCF071F /* Debug */, + 819DC20F5AE6C1F20C4B8244 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9FDEACBA2B7339CE7CE89A00 /* Build configuration list for PBXNativeTarget "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BE00F9B93060A6596813E24A /* Debug */, + 96C984BA7E5489858E4BDAAF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E97BCB73FB8666F4E9BD0CFF /* Build configuration list for PBXNativeTarget "Pods-ObjectiveSugar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D97A2E48DB5C1B296F568C2 /* Debug */, + 691B7107805041391A6D5109 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F9B1CC588BECD991E0E4093E /* Project object */; +} diff --git a/Pods/PromiseKit/README.markdown b/Pods/PromiseKit/README.markdown index 80a7012..0ab54c4 100644 --- a/Pods/PromiseKit/README.markdown +++ b/Pods/PromiseKit/README.markdown @@ -1,91 +1,27 @@ -Modern development is highly asynchronous: isn’t it about time iOS developers had tools that made programming asynchronously powerful, easy and delightful? - -**Vastly, copiously, vigorously documented at [promisekit.org](http://promisekit.org).** - ![PromiseKit](http://promisekit.org/public/img/tight-header.png) -```objc -UIActionSheet *sheet = …; -sheet.message = @"Share photo with your new local bestie?"; -sheet.promise.then(^(NSNumber *dismissedButtonIndex){ - if (dismissedButtonIndex.intValue == alert.cancelButtonIndex) - return; +Modern development is highly asynchronous: isn’t it about time iOS developers had tools that made programming asynchronously powerful, easy and delightful? - UIImagePickerController *picker = …; - [self promiseViewController:picker animated:YES completion: nil].then(^(UIImage *img, NSData *imgData){ +# How To Get Started - [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; - - return [CLLocationManager promise].then(^(CLLocation *located){ - return [NSURLConnection GET:@"share.com/token/%f/%f", located.latitude, located.longitude]; - }).finally(^{ - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - }).then(^(NSDictionary *json){ - // the JSON is automatically decoded +* Read PromiseKit’s [comprehensive learning guide](http://promisekit.org/introduction). +* Read the [API documentation](http://cocoadocs.org/docsets/PromiseKit/). +* [Integrate](http://promisekit.org/getting-started) promises into your existing projects. - MFMessageViewController *messagevc = …; - messagevc.to = json[@"to_email"]; - messagevc.body = json[@"message_text"]; - [messagevc addAttachmentData:imgData typeIdentifier:(NSString *)kUTTypeJPEG filename:@"image.jpeg"]; - - return [self promiseViewController:messagevc animated:YES completion:nil]; - }); - - }).catch(^(NSError *error){ - // because we returned promises in the above handler, any errors - // that may occur during execution of the chain will be caught here - [[UIAlertView:error] show]; - }); -}); +## How To Get Started… Quickly + +```ruby +# CocoaPods +pod "PromiseKit" # Objective-C PromiseKit +pod "PromiseKit/Promise" # Just PMKPromise, none of the categories + +pod "PromiseKit/Swift" # Swift PromiseKit +pod "PromiseKit/Swift/Promise" # Just Promise, none of the categories + +# Carthage +github "mxcl/PromiseKit" # Swift PromiseKit ``` -* PromiseKit can and should be integrated into the other Pods you use. -* PromiseKit is complete, well-tested and in apps on the store. +# Donations -For guides and complete documentation visit [promisekit.org](http://promisekit.org). - - -#Swift - -The Swift version of PromiseKit takes advantage of many new Swift features to make using PromiseKit even more delightful. - -To use the Swift version clone the project and drop the `xcodeproj` into your project. Once CocoaPods properly supports Swift frameworks, we will update the podspec accordingly. - -```swift -let sheet = UIAlertView(…) -sheet.message = "Share photo with your new local bestie?" -sheet.promise().then { dismissedButtonIndex in - if dismissedButtonIndex == alert.cancelButtonIndex - return - - let picker = UIImagePickerController(…) - promiseViewController(picker).then { (img, imgData) in - - UIApplication.sharedApplication().networkActivityIndicatorVisible = true - - return CLLocationManager.promise().then { located in - return NSURLConnection.GET("share.com/token/\(located.latitude)/\(located.longitude)") - }.finally { - UIApplication.sharedApplication().networkActivityIndicatorVisible = false - }.then { (json: NSDictionary) in - let messagevc = MFMessageViewController(…) - messagevc.to = json["to_email"] - messagevc.body = json["message_text"] - messagevc.addAttachmentData(imgData, typeIdentifier:kUTTypeJPEG, filename:"image.jpeg") - return promiseViewController(messagevc) - } - - }.catch { error in - // because we returned promises in the above handler, any errors - // that may occur during execution of the chain will be caught here - UIAlertView(error).show() - }) -}) -``` - -Sadly Swift promises cannot be used from Objective-C, but Objective-C promises can be used from Swift. Though if you do use Objective-C promises, be aware that they are tricky to use in Swift due to the unusual way PromiseKit uses Objective-C. - - -#Donations - -PromiseKit is almost completely the work of one man: me; [Max Howell](https://mxcl.github.io). I thoroughly enjoyed making PromiseKit, but nevertheless if you have found it useful then your bitcoin will give me a warm fuzzy feeling from my head right down to my toes: 1JDbV5zuym3jFw4kBCc5Z758maUD8e4dKR. +PromiseKit is hundreds of hours of work almost completely by just me: [Max Howell](https://twitter.com/mxcl). I thoroughly enjoyed making PromiseKit, but nevertheless if you have found it useful then your bitcoin will give me a warm fuzzy feeling from my head right down to my toes: 1JDbV5zuym3jFw4kBCc5Z758maUD8e4dKR. diff --git a/Pods/PromiseKit/objc/CALayer+PromiseKit.h b/Pods/PromiseKit/objc/CALayer+PromiseKit.h new file mode 100644 index 0000000..4b69f0b --- /dev/null +++ b/Pods/PromiseKit/objc/CALayer+PromiseKit.h @@ -0,0 +1,38 @@ +// +// CALayer+PromiseKit.h +// +// Created by María Patricia Montalvo Dzib on 24/11/14. +// Copyright (c) 2014 Aluxoft SCP. All rights reserved. +// + +#import +#import + +/** + To import the `CALayer` category: + + pod "PromiseKit/CALayer" + + Or you can import all categories on `QuartzCore`: + + pod "PromiseKit/QuartzCore" + + Or `CALayer` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ +@interface CALayer (PromiseKit) + +/** + Add the specified animation object to the layer’s render tree. + + @return A promise that thens two parameters: + 1. A boolean: `YES` if the animation progressed entirely to completion. + 2. the `CAAnimation` object. + + @see addAnimation:forKey +*/ +-(PMKPromise *)promiseAnimation:(CAAnimation *)animation forKey:(NSString *)key; + + +@end diff --git a/Pods/PromiseKit/objc/CALayer+PromiseKit.m b/Pods/PromiseKit/objc/CALayer+PromiseKit.m new file mode 100644 index 0000000..29385f1 --- /dev/null +++ b/Pods/PromiseKit/objc/CALayer+PromiseKit.m @@ -0,0 +1,41 @@ +// +// CALayer+PromiseKit.m +// +// Created by María Patricia Montalvo Dzib on 24/11/14. +// Copyright (c) 2014 Aluxoft SCP. All rights reserved. +// + +#import +#import +#import +#import "CALayer+PromiseKit.h" + + +@interface PMKCAAnimationDelegate : NSObject { + @public + void (^fullfiller)(id); +} +@end +@implementation PMKCAAnimationDelegate + +-(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { + fullfiller(PMKManifold(@(flag), anim)); + PMKRelease(self); +} + +@end + + +@implementation CALayer (PromiseKit) + +-(PMKPromise*) promiseAnimation:(CAAnimation*) animation forKey:(NSString*) key { + PMKCAAnimationDelegate* d = [[PMKCAAnimationDelegate alloc] init]; + PMKRetain(d); + animation.delegate = d; + [self addAnimation:animation forKey:key]; + return [PMKPromise new:^(PMKPromiseFulfiller fulfill, PMKPromiseRejecter reject) { + d->fullfiller = fulfill; + }]; +} + +@end diff --git a/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.h b/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.h index d2e7764..2ee0987 100644 --- a/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.h +++ b/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.h @@ -2,11 +2,30 @@ #import +/** + To import the `NSNotificationCenter` category: + + pod "PromiseKit/NSNotificationCenter" + + Or you can import all categories on `Foundation`: + + pod "PromiseKit/Foundation" + + Or `NSNotificationCenter` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ @interface NSNotificationCenter (PromiseKit) /** - Fires once for the named notification. + Observe the named notification once. + + @warning *Important* Promises only resolve once. If you need your block to execute more than once then use `-addObserverForName:object:queue:usingBlock:`. + + @param notificationName The name of the notification for which to register the observer. - thens the NSNotification object and the NSNotification’s userInfo as the second argument. + @returns A promise that fulfills with two parameters: + 1. The NSNotification object. + 2. The NSNotification’s userInfo property. */ + (PMKPromise *)once:(NSString *)notificationName; @end diff --git a/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.m b/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.m index 14c1b35..a82cc97 100644 --- a/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.m +++ b/Pods/PromiseKit/objc/NSNotificationCenter+PromiseKit.m @@ -1,3 +1,5 @@ +#import +#import #import "NSNotificationCenter+PromiseKit.h" #import "PromiseKit/Promise.h" diff --git a/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.h b/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.h index 69ae09d..9a7d4c8 100644 --- a/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.h +++ b/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.h @@ -6,19 +6,138 @@ extern NSString const*const PMKURLErrorFailingURLResponse PMK_DEPRECATED("Use PMKURLErrorFailingURLResponseKey"); extern NSString const*const PMKURLErrorFailingData PMK_DEPRECATED("Use PMKURLErrorFailingDataKey"); + +/** + To import the `NSURLConnection` category: + + pod "PromiseKit/NSURLConnection" + + Or you can import all categories on `Foudnation`: + + pod "PromiseKit/Foundation" + + Or `NSURLConnection` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" + + PromiseKit automatically deserializes the raw HTTP data response into the + appropriate rich data type based on the mime type the server provides. + Thus if the response is JSON you will get the deserialized JSON response. + PromiseKit supports decoding into strings, JSON and UIImages. + + PromiseKit goes to quite some lengths to provide good `NSError` objects + for error conditions at all stages of the HTTP to rich-data type + pipeline. We provide the following additional `userInfo` keys as + appropriate: + - `PMKURLErrorFailingDataKey` + - `PMKURLErrorFailingStringKey` + - `PMKURLErrorFailingURLResponseKey` + + PromiseKit uses [OMGHTTPURLRQ](https://github.com/mxcl/OMGHTTPURLRQ) to + make its HTTP requests. PromiseKit only provides a convenience layer + above OMGHTTPURLQ, thus if you need more power (eg. a multipartFormData + POST), use OMGHTTPURLRQ to generate the `NSURLRequest` and then pass + that request to `+promise:`. + + @see https://github.com/mxcl/OMGHTTPURLRQ +*/ @interface NSURLConnection (PromiseKit) /** - We depend on OMGHTTPURLRQ a NSURLRequest additions library that provides - all the common REST style verbs and parameter encoders. Thus if you need - eg. a multipartFormData POST, check out OMGHTTPURLRQ (which CocoaPods - already pulled in for you). -*/ + Makes a GET request to the provided URL. + @param urlStringFormatOrURL The `NSURL` or string format to request. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ + (PMKPromise *)GET:(id)urlStringFormatOrURL, ...; -+ (PMKPromise *)GET:(NSString *)string query:(NSDictionary *)parameters; + +/** + Makes a GET request with the provided query parameters. + + @param urlString The `NSURL` or URL string format to request. + @param parameters The parameters to be encoded as the query string for the GET request. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ ++ (PMKPromise *)GET:(NSString *)urlString query:(NSDictionary *)parameters; + +/** + Makes a POST request to the provided URL passing form URL encoded + parameters. + + Form URL-encoding is the standard way to POST on the Internet, so + probably this is what you want. If it doesn’t work, try the `+POST:JSON` + variant. + + @param urlString The URL to request. + @param parameters The parameters to be form URL-encoded and passed as the POST body. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ + (PMKPromise *)POST:(NSString *)urlString formURLEncodedParameters:(NSDictionary *)parameters; + +/** + Makes a POST request to the provided URL passing JSON encoded parameters. + + @param urlString The URL to request. + @param JSONParameters The parameters to be JSON encoded and passed as the POST body. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ ++ (PMKPromise *)POST:(NSString *)urlString JSON:(NSDictionary *)JSONParameters; + +/** + Makes a PUT request to the provided URL passing form URL-encoded + parameters. + + @param urlString The URL to request. + @param parameters The parameters to be form URL-encoded and passed as the HTTP body. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ + (PMKPromise *)PUT:(NSString *)urlString formURLEncodedParameters:(NSDictionary *)params; + +/** + Makes a PUT request to the provided URL passing form URL-encoded + parameters. + + @param urlString The URL to request. + @param parameters The parameters to be form URL-encoded and passed as the HTTP body. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ + (PMKPromise *)DELETE:(NSString *)urlString formURLEncodedParameters:(NSDictionary *)params; -+ (PMKPromise *)promise:(NSURLRequest *)rq; + +/** + Makes an HTTP request using the parameters specified the provided URL + request. + + @param request The URL request. + + @return A promise that fulfills with three parameters: + 1) The deserialized data response. + 2) The `NSHTTPURLResponse`. + 3) The raw `NSData` response. +*/ ++ (PMKPromise *)promise:(NSURLRequest *)request; + @end diff --git a/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.m b/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.m index d5fd9ea..5719afe 100644 --- a/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.m +++ b/Pods/PromiseKit/objc/NSURLConnection+PromiseKit.m @@ -6,8 +6,8 @@ #import #import #import "NSURLConnection+PromiseKit.h" -#import -#import +#import +#import #import "PromiseKit/Promise.h" NSString const*const PMKURLErrorFailingURLResponse = PMKURLErrorFailingURLResponseKey; @@ -40,6 +40,10 @@ NSString const*const PMKURLErrorFailingData = PMKURLErrorFailingDataKey; return [self promise:[OMGHTTPURLRQ POST:url:params]]; } ++ (PMKPromise *)POST:(NSString *)urlString JSON:(NSDictionary *)params { + return [self promise:[OMGHTTPURLRQ POST:urlString JSON:params]]; +} + + (PMKPromise *)PUT:(NSString *)url formURLEncodedParameters:(NSDictionary *)params { return [self promise:[OMGHTTPURLRQ PUT:url:params]]; } diff --git a/Pods/PromiseKit/objc/PMKPromise+When.m b/Pods/PromiseKit/objc/PMKPromise+When.m index 56d0316..1a5064f 100644 --- a/Pods/PromiseKit/objc/PMKPromise+When.m +++ b/Pods/PromiseKit/objc/PMKPromise+When.m @@ -22,7 +22,7 @@ __block NSUInteger count = [(id)promises count]; // FIXME if (count == 0) - return [PMKPromise promiseWithValue:@[]]; + return [PMKPromise promiseWithValue:promises]; // Keep a reference to the newly created // promise so we can check if it's resolved diff --git a/Pods/PromiseKit/objc/PMKPromise.m b/Pods/PromiseKit/objc/PMKPromise.m index ccbd13a..ceff4bf 100644 --- a/Pods/PromiseKit/objc/PMKPromise.m +++ b/Pods/PromiseKit/objc/PMKPromise.m @@ -7,6 +7,7 @@ #import #import #import +#import #import "Private/NSMethodSignatureForBlock.m" #import "PromiseKit/Promise.h" #import @@ -15,13 +16,83 @@ #define IsError(o) ([o isKindOfClass:[NSError class]]) #define PMKE(txt) [NSException exceptionWithName:@"PromiseKit" reason:@"PromiseKit: " txt userInfo:nil] +#ifndef PMKLog +#define PMKLog NSLog +#endif + static const id PMKNull = @"PMKNull"; -@interface PMKError : NSError -{ @public BOOL consumed; } -+ (instancetype):(id)foo; + + +@interface PMKArray : NSObject @end + + +static inline NSError *NSErrorFromNil() { + PMKLog(@"PromiseKit: Warning: Promise rejected with nil"); + return [NSError errorWithDomain:PMKErrorDomain code:PMKInvalidUsageError userInfo:nil]; +} + +static inline NSError *NSErrorFromException(id exception) { + if (!exception) + return NSErrorFromNil(); + + id userInfo = @{ + PMKUnderlyingExceptionKey: exception, + NSLocalizedDescriptionKey: [exception isKindOfClass:[NSException class]] + ? [exception reason] + : [exception description] + }; + return [NSError errorWithDomain:PMKErrorDomain code:PMKUnhandledExceptionError userInfo:userInfo]; +} + + + +@interface PMKError : NSObject @end @implementation PMKError { + NSError *error; + BOOL consumed; +} + +static void *PMKErrorAssociatedObject = &PMKErrorAssociatedObject; + +- (void)dealloc { + if (!consumed && PMKUnhandledErrorHandler) + PMKUnhandledErrorHandler(error); +} + ++ (void)consume:(NSError *)error { + PMKError *pmke = objc_getAssociatedObject(error, PMKErrorAssociatedObject); + pmke->consumed = YES; +} + ++ (void)unconsume:(NSError *)error { + PMKError *pmke = objc_getAssociatedObject(error, PMKErrorAssociatedObject); + + if (!pmke) { + pmke = [PMKError new]; + + // we take a copy to avoid a retain cycle. A weak ref + // is no good because then the error is deallocated + // before we can call PMKUnhandledErrorHandler() + pmke->error = [error copy]; + + // this is how we know when the error is deallocated + // because we will be deallocated at the same time + objc_setAssociatedObject(error, PMKErrorAssociatedObject, pmke, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + else + pmke->consumed = NO; +} + +@end + +void (^PMKUnhandledErrorHandler)(id) = ^(NSError *error){ + PMKLog(@"PromiseKit: Unhandled error: %@", error); +}; + + + // deprecated NSString const*const PMKThrown = PMKUnderlyingExceptionKey; @@ -31,7 +102,7 @@ NSString const*const PMKThrown = PMKUnderlyingExceptionKey; `then` and `catch` are method-signature tolerant, this function calls the block correctly and normalizes the return value to `id`. */ -static id safely_call_block(id frock, id result) { +id pmk_safely_call_block(id frock, id result) { assert(frock); if (result == PMKNull) @@ -115,7 +186,7 @@ static id safely_call_block(id frock, id result) { [e name] == NSPortReceiveException)) @throw e; #endif - return [PMKError:e]; + return NSErrorFromException(e); } } @@ -149,6 +220,12 @@ static id safely_call_block(id frock, id result) { }; } +- (PMKPromise *(^)(id))thenInBackground { + return ^(id block){ + return self.thenOn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block); + }; +} + - (PMKPromise *(^)(id))catch { return ^(id block){ return self.catchOn(dispatch_get_main_queue(), block); @@ -174,7 +251,7 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); // resolved state, the second for the pending state. - (id)resolved:(PMKResolveOnQueueBlock(^)(id result))mkresolvedCallback - pending:(void(^)(id result, PMKPromise *next, dispatch_queue_t q, id block, PMKPromiseFulfiller resolver))mkpendingCallback + pending:(void(^)(id result, PMKPromise *next, dispatch_queue_t q, id block, void (^resolver)(id)))mkpendingCallback { __block PMKResolveOnQueueBlock callBlock; __block id result; @@ -242,16 +319,15 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); block = [block copy]; return dispatch_promise_on(q, ^{ - return safely_call_block(block, result); + return pmk_safely_call_block(block, result); }); }; } - pending:^(id result, PMKPromise *next, dispatch_queue_t q, id block, PMKPromiseFulfiller resolve) { + pending:^(id result, PMKPromise *next, dispatch_queue_t q, id block, void (^resolve)(id)) { if (IsError(result)) - return PMKResolve(next, result); - - dispatch_async(q, ^{ - resolve(safely_call_block(block, result)); + PMKResolve(next, result); + else dispatch_async(q, ^{ + resolve(pmk_safely_call_block(block, result)); }); }]; } @@ -269,11 +345,8 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); block = [block copy]; return dispatch_promise_on(q, ^{ - id rv = safely_call_block(block, result); - if (rv != result) - // if the handler rethrows the same error, it is not consumed - ((PMKError *)result)->consumed = YES; - return rv; + [PMKError consume:result]; + return pmk_safely_call_block(block, result); }); }; @@ -281,14 +354,11 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); return [PMKPromise promiseWithValue:result]; }; } - pending:^(id result, PMKPromise *next, dispatch_queue_t q, id block, PMKPromiseFulfiller resolve) { + pending:^(id result, PMKPromise *next, dispatch_queue_t q, id block, void (^resolve)(id)) { if (IsError(result)) { dispatch_async(q, ^{ - id rv = safely_call_block(block, result); - if (rv != result) - // if the handler rethrows the same error, it is not consumed - ((PMKError *)result)->consumed = YES; - resolve(rv); + [PMKError consume:result]; + resolve(pmk_safely_call_block(block, result)); }); } else PMKResolve(next, result); @@ -312,13 +382,13 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); return passthru; }); }; - } pending:^(id passthru, PMKPromise *next, dispatch_queue_t q, dispatch_block_t block, PMKPromiseFulfiller resolve) { + } pending:^(id passthru, PMKPromise *next, dispatch_queue_t q, dispatch_block_t block, void (^resolve)(id)) { dispatch_async(q, ^{ @try { block(); resolve(passthru); } @catch (id e) { - resolve(e); + resolve(NSErrorFromException(e)); } }); }]; @@ -327,7 +397,7 @@ typedef PMKPromise *(^PMKResolveOnQueueBlock)(dispatch_queue_t, id block); + (PMKPromise *)promiseWithValue:(id)value { PMKPromise *p = [PMKPromise alloc]; p->_promiseQueue = PMKCreatePromiseQueue(); - p->_result = value ?: PMKNull; + p->_result = PMKSanitizeResult(value); return p; } @@ -343,12 +413,22 @@ static id PMKGetResult(PMKPromise *this) { return result; } +static id PMKSanitizeResult(id value) { + if (!value) + return PMKNull; + if (IsError(value)) + [PMKError unconsume:value]; + return value; +} + static NSArray *PMKSetResult(PMKPromise *this, id result) { __block NSArray *handlers; + result = PMKSanitizeResult(result); + dispatch_barrier_sync(this->_promiseQueue, ^{ handlers = this->_handlers; - this->_result = result ?: PMKNull; + this->_result = result; this->_handlers = nil; }); @@ -378,50 +458,85 @@ static void PMKResolve(PMKPromise *this, id result) { set(result); } -+ (instancetype)new:(void(^)(PMKPromiseFulfiller, PMKPromiseRejecter))block { ++ (instancetype)promiseWithResolver:(void (^)(PMKResolver))block { PMKPromise *this = [self alloc]; this->_promiseQueue = PMKCreatePromiseQueue(); this->_handlers = [NSMutableArray new]; - id fulfiller = ^(id value){ - if (PMKGetResult(this)) - return NSLog(@"PromiseKit: Promise already resolved"); - if (IsError(value)) - @throw PMKE(@"You may not fulfill a Promise with an NSError"); - - PMKResolve(this, value); - }; - - id rejecter = ^(id error){ - if (PMKGetResult(this)) - return NSLog(@"PromiseKit: Promise already resolved"); - if (IsPromise(error)) { - if ([error rejected]) { - error = ((PMKPromise *)error).value; - } else - @throw PMKE(@"You may not reject a Promise with a Promise"); - } - if (!error) - error = [PMKError errorWithDomain:PMKErrorDomain code:PMKUnknownError userInfo:nil]; - if (!IsError(error)) { - NSLog(@"PromiseKit: Warning: Reject promises with NSErrors!"); - error = [PMKError errorWithDomain:PMKErrorDomain code:PMKInvalidUsageError userInfo:@{ - NSLocalizedDescriptionKey: [error description] - }]; - } - - PMKResolve(this, [PMKError:error]); - }; - @try { - block(fulfiller, rejecter); + block(^(id result){ + if (PMKGetResult(this)) + return PMKLog(@"PromiseKit: Warning: Promise already resolved"); + + PMKResolve(this, result); + }); } @catch (id e) { - PMKSetResult(this, [PMKError:e]); + // at this point, no pointer to the Promise has been provided + // to the user, so we can’t have any handlers, so all we need + // to do is set _result. Technically using PMKSetResult is + // not needed either, but this seems better safe than sorry. + PMKSetResult(this, NSErrorFromException(e)); } return this; } ++ (instancetype)new:(void(^)(PMKFulfiller, PMKRejecter))block { + return [self promiseWithResolver:^(PMKResolver resolve) { + id rejecter = ^(id error){ + if (error == nil) { + error = NSErrorFromNil(); + } else if (IsPromise(error) && [error rejected]) { + // this is safe, acceptable and (basically) valid + } else if (!IsError(error)) { + id userInfo = @{NSLocalizedDescriptionKey: [error description], PMKUnderlyingExceptionKey: error}; + error = [NSError errorWithDomain:PMKErrorDomain code:PMKInvalidUsageError userInfo:userInfo]; + } + resolve(error); + }; + + id fulfiller = ^(id result){ + if (IsError(result)) + PMKLog(@"PromiseKit: Warning: PMKFulfiller called with NSError."); + resolve(result); + }; + + block(fulfiller, rejecter); + }]; +} + ++ (instancetype)promiseWithAdapter:(void (^)(PMKAdapter))block { + return [self promiseWithResolver:^(PMKResolver resolve) { + block(^(id value, id error){ + resolve(error ?: value); + }); + }]; +} + ++ (instancetype)promiseWithIntegerAdapter:(void (^)(PMKIntegerAdapter))block { + return [self promiseWithResolver:^(PMKResolver resolve) { + block(^(NSInteger value, id error){ + if (error) { + resolve(error); + } else { + resolve(@(value)); + } + }); + }]; +} + ++ (instancetype)promiseWithBooleanAdapter:(void (^)(PMKBooleanAdapter adapter))block { + return [self promiseWithResolver:^(PMKResolver resolve) { + block(^(BOOL value, id error){ + if (error) { + resolve(error); + } else { + resolve(@(value)); + } + }); + }]; +} + - (BOOL)pending { id result = PMKGetResult(self); if (IsPromise(result)) { @@ -490,7 +605,7 @@ PMKPromise *dispatch_promise(id block) { PMKPromise *dispatch_promise_on(dispatch_queue_t queue, id block) { return [PMKPromise new:^(void(^fulfiller)(id), void(^rejecter)(id)){ dispatch_async(queue, ^{ - id result = safely_call_block(block, nil); + id result = pmk_safely_call_block(block, nil); if (IsError(result)) rejecter(result); else @@ -500,11 +615,23 @@ PMKPromise *dispatch_promise_on(dispatch_queue_t queue, id block) { } +@implementation PMKArray { +@public id objs[3]; +@public NSUInteger count; +} -@implementation PMKArray { NSUInteger count; id objs[3]; } +- (id)objectAtIndexedSubscript:(NSUInteger)idx { + if (count <= idx) { + // this check is necessary due to lack of checks in `pmk_safely_call_block` + return nil; + } + return objs[idx]; +} -+ (instancetype)arrayWithCount:(NSUInteger)count, ... { - PMKArray *this = [self new]; +@end + +id __PMKArrayWithCount(NSUInteger count, ...) { + PMKArray *this = [PMKArray new]; this->count = count; va_list args; va_start(args, count); @@ -514,42 +641,6 @@ PMKPromise *dispatch_promise_on(dispatch_queue_t queue, id block) { return this; } -- (id)objectAtIndexedSubscript:(NSUInteger)idx { - if (count <= idx) { - // this check is necessary due to lack of checks in `safely_call_block` - return nil; - } - return objs[idx]; -} - -@end - - - -@implementation PMKError - -+ (instancetype):(id)foo { - if ([foo isKindOfClass:[PMKError class]]) - return foo; - if ([foo isKindOfClass:[NSError class]]) - return [PMKError errorWithDomain:[foo domain] ?: PMKErrorDomain code:[foo code] userInfo:[foo userInfo]]; - else { - id userInfo = [NSMutableDictionary new]; - userInfo[PMKUnderlyingExceptionKey] = foo; - userInfo[NSLocalizedDescriptionKey] = [foo isKindOfClass:[NSException class]] - ? [foo reason] - : [foo description]; - return [PMKError errorWithDomain:PMKErrorDomain code:PMKUnhandledExceptionError userInfo:userInfo]; - } -} - -- (void)dealloc { - if (!consumed) - NSLog(@"PromiseKit: Unhandled error: %@", self); -} - -@end - NSOperationQueue *PMKOperationQueue() { diff --git a/Pods/PromiseKit/objc/Private/NSMethodSignatureForBlock.m b/Pods/PromiseKit/objc/Private/NSMethodSignatureForBlock.m index b3df0ab..11bceb2 100644 --- a/Pods/PromiseKit/objc/Private/NSMethodSignatureForBlock.m +++ b/Pods/PromiseKit/objc/Private/NSMethodSignatureForBlock.m @@ -64,6 +64,10 @@ static NSMethodSignature *NSMethodSignatureForBlock(id block) { const char *signature = (*(const char **)signatureLocation); #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 signature = pmk_removeQuotesFromMethodSignature(signature); + NSMethodSignature *nsSignature = [NSMethodSignature signatureWithObjCTypes:signature]; + free((void *)signature); + + return nsSignature; #endif return [NSMethodSignature signatureWithObjCTypes:signature]; } diff --git a/Pods/PromiseKit/objc/Private/xctest.rb b/Pods/PromiseKit/objc/Private/xctest.rb deleted file mode 100755 index 21ca174..0000000 --- a/Pods/PromiseKit/objc/Private/xctest.rb +++ /dev/null @@ -1,121 +0,0 @@ -FRAMEWORKS = begin - attempt1 = "/Applications/Xcode.app/Contents/Developer/Library/Frameworks" - if File.directory? "#{attempt1}/XCTest.framework" - attempt1 - else - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks" - end -end - -def bold(s); s; end -def red(s); "\e[31m#{s}\e[0m"; end -def green(s); "\e[32m#{s}\e[0m"; end -def tab(n, s); s.gsub(/^/, " " * n); end -def log(message); $stdout.puts(message); end - -def each_test_line - require "stringio" - require "open3" - - Open3.popen3("/tmp/PromiseKitTests") do |stdin, stdout, stderr, wait_thr| - while line = stderr.gets - yield line, stderr - end - exit_status = wait_thr.value - end -end - -def test! - test_method = nil - each_test_line do |line, stderr| - case line - when /Test Suite '(.*)' started/ - log bold($1) unless $1 == 'tmp' - when /Test Suite '.*' finished/ - when /\[(\w+) (\w+)\]' started.$/ - test_method = $2 - when /\s(passed|failed)\s\((.*)\)/ - result = if $1 == "passed" - green("PASS") - else - red("FAIL") - end - result = tab(2, result) - time = $2.gsub(/\sseconds/, "s") - log "#{result} #{test_method} (#{time})" - when /^(Executed(.?)+)$/ - if stderr.eof? - summary = $1 - if /(\d+) failures?/.match(summary)[1] == "0" - summary.gsub!(/(\d+ failures?)/, green('\1')) - else - summary.gsub!(/(\d+ failures?)/, red('\1')) - end - log summary - end - else - log line.strip - end - end -end - -def clone! repo - Dir.chdir "/tmp" do - system "git clone #{repo}" - end unless File.directory? "/tmp/#{File.basename(repo)}" -end - -def prepare! - clone! "https://github.com/mxcl/ChuzzleKit" - clone! "https://github.com/mxcl/OMGHTTPURLRQ" - - File.open('/tmp/PromiseKitTests.m', 'w') do |f| - f.puts # make line numbers correlate - f.puts - f.puts(OBJC.sub('#define URL', "#define URL @\"file:///tmp/hi.text\"")) - end - - File.open('/tmp/hi.text', 'w') do |f| - f.print("hi") - end -end - -def compile! - abort unless system <<-EOS - clang -g -O0 -ObjC -F#{FRAMEWORKS} -I. -fmodules -fobjc-arc \ - -framework XCTest \ - -isystem/tmp/ChuzzleKit -isystem/tmp/OMGHTTPURLRQ \ - /tmp/PromiseKitTests.m \ - NSURLConnection+PromiseKit.m PMKPromise.m PMKPromise+When.m PMKPromise+Until.m \ - /tmp/ChuzzleKit/*.m /tmp/OMGHTTPURLRQ/*.m \ - -Wall -Weverything -Wno-unused-parameter -Wno-missing-field-initializers \ - -Wno-documentation -Wno-gnu-conditional-omitted-operand \ - -Wno-pointer-arith -Wno-disabled-macro-expansion \ - -Wno-gnu-statement-expression -Wno-strict-selector-match -Wno-vla \ - -Wno-selector -Wno-missing-prototypes -Wno-direct-ivar-access \ - -Wno-missing-noreturn -Wno-pedantic \ - -Wno-format-nonliteral \ - -Wno-incomplete-module -Wno-objc-interface-ivars \ - -Wno-auto-import \ - -headerpad_max_install_names \ - -o /tmp/PromiseKitTests - EOS - abort unless system <<-EOS - install_name_tool -change \ - @rpath/XCTest.framework/Versions/A/XCTest \ - #{FRAMEWORKS}/XCTest.framework/XCTest \ - /tmp/PromiseKitTests - EOS -end - -prepare! -compile! - -if not ARGV.include? '-d' - exit! test!.exitstatus -else - system "lldb /tmp/PromiseKitTests" - File.delete("/tmp/PromiseKitTests.m") - File.delete("/tmp/PromiseKitTests") - exit! 0 -end diff --git a/Pods/PromiseKit/objc/PromiseKit.h b/Pods/PromiseKit/objc/PromiseKit.h index 5628f49..6b9014a 100644 --- a/Pods/PromiseKit/objc/PromiseKit.h +++ b/Pods/PromiseKit/objc/PromiseKit.h @@ -9,6 +9,9 @@ #ifdef PMK_PAUSE #import #endif +#ifdef PMK_JOIN +#import +#endif #ifdef PMK_ACACCOUNTSTORE #import diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise+Hang.h b/Pods/PromiseKit/objc/PromiseKit/Promise+Hang.h new file mode 100644 index 0000000..88cfca9 --- /dev/null +++ b/Pods/PromiseKit/objc/PromiseKit/Promise+Hang.h @@ -0,0 +1,18 @@ +#import + +/** + To import `+hang:`: + + pod "PromiseKit/Hang" +*/ +@interface PMKPromise (Hang) + +/** + Literally hangs this thread until the promise has resolved. By all means + use this for testing and debugging, but please! Don’t leave `hang` in + production code! It could literally *hang* your app! The implementation + uses {CF|NS}RunLoop. +*/ ++ (id)hang:(PMKPromise *)promise; + +@end diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise+Join.h b/Pods/PromiseKit/objc/PromiseKit/Promise+Join.h new file mode 100644 index 0000000..fa96eb5 --- /dev/null +++ b/Pods/PromiseKit/objc/PromiseKit/Promise+Join.h @@ -0,0 +1,28 @@ +#import +#import + + +@interface PMKPromise (Join) +/** + Creates a new promise that resolves only when all provided promises have resolved. + + Typically, you should use `+when:`. + + @param promises An array of promises. + + @return A promise that thens two parameters: + + 1) An array of values from the promises that fulfilled. + 2) An array of errors from the promises that rejected or nil if all promises fulfilled. + + This promise is not rejectable. + + @warning *Important* It is not possible to know which promises fulfilled and which rejected. + + pod "PromiseKit/join" + + @see when +*/ ++ (PMKPromise *)join:(NSArray *)promises; + +@end diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise+Pause.h b/Pods/PromiseKit/objc/PromiseKit/Promise+Pause.h index b8894c7..f1ac427 100644 --- a/Pods/PromiseKit/objc/PromiseKit/Promise+Pause.h +++ b/Pods/PromiseKit/objc/PromiseKit/Promise+Pause.h @@ -1,19 +1,32 @@ #import - +#import @interface PMKPromise (Pause) /** - Pauses the chain by the specified number of seconds. + Pauses the chain for the specified number of seconds. - Pipes the value from the parent promise to child promises. The second `then` - value is the `duration` of the pause. + @parameter duration The duration in seconds to wait before resolving this promise. + + @return A new promise fulfilled with two parameters: + 1. The previous promise’s fulfillment. + 2. The duration the chain was suspended. + + For example: + + [PMKPromise promiseWithValue:@"mxcl"].pause(1.5).then(^(NSString *string, NSNumber *duration){ + // string => @"mxcl" + // duration => @1.5 + }); + + @warning *Caveat* Any promise that was previously resolved with `PMKManifold` will lose + parameters beyond the first parameter. */ -- (PMKPromise *(^)(NSTimeInterval))pause; +- (PMKPromise *(^)(NSTimeInterval duration))pause; /** - Returns a new promise that fulfills with @p `duration` after `duration` - seconds have passed. Internally uses `dispatch_after`. + @param duration The duration in seconds to wait before resolving this promise. + @return A promise that thens the duration it waited before resolving. */ + (PMKPromise *)pause:(NSTimeInterval)duration; diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise+When.h b/Pods/PromiseKit/objc/PromiseKit/Promise+When.h index f2a4bd9..ecd2f32 100644 --- a/Pods/PromiseKit/objc/PromiseKit/Promise+When.h +++ b/Pods/PromiseKit/objc/PromiseKit/Promise+When.h @@ -4,20 +4,25 @@ @interface PMKPromise (When) /** -Returns a new Promise that is resolved when all passed Promises are resolved. +Returns a new promise that is fulfilled if and when all the provided promises are fulfilled. -If an array is passed then the returned `Promise` is resolved once all of the `Promise`s in the array are resolved. The returned Promise is rejected immediately if *any* of the `Promise`s received by `when` fail, discarding all other Promise values (thus you only get one error in any catch handler you provide). +@param promiseOrArrayOfPromisesOrValue The input upon which to wait before resolving this promise. -The returned `Promise` is resolved with an array of results indexed as the original array passed to when. If you pass a single value to when, you will not get an array in subsequent `then`s. +If an array is passed then the returned promise is fulfilled once all the provided promises are fulfilled. If *any* of the provided promises reject, the returned promise is immediately rejected with that promise’s rejection error. -@param promiseOrArrayOfPromisesOrValue an array of Promises, a single Promise or a single value of any type. +@return A promise that is resolved with either: +1. An array of values from the provided array of promises. +2. The value from the provided promise. +3. The provided non-promise object. + +Note that passing an `NSError` to when will reject the returned promise. */ + (PMKPromise *)when:(id)promiseOrArrayOfPromisesOrValue; /** - Same as when, though only takes an object that implements `NSFastEnumeration` (`NSArray` implements `NSFastEnumeration`) + Alias for `+when:` provided due to ES6 specifications. - Alias provided due to ES6 specifications. + @see when */ + (PMKPromise *)all:(id)enumerable; diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise+Zalgo.h b/Pods/PromiseKit/objc/PromiseKit/Promise+Zalgo.h new file mode 100644 index 0000000..5c4fc65 --- /dev/null +++ b/Pods/PromiseKit/objc/PromiseKit/Promise+Zalgo.h @@ -0,0 +1,35 @@ +#import + + +/** + Executes block immediately if we are not on the main thread. Otherwise + dispatches to the default background queue first. + + Do not use this function unless you understand the implications of + unleashing zalgo! + + This function is provided mainly as an optimization tool for *libraries* + that provide promises. Typically, it is not worth the risk to use this + function in your own code, the performance gains are negligible relative + to the risk of damaging the integrity of your asynchronous logic. + + @see dispatch_promise +*/ +PMKPromise *dispatch_zalgo(id block); + + +@interface PMKPromise (Zalgo) + +/** + Executes the block immediately if the promise is already resolved. + Otherwise behaves like `then`. + + Do not use this function unless you understand the implications of + unleashing zalgo! + + @see then + @see dispatch_zalgo +*/ +- (PMKPromise *(^)(id))thenUnleashZalgo; + +@end diff --git a/Pods/PromiseKit/objc/PromiseKit/Promise.h b/Pods/PromiseKit/objc/PromiseKit/Promise.h index 874fb51..91cad6e 100644 --- a/Pods/PromiseKit/objc/PromiseKit/Promise.h +++ b/Pods/PromiseKit/objc/PromiseKit/Promise.h @@ -4,91 +4,230 @@ #import /** -A `Promise` represents the future value of a task. + A promise represents the future value of a task. -To obtain the value of a `Promise`, call `then`. When the asynchronous task that this `Promise` represents has resolved successfully, the block you pass to `then` will be executed with the resolved value. If the `Promise` has already been resolved succesfully at the time you `then` the `Promise`, the block will be executed immediately. + To obtain the value of a promise we call `then`. -Effective use of Promises involves chaining `then`s, where the return value from one `then` is fed as the value of the next, et cetera. + Promises are chainable: `then` returns a promise, you can call `then` on that promise, which returns a promise, you can call `then` on that promise, et cetera. -For a thorough overview of Promises, @see http://promisekit.org + Promises start in a pending state: they have `nil` value. Promises *resolve* to become *fulfilled* or *rejected*. A rejected promise has an `NSError` for its value, a fulfilled promise has any other object as its value. + + @see [PromiseKit `then` Guide](http://promisekit.org/then/) + @see [PromiseKit Chaining Guide](http://promisekit.org/chaining/) */ @interface PMKPromise : NSObject /** -The pattern of Promises is defined by the method: `then`. + The provided block is executed when its receiver is resolved. -Provide a block to `then`, your block may take one or no arguments, and return an object or have no return value. We use block introspection to provide such flexibility. + If you provide a block that takes a parameter, the value of the receiver will be passed as that parameter. -Returning from your block will resolve the next `Promise` with that value. + @param block The block that is executed when the receiver is resolved. -If an exception is thrown inside your block, or you return an `NSError` object the next `Promise` will be rejected. @see `catch` for documentation on error handling. + [NSURLConnection GET:url].then(^(NSData *data){ + // do something with data + }); -Then is always executed on the main dispatch queue (i.e the main/UI thread). + @return A new promise that is resolved with the value returned from the provided block. For example: -@see `-thenOn` + [NSURLConnection GET:url].then(^(NSData *data){ + return data.length; + }).then(^(NSNumber *number){ + //… + }); -@return A new `Promise` to be executed after the block passed to this `then` + @warning *Important* The block passed to `then` may take zero, one, two or three arguments, and return an object or return nothing. This flexibility is why the method signature for then is `id`, which means you will not get completion for the block parameter, and must type it yourself. It is safe to type any block syntax here, so to start with try just: `^{}`. + + @warning *Important* If an exception is thrown inside your block, or you return an `NSError` object the next `Promise` will be rejected. See `catch` for documentation on error handling. + + @warning *Important* `then` is always executed on the main queue. + + @see thenOn + @see thenInBackground */ - (PMKPromise *(^)(id))then; /** + The provided block is executed on the default queue when the receiver is fulfilled. + + This method is provided as a convenience for `thenOn`. + + @see then + @see thenOn + */ +- (PMKPromise *(^)(id))thenInBackground; + +/** + The provided block is executed when the receiver is rejected. + + Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either. + The provided block always runs on the main queue. + + @see catchOn */ - (PMKPromise *(^)(id))catch; /** + The provided block is executed when the receiver is resolved. + The provided block always runs on the main queue. + + @see catchOn */ - (PMKPromise *(^)(void(^)(void)))finally; /** - The provided block is executed on the dispatch queue of your choice. + The provided block is executed on the dispatch queue of your choice when the receiver is fulfilled. + + @see then + @see thenInBackground */ - (PMKPromise *(^)(dispatch_queue_t, id))thenOn; /** - The provided block is executed on the dispatch queue of your choice. + The provided block is executed on the dispatch queue of your choice when the receiver is rejected. + + @see catch */ - (PMKPromise *(^)(dispatch_queue_t, id))catchOn; /** - The provided block is executed on the dispatch queue of your choice. + The provided block is executed on the dispatch queue of your choice when the receiver is resolved. + + @see finally */ - (PMKPromise *(^)(dispatch_queue_t, void(^)(void)))finallyOn; -/** -@return A new `Promise` that is already resolved with @param value. Calling `then` on a resolved `Promise` executes the provided block immediately. +/** + Creates a resolved promise. -Note that passing an `NSError` object is valid usage and will reject this promise. + When developing your own promise systems, it is ocassionally useful to be able to return an already resolved promise. + + @param value The value with which to resolve this promise. Passing an `NSError` will cause the promise to be rejected, otherwise the promise will be fulfilled. + + @return A resolved promise. */ + (PMKPromise *)promiseWithValue:(id)value; +/// @return `YES` if the promise has not yet resolved. - (BOOL)pending; -/** - A resolved promise is not pending. It is either fulfilled, or - rejected. -**/ +/// @return `YES` if the promise has resolved (ie. is fulfilled or rejected) `NO` if it is pending. - (BOOL)resolved; + +/// @return `YES` if the promise is fulfilled, `NO` if it is rejected or pending. - (BOOL)fulfilled; + +/// @return `YES` if the promise is rejected, `NO` if it is fulfilled or pending. - (BOOL)rejected; /** - A promise has a nil value if it is pending. A promise is still - pending if the `then` or `catch` that created this promise - returned a `Promise`. + The value of the asynchronous task this promise represents. + + A promise has `nil` value if the asynchronous task it represents has not + finished. If the value is `nil` the promise is still `pending`. + + @returns If `resolved` the object that was used to resolve this promise, + if `pending` nil. */ - (id)value; /** - Create a new root Promise. + Create a new promise that is fulfilled or rejected with the provided + blocks. - Pass a block to this constructor, the block must take two arguments that point to the `fulfiller` and `rejecter` of this Promise. Fulfill or reject this Promise using those blocks and the Promise chain that roots to this Promise will be resolved accordingly. + Use this method when wrapping asynchronous code that does *not* use + promises so that this code can be used in promise chains. - Should you need to fulfill a promise but have no sensical value to use; fulfill with `nil`. + Don’t use this method if you already have promises! Instead, just + return your promise. + + @param block The provided block is immediately executed, any exceptions that occur will be caught and cause the returned promise to be rejected. + - @param fulfill fulfills the returned promise with the provided value + - @param reject rejects the returned promise with the provided `NSError` + + Should you need to fulfill a promise but have no sensical value to use; + your promise is a `void` promise: fulfill with `nil`. + + The block you pass is executed immediately on the calling thread. + + @return A new promise. + + @see http://promisekit.org/sealing-your-own-promises/ + @see http://promisekit.org/wrapping-delegation/ */ -+ (instancetype)new:(void(^)(PMKPromiseFulfiller fulfill, PMKPromiseRejecter reject))block; ++ (instancetype)new:(void(^)(PMKFulfiller fulfill, PMKRejecter reject))block; + +/** + Create a new promise that is resolved with the provided block. + + Use this method when wrapping asynchronous code that does *not* use + promises so that this code can be used in promise chains. + + Javascript promise libraries are the basis of most modern implementations + hence the signature of `+new:`. Such libraries allow anything to fulfill + or reject promises. Since in PromiseKit we only allow promises to be + rejected by `NSError` objects, we can determine the promise state with + one rather than two blocks. + + Pass an `NSError` object to reject the promise, and anything else to + fulfill it. + + return [PMKPromise promiseWithResolver:^(PMKResolver resolve){ + PFQuery *query = [PFQuery …]; + [query findObjectsInBackgroundWithBlock:^(id objs, id error){ + resolve(objs ?: error); + }]; + }]; + + @warning *Important* Resolving a promise with `nil` fulfills it. + + @see http://promisekit.org/sealing-your-own-promises/ +*/ ++ (instancetype)promiseWithResolver:(void (^)(PMKResolver resolve))block; + +/** + Create a new promise by adapting an existing asynchronous system. + + The pattern of a completion block that passes two parameters, the first + the result and the second an `NSError` object is so common that we + provide this convenience adapter to make wrapping such systems more + elegant. + + return [PMKPromise promiseWithAdapter:^(PMKAdapter adapter){ + PFQuery *query = [PFQuery …]; + [query findObjectsInBackgroundWithBlock:adapter]; + }]; + + @warning *Important* If both parameters are nil, the promise fulfills, + if both are non-nil the promise rejects. This is per the convention. + + @see http://promisekit.org/sealing-your-own-promises/ +*/ ++ (instancetype)promiseWithAdapter:(void (^)(PMKAdapter adapter))block; + +/** + Create a new promise by adapting an existing asynchronous system. + + Adapts asynchronous systems that complete with `^(NSInteger, NSError *)`. + NSInteger will cast to enums provided the enum has been wrapped with + `NS_ENUM`. All of Apple’s enums are, so if you find one that hasn’t you + may need to make a pull-request. + + @see promiseWithAdapter +*/ ++ (instancetype)promiseWithIntegerAdapter:(void (^)(PMKIntegerAdapter adapter))block; + +/** + Create a new promise by adapting an existing asynchronous system. + + Adapts asynchronous systems that complete with `^(BOOL, NSError *)`. + + @see promiseWithAdapter +*/ ++ (instancetype)promiseWithBooleanAdapter:(void (^)(PMKBooleanAdapter adapter))block; @end @@ -105,27 +244,39 @@ Note that passing an `NSError` object is valid usage and will reject this promis Currently PromiseKit limits you to THREE parameters to the manifold. */ #define PMKManifold(...) __PMKManifold(__VA_ARGS__, 3, 2, 1) -#define __PMKManifold(_1, _2, _3, N, ...) [PMKArray arrayWithCount:N, _1, _2, _3] -@interface PMKArray : NSObject -// returning `id` to avoid compiler issues: https://github.com/mxcl/PromiseKit/issues/76 -+ (id)arrayWithCount:(NSUInteger)count, ...; -@end - +#define __PMKManifold(_1, _2, _3, N, ...) __PMKArrayWithCount(N, _1, _2, _3) +extern id __PMKArrayWithCount(NSUInteger, ...); /** -Executes @param block via `dispatch_async` with `DISPATCH_QUEUE_PRIORITY_DEFAULT`. + Executes the provided block on a background queue. -The returned `Promise` is resolved with the value returned from @param block (if any). Any `then` or `catch` attached to the returned `Promise` is exectued on the main queue. + dispatch_promise is a convenient way to start a promise chain where the + first step needs to run synchronously on a background queue. -@param block A block to be executed in the background. -@return A new `Promise` to be executed after @param block. + @param block The block to be executed in the background. Returning an `NSError` will reject the promise, everything else (including void) fulfills the promise. + + @return A promise resolved with the provided block. + + @see dispatch_async */ PMKPromise *dispatch_promise(id block); /** - Executes @param block via `dispatch_async` on the specified queue. + Executes the provided block on the specified queue. + @see dispatch_promise - */ + @see dispatch_async +*/ PMKPromise *dispatch_promise_on(dispatch_queue_t q, id block); + + + +/** + Called by PromiseKit in the event of unhandled errors. + The default handler NSLogs the error. Note, your handler is executed + from an undefined queue, unless you manage thread-safe data, dispatch to + a safe queue before doing anything else in your handler. +*/ +extern void (^PMKUnhandledErrorHandler)(NSError *); diff --git a/Pods/PromiseKit/objc/PromiseKit/fwd.h b/Pods/PromiseKit/objc/PromiseKit/fwd.h index cd07550..808b89f 100644 --- a/Pods/PromiseKit/objc/PromiseKit/fwd.h +++ b/Pods/PromiseKit/objc/PromiseKit/fwd.h @@ -1,3 +1,7 @@ +#import + +@class NSError; +@class NSString; @class NSOperationQueue; @class PMKPromise; @@ -21,6 +25,12 @@ typedef void (^PromiseFulfiller)(id) PMK_DEPRECATED("Use PMKPromiseFulfiller"); typedef void (^PromiseRejecter)(NSError *) PMK_DEPRECATED("Use PMKPromiseRejecter"); typedef void (^PMKPromiseFulfiller)(id); typedef void (^PMKPromiseRejecter)(NSError *); +typedef void (^PMKFulfiller)(id); +typedef void (^PMKRejecter)(NSError *); +typedef void (^PMKResolver)(id); +typedef void (^PMKAdapter)(id, NSError *); +typedef void (^PMKIntegerAdapter)(NSInteger, NSError *); +typedef void (^PMKBooleanAdapter)(BOOL, NSError *); #define PMKErrorDomain @"PMKErrorDomain" #define PMKUnderlyingExceptionKey @"PMKUnderlyingExceptionKey" diff --git a/Pods/PromiseKit/objc/UIActionSheet+PromiseKit.h b/Pods/PromiseKit/objc/UIActionSheet+PromiseKit.h index d7b9738..92159e6 100644 --- a/Pods/PromiseKit/objc/UIActionSheet+PromiseKit.h +++ b/Pods/PromiseKit/objc/UIActionSheet+PromiseKit.h @@ -1,10 +1,30 @@ #import #import -@interface UIActionSheet (PromiseKit) /** - Thens the dismissedButtonIndex and the actionSheet itself as the second - parameter. This promise will never be rejected. - */ + To import the `UIActionSheet` category: + + pod "PromiseKit/UIActionSheet" + + Or you can import all categories on `UIKit`: + + pod "PromiseKit/UIKit" + + Or `UIKit` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ +@interface UIActionSheet (PromiseKit) + +/** + Displays the action sheet originating from the specified view. + + @param view The view from which the action sheet originates. + + @return A promise the fulfills with two parameters: + 1) The index of the button that was tapped to dismiss the sheet. + 2) This action sheet. +*/ - (PMKPromise *)promiseInView:(UIView *)view; + @end diff --git a/Pods/PromiseKit/objc/UIAlertView+PromiseKit.h b/Pods/PromiseKit/objc/UIAlertView+PromiseKit.h index 24b5386..25cd60a 100644 --- a/Pods/PromiseKit/objc/UIAlertView+PromiseKit.h +++ b/Pods/PromiseKit/objc/UIAlertView+PromiseKit.h @@ -1,10 +1,28 @@ #import #import -@interface UIAlertView (PromiseKit) /** - Thens the dismissedButtonIndex and the alertView itself as the second - parameter. This promise will never be rejected. - */ + To import the `UIAlertView` category: + + pod "PromiseKit/UIAlertView" + + Or you can import all categories on `UIKit`: + + pod "PromiseKit/UIKit" + + Or `UIKit` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ +@interface UIAlertView (PromiseKit) + +/** + Displays the alert view. + + @return A promise the fulfills with two parameters: + 1) The index of the button that was tapped to dismiss the alert. + 2) This alert view. +*/ - (PMKPromise *)promise; + @end diff --git a/Pods/PromiseKit/objc/UIView+PromiseKit.h b/Pods/PromiseKit/objc/UIView+PromiseKit.h index 86bee9e..7c4fa29 100644 --- a/Pods/PromiseKit/objc/UIView+PromiseKit.h +++ b/Pods/PromiseKit/objc/UIView+PromiseKit.h @@ -4,6 +4,19 @@ // Created by Masafumi Yoshida on 2014/07/11. // Copyright (c) 2014年 DeNA. All rights reserved. +/** + To import the `UIView` category: + + pod "PromiseKit/UIView" + + Or you can import all categories on `UIKit`: + + pod "PromiseKit/UIKit" + + Or `UIKit` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ @interface UIView (PromiseKit) /** diff --git a/Pods/PromiseKit/objc/UIViewController+PromiseKit.h b/Pods/PromiseKit/objc/UIViewController+PromiseKit.h index 567fa35..3f37873 100644 --- a/Pods/PromiseKit/objc/UIViewController+PromiseKit.h +++ b/Pods/PromiseKit/objc/UIViewController+PromiseKit.h @@ -1,22 +1,53 @@ #import #import +/** + To import the `UIViewController` category: + + pod "PromiseKit/UIViewController" + + Or you can import all categories on `UIKit`: + + pod "PromiseKit/UIKit" + + Or `UIKit` is one of the categories imported by the umbrella pod: + + pod "PromiseKit" +*/ @interface UIViewController (PromiseKit) /** + Presents a view controller modally. + Calls `presentViewController:` such that the presentedViewController can call `reject:` or `fulfill:` and resolve the promise. When resolved the presentedViewController is dismissed. - This method is smart and SDK provided ViewControllers like - `MFMailComposeViewController` will be automatically delegate into the - returned Promise. + PromiseKit goes the extra mile and automatically handles the delegation + or completion handlers for the following CocoaTouch view controllers: + + - MFMailComposeViewController + - UIImagePickerController + - SLComposeViewController + + @return A promise that can be fulfilled by the presented view controller. */ - (PMKPromise *)promiseViewController:(UIViewController *)vc animated:(BOOL)animated completion:(void(^)(void))block NS_AVAILABLE_IOS(5_0); +/** + View controllers presented with promiseViewController:animated:completion: + can call this method to dismiss themselves and fulfill the promise they + were presented with. +*/ - (void)fulfill:(id)result; + +/** + View controllers presented with promiseViewController:animated:completion: + can call this method to dismiss themselves and reject the promise they + were presented with. +*/ - (void)reject:(NSError *)error; -- (PMKPromise *)promiseSegueWithIdentifier:(NSString*) identifier sender:(id) sender NS_AVAILABLE_IOS(5_0); +- (PMKPromise *)promiseSegueWithIdentifier:(NSString*) identifier sender:(id) sender NS_AVAILABLE_IOS(5_0) PMK_DEPRECATED("This method is considered unsafe and will be removed."); @end diff --git a/Pods/PromiseKit/objc/UIViewController+PromiseKit.m b/Pods/PromiseKit/objc/UIViewController+PromiseKit.m index 33b4d3e..ffbb2ec 100644 --- a/Pods/PromiseKit/objc/UIViewController+PromiseKit.m +++ b/Pods/PromiseKit/objc/UIViewController+PromiseKit.m @@ -2,6 +2,7 @@ #import #import #import "PromiseKit/Promise.h" +#import #import #import #import "UIViewController+PromiseKit.h" @@ -116,7 +117,7 @@ static void classOverridingSelector(const char* newClassPrefix, id target, SEL o struct objc_super objcSuper; objcSuper.receiver = self; objcSuper.super_class = zuper; - objc_msgSendSuper(&objcSuper, prepareForSegueSelector, segue, sender); + ((void(*)(id, SEL, id, id))objc_msgSendSuper)((__bridge id)(&objcSuper), prepareForSegueSelector, segue, sender); } } diff --git a/Pods/PromiseKit/objc/deprecated/PromiseKit+Foundation.h b/Pods/PromiseKit/objc/deprecated/PromiseKit+Foundation.h deleted file mode 100644 index 556b67a..0000000 --- a/Pods/PromiseKit/objc/deprecated/PromiseKit+Foundation.h +++ /dev/null @@ -1,4 +0,0 @@ -#warning This header is deprecated, #import instead. - -#import -#import diff --git a/Pods/PromiseKit/objc/deprecated/PromiseKit+UIKit.h b/Pods/PromiseKit/objc/deprecated/PromiseKit+UIKit.h deleted file mode 100644 index 79b3c4b..0000000 --- a/Pods/PromiseKit/objc/deprecated/PromiseKit+UIKit.h +++ /dev/null @@ -1,5 +0,0 @@ -#warning This header is deprecated, #import instead. - -#import -#import -#import diff --git a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-Private.xcconfig deleted file mode 100644 index 41651cc..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-CocoaLumberjack.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/CocoaLumberjack" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-dummy.m b/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-dummy.m deleted file mode 100644 index c926822..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_CocoaLumberjack : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_CocoaLumberjack -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-Private.xcconfig deleted file mode 100644 index a3465ee..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-Mantle.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/Mantle" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = ${PODS_BLOGTESTS_MANTLE_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-dummy.m b/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-dummy.m deleted file mode 100644 index a12e198..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_Mantle : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_Mantle -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle.xcconfig b/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle.xcconfig deleted file mode 100644 index c43ca6c..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-Mantle/Pods-BlogTests-Mantle.xcconfig +++ /dev/null @@ -1 +0,0 @@ -PODS_BLOGTESTS_MANTLE_OTHER_LDFLAGS = -framework "Foundation" \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-Private.xcconfig deleted file mode 100644 index d289a1c..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-OHHTTPStubs.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ${PODS_BLOGTESTS_OHHTTPSTUBS_GCC_PREPROCESSOR_DEFINITIONS} -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/OHHTTPStubs" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = ${PODS_BLOGTESTS_OHHTTPSTUBS_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-dummy.m b/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-dummy.m deleted file mode 100644 index 03062aa..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_OHHTTPStubs : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_OHHTTPStubs -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs.xcconfig b/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs.xcconfig deleted file mode 100644 index 9af6bf7..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OHHTTPStubs/Pods-BlogTests-OHHTTPStubs.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -PODS_BLOGTESTS_OHHTTPSTUBS_GCC_PREPROCESSOR_DEFINITIONS = XCODE_VERSION=$(XCODE_VERSION_MAJOR) -PODS_BLOGTESTS_OHHTTPSTUBS_OTHER_LDFLAGS = -framework "CFNetwork" -framework "Foundation" \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-Private.xcconfig deleted file mode 100644 index cdd1dcd..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-OMGHTTPURLRQ.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-dummy.m b/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-dummy.m deleted file mode 100644 index 40c33d3..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_OMGHTTPURLRQ : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_OMGHTTPURLRQ -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ.xcconfig b/Pods/Target Support Files/Pods-BlogTests-OMGHTTPURLRQ/Pods-BlogTests-OMGHTTPURLRQ.xcconfig deleted file mode 100644 index e69de29..0000000 diff --git a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-Private.xcconfig deleted file mode 100644 index 720806b..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-PromiseKit.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ${PODS_BLOGTESTS_PROMISEKIT_GCC_PREPROCESSOR_DEFINITIONS} -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/PromiseKit" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = ${PODS_BLOGTESTS_PROMISEKIT_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-dummy.m b/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-dummy.m deleted file mode 100644 index 241f751..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_PromiseKit : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_PromiseKit -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit.xcconfig b/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit.xcconfig deleted file mode 100644 index c5ad2d0..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-PromiseKit/Pods-BlogTests-PromiseKit.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -PODS_BLOGTESTS_PROMISEKIT_GCC_PREPROCESSOR_DEFINITIONS = $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -PODS_BLOGTESTS_PROMISEKIT_OTHER_LDFLAGS = -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-Private.xcconfig deleted file mode 100644 index 641db05..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-YapDatabase.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/YapDatabase" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = ${PODS_BLOGTESTS_YAPDATABASE_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-dummy.m b/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-dummy.m deleted file mode 100644 index c37a04c..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_YapDatabase : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_YapDatabase -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase.xcconfig b/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase.xcconfig deleted file mode 100644 index 86b550b..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-YapDatabase/Pods-BlogTests-YapDatabase.xcconfig +++ /dev/null @@ -1 +0,0 @@ -PODS_BLOGTESTS_YAPDATABASE_OTHER_LDFLAGS = -weak_library /usr/lib/libc++.dylib -l"sqlite3" \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-Private.xcconfig b/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-Private.xcconfig deleted file mode 100644 index a27858b..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "Pods-BlogTests-libextobjc.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/libextobjc" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-dummy.m b/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-dummy.m deleted file mode 100644 index 9119472..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests_libextobjc : NSObject -@end -@implementation PodsDummy_Pods_BlogTests_libextobjc -@end diff --git a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch b/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch deleted file mode 100644 index 6c25023..0000000 --- a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc-prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - -#import "Pods-BlogTests-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc.xcconfig b/Pods/Target Support Files/Pods-BlogTests-libextobjc/Pods-BlogTests-libextobjc.xcconfig deleted file mode 100644 index e69de29..0000000 diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.markdown b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.markdown deleted file mode 100644 index 01afe44..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.markdown +++ /dev/null @@ -1,120 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## CocoaLumberjack - -Software License Agreement (BSD License) - -Copyright (c) 2010, Deusty, LLC -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Neither the name of Deusty nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Deusty, LLC. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -## Mantle - -**Copyright (c) 2012 - 2014, GitHub, Inc.** -**All rights reserved.** - -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. - ---- - -**This project uses portions of code from the Proton framework.** -**Proton is copyright (c) 2012, Bitswift, Inc.** -**All rights reserved.** - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -## OHHTTPStubs - -- MIT LICENSE - - -Copyright (c) 2012 Olivier Halligon - -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. - -## OMGHTTPURLRQ - -See README.markdown for full license text. - -## PromiseKit - -Copyright 2014 Max Howell - -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. - - -## YapDatabase - -Software License Agreement (BSD License) - -Copyright (c) 2013, yap.TV Inc. -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Neither the name of yap.TV nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of yap.TV Inc. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -## libextobjc - -Copyright (c) 2012 Justin Spahr-Summers - -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. - -Generated by CocoaPods - http://cocoapods.org diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.plist b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.plist deleted file mode 100644 index 92ebfa2..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-acknowledgements.plist +++ /dev/null @@ -1,174 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Software License Agreement (BSD License) - -Copyright (c) 2010, Deusty, LLC -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Neither the name of Deusty nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Deusty, LLC. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Title - CocoaLumberjack - Type - PSGroupSpecifier - - - FooterText - **Copyright (c) 2012 - 2014, GitHub, Inc.** -**All rights reserved.** - -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. - ---- - -**This project uses portions of code from the Proton framework.** -**Proton is copyright (c) 2012, Bitswift, Inc.** -**All rights reserved.** - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Title - Mantle - Type - PSGroupSpecifier - - - FooterText - - MIT LICENSE - - -Copyright (c) 2012 Olivier Halligon - -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. - Title - OHHTTPStubs - Type - PSGroupSpecifier - - - FooterText - See README.markdown for full license text. - Title - OMGHTTPURLRQ - Type - PSGroupSpecifier - - - FooterText - Copyright 2014 Max Howell <mxcl@me.com> - -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. - - Title - PromiseKit - Type - PSGroupSpecifier - - - FooterText - Software License Agreement (BSD License) - -Copyright (c) 2013, yap.TV Inc. -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Neither the name of yap.TV nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of yap.TV Inc. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Title - YapDatabase - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2012 Justin Spahr-Summers - -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. - - Title - libextobjc - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - http://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-dummy.m b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-dummy.m deleted file mode 100644 index 50a561d..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_BlogTests : NSObject -@end -@implementation PodsDummy_Pods_BlogTests -@end diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-environment.h b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-environment.h deleted file mode 100644 index 2f5df19..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-environment.h +++ /dev/null @@ -1,236 +0,0 @@ - -// To check if a library is compiled with CocoaPods you -// can use the `COCOAPODS` macro definition which is -// defined in the xcconfigs so it is available in -// headers also when they are imported in the client -// project. - - -// CocoaLumberjack -#define COCOAPODS_POD_AVAILABLE_CocoaLumberjack -#define COCOAPODS_VERSION_MAJOR_CocoaLumberjack 1 -#define COCOAPODS_VERSION_MINOR_CocoaLumberjack 9 -#define COCOAPODS_VERSION_PATCH_CocoaLumberjack 2 - -// CocoaLumberjack/Core -#define COCOAPODS_POD_AVAILABLE_CocoaLumberjack_Core -#define COCOAPODS_VERSION_MAJOR_CocoaLumberjack_Core 1 -#define COCOAPODS_VERSION_MINOR_CocoaLumberjack_Core 9 -#define COCOAPODS_VERSION_PATCH_CocoaLumberjack_Core 2 - -// CocoaLumberjack/Extensions -#define COCOAPODS_POD_AVAILABLE_CocoaLumberjack_Extensions -#define COCOAPODS_VERSION_MAJOR_CocoaLumberjack_Extensions 1 -#define COCOAPODS_VERSION_MINOR_CocoaLumberjack_Extensions 9 -#define COCOAPODS_VERSION_PATCH_CocoaLumberjack_Extensions 2 - -// Mantle -#define COCOAPODS_POD_AVAILABLE_Mantle -#define COCOAPODS_VERSION_MAJOR_Mantle 1 -#define COCOAPODS_VERSION_MINOR_Mantle 5 -#define COCOAPODS_VERSION_PATCH_Mantle 1 - -// Mantle/extobjc -#define COCOAPODS_POD_AVAILABLE_Mantle_extobjc -#define COCOAPODS_VERSION_MAJOR_Mantle_extobjc 1 -#define COCOAPODS_VERSION_MINOR_Mantle_extobjc 5 -#define COCOAPODS_VERSION_PATCH_Mantle_extobjc 1 - -// OHHTTPStubs -#define COCOAPODS_POD_AVAILABLE_OHHTTPStubs -#define COCOAPODS_VERSION_MAJOR_OHHTTPStubs 3 -#define COCOAPODS_VERSION_MINOR_OHHTTPStubs 1 -#define COCOAPODS_VERSION_PATCH_OHHTTPStubs 6 - -// OHHTTPStubs/Core -#define COCOAPODS_POD_AVAILABLE_OHHTTPStubs_Core -#define COCOAPODS_VERSION_MAJOR_OHHTTPStubs_Core 3 -#define COCOAPODS_VERSION_MINOR_OHHTTPStubs_Core 1 -#define COCOAPODS_VERSION_PATCH_OHHTTPStubs_Core 6 - -// OMGHTTPURLRQ -#define COCOAPODS_POD_AVAILABLE_OMGHTTPURLRQ -#define COCOAPODS_VERSION_MAJOR_OMGHTTPURLRQ 2 -#define COCOAPODS_VERSION_MINOR_OMGHTTPURLRQ 1 -#define COCOAPODS_VERSION_PATCH_OMGHTTPURLRQ 0 - -// OMGHTTPURLRQ/FormURLEncode -#define COCOAPODS_POD_AVAILABLE_OMGHTTPURLRQ_FormURLEncode -#define COCOAPODS_VERSION_MAJOR_OMGHTTPURLRQ_FormURLEncode 2 -#define COCOAPODS_VERSION_MINOR_OMGHTTPURLRQ_FormURLEncode 1 -#define COCOAPODS_VERSION_PATCH_OMGHTTPURLRQ_FormURLEncode 0 - -// OMGHTTPURLRQ/RQ -#define COCOAPODS_POD_AVAILABLE_OMGHTTPURLRQ_RQ -#define COCOAPODS_VERSION_MAJOR_OMGHTTPURLRQ_RQ 2 -#define COCOAPODS_VERSION_MINOR_OMGHTTPURLRQ_RQ 1 -#define COCOAPODS_VERSION_PATCH_OMGHTTPURLRQ_RQ 0 - -// OMGHTTPURLRQ/UserAgent -#define COCOAPODS_POD_AVAILABLE_OMGHTTPURLRQ_UserAgent -#define COCOAPODS_VERSION_MAJOR_OMGHTTPURLRQ_UserAgent 2 -#define COCOAPODS_VERSION_MINOR_OMGHTTPURLRQ_UserAgent 1 -#define COCOAPODS_VERSION_PATCH_OMGHTTPURLRQ_UserAgent 0 - -// PromiseKit -#define COCOAPODS_POD_AVAILABLE_PromiseKit -#define COCOAPODS_VERSION_MAJOR_PromiseKit 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit 0 - -// PromiseKit/NSNotificationCenter -#define COCOAPODS_POD_AVAILABLE_PromiseKit_NSNotificationCenter -#define COCOAPODS_VERSION_MAJOR_PromiseKit_NSNotificationCenter 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_NSNotificationCenter 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_NSNotificationCenter 0 - -// PromiseKit/NSURLConnection -#define COCOAPODS_POD_AVAILABLE_PromiseKit_NSURLConnection -#define COCOAPODS_VERSION_MAJOR_PromiseKit_NSURLConnection 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_NSURLConnection 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_NSURLConnection 0 - -// PromiseKit/Pause -#define COCOAPODS_POD_AVAILABLE_PromiseKit_Pause -#define COCOAPODS_VERSION_MAJOR_PromiseKit_Pause 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Pause 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Pause 0 - -// PromiseKit/Promise -#define COCOAPODS_POD_AVAILABLE_PromiseKit_Promise -#define COCOAPODS_VERSION_MAJOR_PromiseKit_Promise 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Promise 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Promise 0 - -// PromiseKit/UIActionSheet -#define COCOAPODS_POD_AVAILABLE_PromiseKit_UIActionSheet -#define COCOAPODS_VERSION_MAJOR_PromiseKit_UIActionSheet 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIActionSheet 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIActionSheet 0 - -// PromiseKit/UIAlertView -#define COCOAPODS_POD_AVAILABLE_PromiseKit_UIAlertView -#define COCOAPODS_VERSION_MAJOR_PromiseKit_UIAlertView 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIAlertView 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIAlertView 0 - -// PromiseKit/UIView -#define COCOAPODS_POD_AVAILABLE_PromiseKit_UIView -#define COCOAPODS_VERSION_MAJOR_PromiseKit_UIView 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIView 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIView 0 - -// PromiseKit/UIViewController -#define COCOAPODS_POD_AVAILABLE_PromiseKit_UIViewController -#define COCOAPODS_VERSION_MAJOR_PromiseKit_UIViewController 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIViewController 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIViewController 0 - -// PromiseKit/Until -#define COCOAPODS_POD_AVAILABLE_PromiseKit_Until -#define COCOAPODS_VERSION_MAJOR_PromiseKit_Until 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Until 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Until 0 - -// PromiseKit/When -#define COCOAPODS_POD_AVAILABLE_PromiseKit_When -#define COCOAPODS_VERSION_MAJOR_PromiseKit_When 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_When 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_When 0 - -// YapDatabase -#define COCOAPODS_POD_AVAILABLE_YapDatabase -#define COCOAPODS_VERSION_MAJOR_YapDatabase 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase 2 - -// YapDatabase/common -#define COCOAPODS_POD_AVAILABLE_YapDatabase_common -#define COCOAPODS_VERSION_MAJOR_YapDatabase_common 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase_common 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase_common 2 - -// YapDatabase/standard -#define COCOAPODS_POD_AVAILABLE_YapDatabase_standard -#define COCOAPODS_VERSION_MAJOR_YapDatabase_standard 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase_standard 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase_standard 2 - -// libextobjc -#define COCOAPODS_POD_AVAILABLE_libextobjc -#define COCOAPODS_VERSION_MAJOR_libextobjc 0 -#define COCOAPODS_VERSION_MINOR_libextobjc 4 -#define COCOAPODS_VERSION_PATCH_libextobjc 0 - -// libextobjc/EXTADT -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTADT -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTADT 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTADT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTADT 0 - -// libextobjc/EXTConcreteProtocol -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTConcreteProtocol -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTConcreteProtocol 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTConcreteProtocol 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTConcreteProtocol 0 - -// libextobjc/EXTKeyPathCoding -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTKeyPathCoding -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTKeyPathCoding 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTKeyPathCoding 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTKeyPathCoding 0 - -// libextobjc/EXTNil -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTNil -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTNil 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTNil 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTNil 0 - -// libextobjc/EXTSafeCategory -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSafeCategory -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSafeCategory 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTSafeCategory 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSafeCategory 0 - -// libextobjc/EXTScope -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTScope -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTScope 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTScope 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTScope 0 - -// libextobjc/EXTSelectorChecking -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSelectorChecking -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSelectorChecking 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTSelectorChecking 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSelectorChecking 0 - -// libextobjc/EXTSynthesize -#define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSynthesize -#define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSynthesize 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_EXTSynthesize 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSynthesize 0 - -// libextobjc/NSInvocation+EXT -#define COCOAPODS_POD_AVAILABLE_libextobjc_NSInvocation_EXT -#define COCOAPODS_VERSION_MAJOR_libextobjc_NSInvocation_EXT 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_NSInvocation_EXT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_NSInvocation_EXT 0 - -// libextobjc/NSMethodSignature+EXT -#define COCOAPODS_POD_AVAILABLE_libextobjc_NSMethodSignature_EXT -#define COCOAPODS_VERSION_MAJOR_libextobjc_NSMethodSignature_EXT 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_NSMethodSignature_EXT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_NSMethodSignature_EXT 0 - -// libextobjc/RuntimeExtensions -#define COCOAPODS_POD_AVAILABLE_libextobjc_RuntimeExtensions -#define COCOAPODS_VERSION_MAJOR_libextobjc_RuntimeExtensions 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_RuntimeExtensions 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_RuntimeExtensions 0 - -// libextobjc/UmbrellaHeader -#define COCOAPODS_POD_AVAILABLE_libextobjc_UmbrellaHeader -#define COCOAPODS_VERSION_MAJOR_libextobjc_UmbrellaHeader 0 -#define COCOAPODS_VERSION_MINOR_libextobjc_UmbrellaHeader 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_UmbrellaHeader 0 - diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-resources.sh b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-resources.sh deleted file mode 100755 index 216f0cf..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests-resources.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -install_resource() -{ - case $1 in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" - ;; - *.xcassets) - ;; - /*) - echo "$1" - echo "$1" >> "$RESOURCES_TO_COPY" - ;; - *) - echo "${PODS_ROOT}/$1" - echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]]; then - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] -then - case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; - esac - find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.debug.xcconfig b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.debug.xcconfig deleted file mode 100644 index 0ed9264..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.debug.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 XCODE_VERSION=$(XCODE_VERSION_MAJOR) $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OHHTTPStubs" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-BlogTests-CocoaLumberjack" -l"Pods-BlogTests-Mantle" -l"Pods-BlogTests-OHHTTPStubs" -l"Pods-BlogTests-OMGHTTPURLRQ" -l"Pods-BlogTests-PromiseKit" -l"Pods-BlogTests-YapDatabase" -l"Pods-BlogTests-libextobjc" -l"sqlite3" -framework "CFNetwork" -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" -OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.release.xcconfig b/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.release.xcconfig deleted file mode 100644 index 0ed9264..0000000 --- a/Pods/Target Support Files/Pods-BlogTests/Pods-BlogTests.release.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 XCODE_VERSION=$(XCODE_VERSION_MAJOR) $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OHHTTPStubs" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-BlogTests-CocoaLumberjack" -l"Pods-BlogTests-Mantle" -l"Pods-BlogTests-OHHTTPStubs" -l"Pods-BlogTests-OMGHTTPURLRQ" -l"Pods-BlogTests-PromiseKit" -l"Pods-BlogTests-YapDatabase" -l"Pods-BlogTests-libextobjc" -l"sqlite3" -framework "CFNetwork" -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" -OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig b/Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig index 48ddc3b..74bb7d7 100644 --- a/Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig +++ b/Pods/Target Support Files/Pods-CocoaLumberjack/Pods-CocoaLumberjack-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-CocoaLumberjack.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/CocoaLumberjack" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/CocoaLumberjack" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-Mantle/Pods-Mantle-Private.xcconfig b/Pods/Target Support Files/Pods-Mantle/Pods-Mantle-Private.xcconfig index 45caeaa..320c3d8 100644 --- a/Pods/Target Support Files/Pods-Mantle/Pods-Mantle-Private.xcconfig +++ b/Pods/Target Support Files/Pods-Mantle/Pods-Mantle-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-Mantle.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/Mantle" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Mantle" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = ${PODS_MANTLE_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-Private.xcconfig b/Pods/Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-Private.xcconfig index 875da67..08ffc05 100644 --- a/Pods/Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-Private.xcconfig +++ b/Pods/Target Support Files/Pods-OMGHTTPURLRQ/Pods-OMGHTTPURLRQ-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-OMGHTTPURLRQ.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-Private.xcconfig b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-Private.xcconfig new file mode 100644 index 0000000..2d4284d --- /dev/null +++ b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-Private.xcconfig @@ -0,0 +1,6 @@ +#include "Pods-ObjectiveSugar.xcconfig" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ObjectiveSugar" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +OTHER_LDFLAGS = -ObjC +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-dummy.m b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-dummy.m new file mode 100644 index 0000000..90e1475 --- /dev/null +++ b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_ObjectiveSugar : NSObject +@end +@implementation PodsDummy_Pods_ObjectiveSugar +@end diff --git a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch similarity index 55% rename from Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch rename to Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch index 6c25023..95cf11d 100644 --- a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack-prefix.pch +++ b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar-prefix.pch @@ -2,4 +2,4 @@ #import #endif -#import "Pods-BlogTests-environment.h" +#import "Pods-environment.h" diff --git a/Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack.xcconfig b/Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar.xcconfig similarity index 100% rename from Pods/Target Support Files/Pods-BlogTests-CocoaLumberjack/Pods-BlogTests-CocoaLumberjack.xcconfig rename to Pods/Target Support Files/Pods-ObjectiveSugar/Pods-ObjectiveSugar.xcconfig diff --git a/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit-Private.xcconfig b/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit-Private.xcconfig index 956136e..dac407b 100644 --- a/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit-Private.xcconfig +++ b/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-PromiseKit.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 ${PODS_PROMISEKIT_GCC_PREPROCESSOR_DEFINITIONS} -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/PromiseKit" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/PromiseKit" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = ${PODS_PROMISEKIT_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit.xcconfig b/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit.xcconfig index 795a32b..25904dd 100644 --- a/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit.xcconfig +++ b/Pods/Target Support Files/Pods-PromiseKit/Pods-PromiseKit.xcconfig @@ -1,2 +1,2 @@ -PODS_PROMISEKIT_GCC_PREPROCESSOR_DEFINITIONS = $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -PODS_PROMISEKIT_OTHER_LDFLAGS = -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" \ No newline at end of file +PODS_PROMISEKIT_GCC_PREPROCESSOR_DEFINITIONS = $(inherited) PMK_CALAYER=1 $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 +PODS_PROMISEKIT_OTHER_LDFLAGS = -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -weak_framework "AssetsLibrary" \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-YapDatabase/Pods-YapDatabase-Private.xcconfig b/Pods/Target Support Files/Pods-YapDatabase/Pods-YapDatabase-Private.xcconfig index 33598c1..4db43d0 100644 --- a/Pods/Target Support Files/Pods-YapDatabase/Pods-YapDatabase-Private.xcconfig +++ b/Pods/Target Support Files/Pods-YapDatabase/Pods-YapDatabase-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-YapDatabase.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/YapDatabase" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/YapDatabase" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = ${PODS_YAPDATABASE_OTHER_LDFLAGS} -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-libextobjc/Pods-libextobjc-Private.xcconfig b/Pods/Target Support Files/Pods-libextobjc/Pods-libextobjc-Private.xcconfig index ceaf0b4..d3f1534 100644 --- a/Pods/Target Support Files/Pods-libextobjc/Pods-libextobjc-Private.xcconfig +++ b/Pods/Target Support Files/Pods-libextobjc/Pods-libextobjc-Private.xcconfig @@ -1,5 +1,6 @@ #include "Pods-libextobjc.xcconfig" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/libextobjc" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/libextobjc" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" OTHER_LDFLAGS = -ObjC -PODS_ROOT = ${SRCROOT} \ No newline at end of file +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown b/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown index 968e867..bd837db 100644 --- a/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown +++ b/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown @@ -24,7 +24,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ## Mantle -**Copyright (c) 2012 - 2014, GitHub, Inc.** +**Copyright (c) GitHub, Inc.** **All rights reserved.** 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: @@ -51,6 +51,17 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND See README.markdown for full license text. +## ObjectiveSugar + +Copyright © 2012 Marin Usalj, http://mneorr.com + +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. + + ## PromiseKit Copyright 2014 Max Howell @@ -97,12 +108,23 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ## libextobjc -Copyright (c) 2012 Justin Spahr-Summers +**Copyright (c) 2012 - 2014 Justin Spahr-Summers** -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: +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 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. +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. Generated by CocoaPods - http://cocoapods.org diff --git a/Pods/Target Support Files/Pods/Pods-acknowledgements.plist b/Pods/Target Support Files/Pods/Pods-acknowledgements.plist index 5cad27f..7a8272b 100644 --- a/Pods/Target Support Files/Pods/Pods-acknowledgements.plist +++ b/Pods/Target Support Files/Pods/Pods-acknowledgements.plist @@ -39,7 +39,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND FooterText - **Copyright (c) 2012 - 2014, GitHub, Inc.** + **Copyright (c) GitHub, Inc.** **All rights reserved.** 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: @@ -74,6 +74,21 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND Type PSGroupSpecifier + + FooterText + Copyright © 2012 Marin Usalj, http://mneorr.com + +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. + + Title + ObjectiveSugar + Type + PSGroupSpecifier + FooterText Copyright 2014 Max Howell <mxcl@me.com> @@ -128,13 +143,24 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND FooterText - Copyright (c) 2012 Justin Spahr-Summers + **Copyright (c) 2012 - 2014 Justin Spahr-Summers** -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: +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 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. +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. Title libextobjc diff --git a/Pods/Target Support Files/Pods/Pods-environment.h b/Pods/Target Support Files/Pods/Pods-environment.h index 153cce8..e179289 100644 --- a/Pods/Target Support Files/Pods/Pods-environment.h +++ b/Pods/Target Support Files/Pods/Pods-environment.h @@ -26,15 +26,15 @@ // Mantle #define COCOAPODS_POD_AVAILABLE_Mantle -#define COCOAPODS_VERSION_MAJOR_Mantle 1 -#define COCOAPODS_VERSION_MINOR_Mantle 5 -#define COCOAPODS_VERSION_PATCH_Mantle 1 +#define COCOAPODS_VERSION_MAJOR_Mantle 2 +#define COCOAPODS_VERSION_MINOR_Mantle 0 +#define COCOAPODS_VERSION_PATCH_Mantle 0 // Mantle/extobjc #define COCOAPODS_POD_AVAILABLE_Mantle_extobjc -#define COCOAPODS_VERSION_MAJOR_Mantle_extobjc 1 -#define COCOAPODS_VERSION_MINOR_Mantle_extobjc 5 -#define COCOAPODS_VERSION_PATCH_Mantle_extobjc 1 +#define COCOAPODS_VERSION_MAJOR_Mantle_extobjc 2 +#define COCOAPODS_VERSION_MINOR_Mantle_extobjc 0 +#define COCOAPODS_VERSION_PATCH_Mantle_extobjc 0 // OMGHTTPURLRQ #define COCOAPODS_POD_AVAILABLE_OMGHTTPURLRQ @@ -60,165 +60,177 @@ #define COCOAPODS_VERSION_MINOR_OMGHTTPURLRQ_UserAgent 1 #define COCOAPODS_VERSION_PATCH_OMGHTTPURLRQ_UserAgent 0 +// ObjectiveSugar +#define COCOAPODS_POD_AVAILABLE_ObjectiveSugar +#define COCOAPODS_VERSION_MAJOR_ObjectiveSugar 1 +#define COCOAPODS_VERSION_MINOR_ObjectiveSugar 1 +#define COCOAPODS_VERSION_PATCH_ObjectiveSugar 0 + // PromiseKit #define COCOAPODS_POD_AVAILABLE_PromiseKit #define COCOAPODS_VERSION_MAJOR_PromiseKit 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit 1 + +// PromiseKit/CALayer +#define COCOAPODS_POD_AVAILABLE_PromiseKit_CALayer +#define COCOAPODS_VERSION_MAJOR_PromiseKit_CALayer 1 +#define COCOAPODS_VERSION_MINOR_PromiseKit_CALayer 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_CALayer 1 // PromiseKit/NSNotificationCenter #define COCOAPODS_POD_AVAILABLE_PromiseKit_NSNotificationCenter #define COCOAPODS_VERSION_MAJOR_PromiseKit_NSNotificationCenter 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_NSNotificationCenter 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_NSNotificationCenter 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_NSNotificationCenter 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_NSNotificationCenter 1 // PromiseKit/NSURLConnection #define COCOAPODS_POD_AVAILABLE_PromiseKit_NSURLConnection #define COCOAPODS_VERSION_MAJOR_PromiseKit_NSURLConnection 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_NSURLConnection 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_NSURLConnection 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_NSURLConnection 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_NSURLConnection 1 // PromiseKit/Pause #define COCOAPODS_POD_AVAILABLE_PromiseKit_Pause #define COCOAPODS_VERSION_MAJOR_PromiseKit_Pause 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Pause 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Pause 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_Pause 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_Pause 1 // PromiseKit/Promise #define COCOAPODS_POD_AVAILABLE_PromiseKit_Promise #define COCOAPODS_VERSION_MAJOR_PromiseKit_Promise 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Promise 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Promise 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_Promise 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_Promise 1 // PromiseKit/UIActionSheet #define COCOAPODS_POD_AVAILABLE_PromiseKit_UIActionSheet #define COCOAPODS_VERSION_MAJOR_PromiseKit_UIActionSheet 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIActionSheet 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIActionSheet 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_UIActionSheet 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_UIActionSheet 1 // PromiseKit/UIAlertView #define COCOAPODS_POD_AVAILABLE_PromiseKit_UIAlertView #define COCOAPODS_VERSION_MAJOR_PromiseKit_UIAlertView 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIAlertView 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIAlertView 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_UIAlertView 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_UIAlertView 1 // PromiseKit/UIView #define COCOAPODS_POD_AVAILABLE_PromiseKit_UIView #define COCOAPODS_VERSION_MAJOR_PromiseKit_UIView 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIView 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIView 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_UIView 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_UIView 1 // PromiseKit/UIViewController #define COCOAPODS_POD_AVAILABLE_PromiseKit_UIViewController #define COCOAPODS_VERSION_MAJOR_PromiseKit_UIViewController 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_UIViewController 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_UIViewController 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_UIViewController 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_UIViewController 1 // PromiseKit/Until #define COCOAPODS_POD_AVAILABLE_PromiseKit_Until #define COCOAPODS_VERSION_MAJOR_PromiseKit_Until 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_Until 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_Until 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_Until 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_Until 1 // PromiseKit/When #define COCOAPODS_POD_AVAILABLE_PromiseKit_When #define COCOAPODS_VERSION_MAJOR_PromiseKit_When 1 -#define COCOAPODS_VERSION_MINOR_PromiseKit_When 0 -#define COCOAPODS_VERSION_PATCH_PromiseKit_When 0 +#define COCOAPODS_VERSION_MINOR_PromiseKit_When 5 +#define COCOAPODS_VERSION_PATCH_PromiseKit_When 1 // YapDatabase #define COCOAPODS_POD_AVAILABLE_YapDatabase #define COCOAPODS_VERSION_MAJOR_YapDatabase 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase 2 +#define COCOAPODS_VERSION_MINOR_YapDatabase 6 +#define COCOAPODS_VERSION_PATCH_YapDatabase 1 // YapDatabase/common #define COCOAPODS_POD_AVAILABLE_YapDatabase_common #define COCOAPODS_VERSION_MAJOR_YapDatabase_common 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase_common 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase_common 2 +#define COCOAPODS_VERSION_MINOR_YapDatabase_common 6 +#define COCOAPODS_VERSION_PATCH_YapDatabase_common 1 // YapDatabase/standard #define COCOAPODS_POD_AVAILABLE_YapDatabase_standard #define COCOAPODS_VERSION_MAJOR_YapDatabase_standard 2 -#define COCOAPODS_VERSION_MINOR_YapDatabase_standard 5 -#define COCOAPODS_VERSION_PATCH_YapDatabase_standard 2 +#define COCOAPODS_VERSION_MINOR_YapDatabase_standard 6 +#define COCOAPODS_VERSION_PATCH_YapDatabase_standard 1 // libextobjc #define COCOAPODS_POD_AVAILABLE_libextobjc #define COCOAPODS_VERSION_MAJOR_libextobjc 0 #define COCOAPODS_VERSION_MINOR_libextobjc 4 -#define COCOAPODS_VERSION_PATCH_libextobjc 0 +#define COCOAPODS_VERSION_PATCH_libextobjc 1 // libextobjc/EXTADT #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTADT #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTADT 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTADT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTADT 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTADT 1 // libextobjc/EXTConcreteProtocol #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTConcreteProtocol #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTConcreteProtocol 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTConcreteProtocol 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTConcreteProtocol 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTConcreteProtocol 1 // libextobjc/EXTKeyPathCoding #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTKeyPathCoding #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTKeyPathCoding 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTKeyPathCoding 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTKeyPathCoding 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTKeyPathCoding 1 // libextobjc/EXTNil #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTNil #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTNil 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTNil 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTNil 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTNil 1 // libextobjc/EXTSafeCategory #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSafeCategory #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSafeCategory 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTSafeCategory 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSafeCategory 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSafeCategory 1 // libextobjc/EXTScope #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTScope #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTScope 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTScope 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTScope 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTScope 1 // libextobjc/EXTSelectorChecking #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSelectorChecking #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSelectorChecking 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTSelectorChecking 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSelectorChecking 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSelectorChecking 1 // libextobjc/EXTSynthesize #define COCOAPODS_POD_AVAILABLE_libextobjc_EXTSynthesize #define COCOAPODS_VERSION_MAJOR_libextobjc_EXTSynthesize 0 #define COCOAPODS_VERSION_MINOR_libextobjc_EXTSynthesize 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSynthesize 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_EXTSynthesize 1 // libextobjc/NSInvocation+EXT #define COCOAPODS_POD_AVAILABLE_libextobjc_NSInvocation_EXT #define COCOAPODS_VERSION_MAJOR_libextobjc_NSInvocation_EXT 0 #define COCOAPODS_VERSION_MINOR_libextobjc_NSInvocation_EXT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_NSInvocation_EXT 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_NSInvocation_EXT 1 // libextobjc/NSMethodSignature+EXT #define COCOAPODS_POD_AVAILABLE_libextobjc_NSMethodSignature_EXT #define COCOAPODS_VERSION_MAJOR_libextobjc_NSMethodSignature_EXT 0 #define COCOAPODS_VERSION_MINOR_libextobjc_NSMethodSignature_EXT 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_NSMethodSignature_EXT 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_NSMethodSignature_EXT 1 // libextobjc/RuntimeExtensions #define COCOAPODS_POD_AVAILABLE_libextobjc_RuntimeExtensions #define COCOAPODS_VERSION_MAJOR_libextobjc_RuntimeExtensions 0 #define COCOAPODS_VERSION_MINOR_libextobjc_RuntimeExtensions 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_RuntimeExtensions 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_RuntimeExtensions 1 // libextobjc/UmbrellaHeader #define COCOAPODS_POD_AVAILABLE_libextobjc_UmbrellaHeader #define COCOAPODS_VERSION_MAJOR_libextobjc_UmbrellaHeader 0 #define COCOAPODS_VERSION_MINOR_libextobjc_UmbrellaHeader 4 -#define COCOAPODS_VERSION_PATCH_libextobjc_UmbrellaHeader 0 +#define COCOAPODS_VERSION_PATCH_libextobjc_UmbrellaHeader 1 diff --git a/Pods/Target Support Files/Pods/Pods-resources.sh b/Pods/Target Support Files/Pods/Pods-resources.sh index 216f0cf..43f0852 100755 --- a/Pods/Target Support Files/Pods/Pods-resources.sh +++ b/Pods/Target Support Files/Pods/Pods-resources.sh @@ -6,6 +6,14 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt > "$RESOURCES_TO_COPY" +XCASSET_FILES=() + +realpath() { + DIRECTORY=$(cd "${1%/*}" && pwd) + FILENAME="${1##*/}" + echo "$DIRECTORY/$FILENAME" +} + install_resource() { case $1 in @@ -31,7 +39,13 @@ install_resource() echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" ;; + *.xcmappingmodel) + echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" + xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" + ;; *.xcassets) + ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; /*) echo "$1" @@ -50,7 +64,7 @@ if [[ "${ACTION}" == "install" ]]; then fi rm -f "$RESOURCES_TO_COPY" -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] then case "${TARGETED_DEVICE_FAMILY}" in 1,2) @@ -66,5 +80,14 @@ then TARGET_DEVICE_ARGS="--target-device mac" ;; esac - find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "`realpath $PODS_ROOT`*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi diff --git a/Pods/Target Support Files/Pods/Pods.debug.xcconfig b/Pods/Target Support Files/Pods/Pods.debug.xcconfig index a98ecb5..5cf35a5 100644 --- a/Pods/Target Support Files/Pods/Pods.debug.xcconfig +++ b/Pods/Target Support Files/Pods/Pods.debug.xcconfig @@ -1,6 +1,6 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OHHTTPStubs" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-CocoaLumberjack" -l"Pods-Mantle" -l"Pods-OMGHTTPURLRQ" -l"Pods-PromiseKit" -l"Pods-YapDatabase" -l"Pods-libextobjc" -l"sqlite3" -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PMK_CALAYER=1 $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/ObjectiveSugar" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" +OTHER_LDFLAGS = $(inherited) -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-CocoaLumberjack" -l"Pods-Mantle" -l"Pods-OMGHTTPURLRQ" -l"Pods-ObjectiveSugar" -l"Pods-PromiseKit" -l"Pods-YapDatabase" -l"Pods-libextobjc" -l"sqlite3" -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -weak_framework "AssetsLibrary" OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Pods/Target Support Files/Pods/Pods.release.xcconfig b/Pods/Target Support Files/Pods/Pods.release.xcconfig index a98ecb5..5cf35a5 100644 --- a/Pods/Target Support Files/Pods/Pods.release.xcconfig +++ b/Pods/Target Support Files/Pods/Pods.release.xcconfig @@ -1,6 +1,6 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OHHTTPStubs" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OHHTTPStubs" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" -OTHER_LDFLAGS = -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-CocoaLumberjack" -l"Pods-Mantle" -l"Pods-OMGHTTPURLRQ" -l"Pods-PromiseKit" -l"Pods-YapDatabase" -l"Pods-libextobjc" -l"sqlite3" -framework "Foundation" -framework "UIKit" -weak_framework "AssetsLibrary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PMK_CALAYER=1 $(inherited) PMK_NSNOTIFICATIONCENTER=1 $(inherited) PMK_NSURLCONNECTION=1 $(inherited) PMK_PAUSE=1 $(inherited) PMK_UIACTIONSHEET=1 $(inherited) PMK_UIALERTVIEW=1 $(inherited) PMK_UIVIEW=1 $(inherited) PMK_UIVIEWCONTROLLER=1 $(inherited) PMK_UNTIL=1 $(inherited) PMK_WHEN=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/CocoaLumberjack" "${PODS_ROOT}/Headers/Public/Mantle" "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" "${PODS_ROOT}/Headers/Public/ObjectiveSugar" "${PODS_ROOT}/Headers/Public/PromiseKit" "${PODS_ROOT}/Headers/Public/YapDatabase" "${PODS_ROOT}/Headers/Public/libextobjc" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/CocoaLumberjack" -isystem "${PODS_ROOT}/Headers/Public/Mantle" -isystem "${PODS_ROOT}/Headers/Public/OMGHTTPURLRQ" -isystem "${PODS_ROOT}/Headers/Public/ObjectiveSugar" -isystem "${PODS_ROOT}/Headers/Public/PromiseKit" -isystem "${PODS_ROOT}/Headers/Public/YapDatabase" -isystem "${PODS_ROOT}/Headers/Public/libextobjc" +OTHER_LDFLAGS = $(inherited) -ObjC -weak_library /usr/lib/libc++.dylib -l"Pods-CocoaLumberjack" -l"Pods-Mantle" -l"Pods-OMGHTTPURLRQ" -l"Pods-ObjectiveSugar" -l"Pods-PromiseKit" -l"Pods-YapDatabase" -l"Pods-libextobjc" -l"sqlite3" -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -weak_framework "AssetsLibrary" OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Pods/YapDatabase/README.md b/Pods/YapDatabase/README.md index c7e9700..72dd5ef 100644 --- a/Pods/YapDatabase/README.md +++ b/Pods/YapDatabase/README.md @@ -20,6 +20,8 @@ It has the following features: * **Relationships**. You can setup relationships between objects and even configure cascading delete rules. +* **Sync**. Support for syncing with Apple's CloudKit is available out of the box. There's even a fully functioning example project that demonstrates writing a syncing Todo app. + * **Extensions**. More than just a key/value store, YapDatabase comes with an extensions architecture built-in. You can even create your own extensions. * **Performance**. Fetch thousands of objects on the main thread without dropping a frame. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h new file mode 100644 index 0000000..e357437 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.h @@ -0,0 +1,12 @@ +#import +#import + + +@interface YDBCKAttachRequest : NSObject + +@property (nonatomic, copy, readwrite) NSString *databaseIdentifier; +@property (nonatomic, strong, readwrite) CKRecord *record; + +@property (nonatomic, assign, readwrite) BOOL shouldUploadRecord; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.m new file mode 100644 index 0000000..cc71923 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKAttachRequest.m @@ -0,0 +1,11 @@ +#import "YDBCKAttachRequest.h" + + +@implementation YDBCKAttachRequest + +@synthesize databaseIdentifier; +@synthesize record; + +@synthesize shouldUploadRecord; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h new file mode 100644 index 0000000..725a2e6 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.h @@ -0,0 +1,261 @@ +#import +#import + +#import "YDBCKChangeSet.h" +#import "YDBCKMergeInfo.h" + + +@interface YDBCKChangeQueue : NSObject + +/** + * Every YapDatabaseCloudKit instance has a single masterQueue, + * which tracks the CloutKit related changeSets per commit. + * + * This information is used to create and track the NSOperation's that are pushing data to the cloud, + * as well as the corresponding information that we need to save to persistent storage. +**/ +- (instancetype)initMasterQueue; + +#pragma mark Lifecycle + +/** + * This method is used during extension registration + * after the old changeSets, from previous app run(s), have been restored. + * + * This method MUST be called from within the readWriteTransaction that registers the extension. +**/ +- (void)restoreOldChangeSets:(NSArray *)oldChangeSets; + +/** + * If there is NOT already an in-flight changeSet, then this method sets the appropriate flag(s), + * and returns the next changeSet ready for upload. +**/ +- (YDBCKChangeSet *)makeInFlightChangeSet:(BOOL *)isAlreadyInFlightPtr; + +/** + * If there is an in-flight changeSet, + * then this method removes it to make room for new in-flight changeSets. +**/ +- (void)removeCompletedInFlightChangeSet; + +/** + * If there is an in-flight changeSet, + * then this method "resets" it so it can be restarted again (when ready). +**/ +- (void)resetFailedInFlightChangeSet; + +/** + * Invoke this method from 'prepareForReadWriteTransaction' in order to fetch a 'pendingQueue' object. + * + * This pendingQueue object will then be used to keep track of all the changes + * that need to be written to the changesTable. + * + * This method MUST be called from within a readWriteTransaction. + * + * Keep in mind that the creation of a pendingQueue locks the masterQueue until + * that pendingQueue is merged via mergePendingQueue. +**/ +- (YDBCKChangeQueue *)newPendingQueue; + +/** + * This should be done AFTER the pendingQueue has been written to disk, + * at the end of the flushPendingChangesToExtensionTables method. + * + * This method MUST be called from within a readWriteTransaction. + * + * Keep in mind that the creation of a pendingQueue locks the masterQueue until + * that pendingQueue is merged via mergePendingQueue. +**/ +- (void)mergePendingQueue:(YDBCKChangeQueue *)pendingQueue; + +#pragma mark Properties + +/** + * Determining queue type. + * Primarily used for sanity checks. +**/ +@property (nonatomic, readonly) BOOL isMasterQueue; +@property (nonatomic, readonly) BOOL isPendingQueue; + +#pragma mark Change-Sets Access + +/** + * Returns the changeSet.uuid of the "current" changeSet, + * which is either the inFlightChangeSet, or the next changeSet to go inFlight once resumed. + * + * In other words, the first YDBCKChangeSet in the queue. +**/ +- (NSString *)currentChangeSetUUID; + +/** + * Each commit that makes one or more changes to a CKRecord (insert/modify/delete) + * will result in one or more YDBCKChangeSet(s). + * There is one YDBCKChangeSet per databaseIdentifier. + * So a single commit may possibly generate multiple changeSets. + * + * Thus a changeSet encompasses all the relavent CloudKit related changes per database, per commit. +**/ +- (NSArray *)changeSetsFromPreviousCommits; +- (NSArray *)changeSetsFromCurrentCommit; + +/** + * Faster access if you just want to get the counts. + * + * - numberOfInFlightChangeSets: + * YDBCKChangeSets that have been dispatched to CloudKit Framework. + * These may or may not succeed, depending upon network conditions & other factors. + * + * - numberOfQueuedChangeSets: + * YDBCKChangeSets that have not been dispatched to CloudKit Framework. + * They are waiting for the current inFlight change-sets to succeed, or for YDBCK to be resumed. + * + * - numberOfPendingChangeSets: + * Includes all YDBCKChangeSets, both inFlight & queued. + * + * In mathematical notion, the relationships are: + * + * numberOfInFlightChangeSets == numberOfPendingChangeSets - numberOfQueuedChangeSets + * numberOfQueuedChangeSets == numberOfPendingChangeSets - numberOfInFlightChangeSets + * numberOfPendingChangeSets == numberOfPendingChangeSets + numberOfQueuedChangeSets +**/ +@property (atomic, readonly) NSUInteger numberOfInFlightChangeSets; +@property (atomic, readonly) NSUInteger numberOfQueuedChangeSets; +@property (atomic, readonly) NSUInteger numberOfPendingChangeSets; + +/** + * Atomic access to all counts at once. +**/ +- (void)getNumberOfInFlightChangeSets:(NSUInteger *)numInFlightChangeSetsPtr + queuedChangeSets:(NSUInteger *)numQueuedChangeSetsPtr; + +#pragma mark Merge Handling + +/** + * Check in pendingChangeSetsFromPreviousCommits to see what kind of changes are pending. +**/ +- (void)getHasPendingModification:(BOOL *)outHasPendingModification + hasPendingDelete:(BOOL *)outHasPendingDelete + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method enumerates pendingChangeSetsFromPreviousCommits, from oldest commit to newest commit, + * and merges the changedKeys & values into the given record. + * Thus, if the value for a particular key has been changed multiple times, + * then the given record will end up with the most recent value for that key. + * + * The given record is expected to be a sanitized record. + * + * Returns YES if there are any pending records in the pendingChangeSetsFromPreviousCommits. +**/ +- (BOOL)mergeChangesForRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier + into:(YDBCKMergeInfo *)mergeInfo; + +#pragma mark Transaction Commit Handling + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the record to the changeSet + * + * The following may be modified: + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withInsertedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the record to the changeSet + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withModifiedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier + originalValues:(NSDictionary *)originalValues; + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withDetachedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the deleted recordID to the changeSet + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed), + * if the mergedRecord disagrees with the pending record. + * - If the mergedRecord contains values that aren're represending in previous commits, + * then it creates a changeSet for the given databaseIdentifier for the current commit, + * and adds a record with the missing values. + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withMergedRecord:(CKRecord *)mergedRecord + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withRemoteDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * This method + * - removes the record from the inFlightChangeSet (if isOpPartialCompletion) + * - if modifications for the same record are queued in other changeSets, then updates the base record (system metadata) + * for those records (such that the have the latest recordChangeTag, etc) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withSavedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier + isOpPartialCompletion:(BOOL)isOpPartialCompletion; + +/** + * This method: + * - modifies the inFlightChangeSet by removing the given recordID from the deletedRecordIDs + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withSavedDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.m new file mode 100644 index 0000000..c64d45f --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeQueue.m @@ -0,0 +1,1205 @@ +#import "YDBCKChangeQueue.h" +#import "YDBCKChangeSet.h" +#import "YDBCKChangeRecord.h" +#import "YDBCKRecord.h" +#import "YapDatabaseCloudKitPrivate.h" +#if DEBUG +#import "YapDebugDictionary.h" +#endif + + +@interface YDBCKChangeQueue () +@property (atomic, readwrite, strong) NSString *lockUUID; +@end + +@implementation YDBCKChangeQueue +{ + BOOL isMasterQueue; + NSLock *masterQueueLock; + + NSMutableArray *oldChangeSets; + + NSArray *newChangeSets; + NSMutableDictionary *newChangeSetsDict; +} + +@dynamic isMasterQueue; +@dynamic isPendingQueue; + +@synthesize lockUUID; + +- (instancetype)initMasterQueue +{ + if ((self = [super init])) + { + isMasterQueue = YES; + masterQueueLock = [[NSLock alloc] init]; + + oldChangeSets = [[NSMutableArray alloc] init]; + } + return self; +} + +#pragma mark Lifecycle + +/** + * This method is used during extension registration + * after the old changeSets, from previous app run(s), have been restored. +**/ +- (void)restoreOldChangeSets:(NSArray *)inOldChangeSets +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + [oldChangeSets addObjectsFromArray:inOldChangeSets]; + } + [masterQueueLock unlock]; +} + +/** + * If there is NOT already an in-flight changeSet, then this method sets the appropriate flag(s), + * and returns the next changeSet ready for upload. +**/ +- (YDBCKChangeSet *)makeInFlightChangeSet:(BOOL *)isAlreadyInFlightPtr +{ + YDBCKChangeSet *inFlightChangeSet = nil; + BOOL isAlreadyInFlight = NO; + + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + YDBCKChangeSet *nextChangeSet = [oldChangeSets firstObject]; + + if (nextChangeSet) + { + if (nextChangeSet.isInFlight) + { + isAlreadyInFlight = YES; + } + else + { + nextChangeSet.isInFlight = YES; + inFlightChangeSet = [nextChangeSet fullCopy]; + } + } + } + [masterQueueLock unlock]; + + if (isAlreadyInFlightPtr) *isAlreadyInFlightPtr = isAlreadyInFlight; + return inFlightChangeSet; +} + +/** + * If there is an in-flight changeSet, + * then this method removes it to make room for new in-flight changeSets. +**/ +- (void)removeCompletedInFlightChangeSet +{ + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + if (firstChangeSet.isInFlight) + { + firstChangeSet.isInFlight = NO; + [oldChangeSets removeObjectAtIndex:0]; + } + } + [masterQueueLock unlock]; +} + +/** + * If there is an in-flight changeSet, + * then this method "resets" it so it can be restarted again (when ready). +**/ +- (void)resetFailedInFlightChangeSet +{ + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + if (firstChangeSet.isInFlight) + { + firstChangeSet.isInFlight = NO; + } + } + [masterQueueLock unlock]; +} + +/** + * Invoke this method from 'prepareForReadWriteTransaction' in order to fetch a 'pendingQueue' object. + * + * This pendingQueue object will then be used to keep track of all the changes + * that need to be written to the changesTable. +**/ +- (YDBCKChangeQueue *)newPendingQueue +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSUInteger capacity = [oldChangeSets count] + 1; + + YDBCKChangeQueue *pendingQueue = [[YDBCKChangeQueue alloc] init]; + pendingQueue->isMasterQueue = NO; + pendingQueue->oldChangeSets = [[NSMutableArray alloc] initWithCapacity:capacity]; + + for (YDBCKChangeSet *changeSet in oldChangeSets) + { + [pendingQueue->oldChangeSets addObject:[changeSet emptyCopy]]; + } + + pendingQueue->newChangeSetsDict = [[NSMutableDictionary alloc] initWithCapacity:1]; + + [masterQueueLock lock]; + self.lockUUID = pendingQueue.lockUUID = [[NSUUID UUID] UUIDString]; + + return pendingQueue; +} + +/** + * This should be done AFTER the pendingQueue has been written to disk, + * at the end of the flushPendingChangesToExtensionTables method. +**/ +- (void)mergePendingQueue:(YDBCKChangeQueue *)pendingQueue +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + NSUInteger count = [oldChangeSets count]; + NSAssert(count == [pendingQueue->oldChangeSets count], @"Logic error !"); + + for (NSUInteger index = 0; index < count; index++) + { + YDBCKChangeSet *pending_oldChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pending_oldChangeSet.hasChangesToDeletedRecordIDs || pending_oldChangeSet.hasChangesToModifiedRecords) + { + YDBCKChangeSet *master_oldChangeSet = [self->oldChangeSets objectAtIndex:index]; + + if (pending_oldChangeSet.hasChangesToDeletedRecordIDs) + master_oldChangeSet->deletedRecordIDs = pending_oldChangeSet->deletedRecordIDs; + + if (pending_oldChangeSet.hasChangesToModifiedRecords) + master_oldChangeSet->modifiedRecords = pending_oldChangeSet->modifiedRecords; + } + } + + NSArray *pending_newChangeSets = pendingQueue.changeSetsFromCurrentCommit; + for (YDBCKChangeSet *pending_newChangeSet in pending_newChangeSets) + { + pending_newChangeSet.hasChangesToDeletedRecordIDs = NO; + pending_newChangeSet.hasChangesToModifiedRecords = NO; + + [oldChangeSets addObject:pending_newChangeSet]; + } + + self.lockUUID = nil; + [masterQueueLock unlock]; +} + +#pragma mark Properties + +/** + * Determining queue type. + * Primarily used for sanity checks. +**/ +- (BOOL)isMasterQueue { + return isMasterQueue; +} +- (BOOL)isPendingQueue { + return !isMasterQueue; +} + +#pragma mark Change-Sets Access + +/** + * Returns the changeSet.uuid of the "current" changeSet, + * which is either the inFlightChangeSet, or the next changeSet to go inFlight once resumed. + * + * In other words, the first YDBCKChangeSet in the queue. +**/ +- (NSString *)currentChangeSetUUID +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSString *firstChangeSetUUID = nil; + + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + firstChangeSetUUID = firstChangeSet.uuid; + } + [masterQueueLock unlock]; + + return firstChangeSetUUID; +} + +/** + * Each commit that makes one or more changes to a CKRecord (insert/modify/delete) + * will result in one or more YDBCKChangeSet(s). + * There is one YDBCKChangeSet per databaseIdentifier. + * So a single commit may possibly generate multiple changeSets. + * + * Thus a changeSet encompasses all the relavent CloudKit related changes per database, per commit. +**/ +- (NSArray *)changeSetsFromPreviousCommits +{ + if (self.isMasterQueue) + { + NSMutableArray *oldChangeSetsCopy = nil; + [masterQueueLock lock]; + + if (oldChangeSets.count) + { + oldChangeSetsCopy = [NSMutableArray arrayWithCapacity:oldChangeSets.count]; + + for (YDBCKChangeSet *changeSet in oldChangeSets) + { + [oldChangeSetsCopy addObject:[changeSet fullCopy]]; + } + } + + [masterQueueLock unlock]; + return oldChangeSetsCopy; + } + else // if (self.isPendingQueue) + { + return [oldChangeSets copy]; + } +} +- (NSArray *)changeSetsFromCurrentCommit +{ + NSAssert(self.isPendingQueue, @"Method can only be invoked on pendingQueue"); + + if ((newChangeSets == nil) && ([newChangeSetsDict count] > 0)) + { + NSMutableArray *orderedChangeSets = [NSMutableArray arrayWithCapacity:[newChangeSetsDict count]]; + + NSString *baseUUID = [[NSUUID UUID] UUIDString]; + NSString *prevChangeSetUUID = [[oldChangeSets lastObject] uuid]; + + for (YDBCKChangeSet *newChangeSet in [newChangeSetsDict objectEnumerator]) + { + NSString *uuid = [NSString stringWithFormat:@"%@@%lu", baseUUID, (unsigned long)[orderedChangeSets count]]; + + newChangeSet.uuid = uuid; + newChangeSet.prev = prevChangeSetUUID; + prevChangeSetUUID = newChangeSet.uuid; + + [orderedChangeSets addObject:newChangeSet]; + } + + newChangeSets = [orderedChangeSets copy]; + } + + return newChangeSets; +} + +/** + * See header file for documentation. +**/ +- (NSUInteger)numberOfInFlightChangeSets +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSUInteger count = 0; + [masterQueueLock lock]; + + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + if (firstChangeSet.isInFlight) { + count = 1; + } + + [masterQueueLock unlock]; + return count; +} + +/** + * See header file for documentation. +**/ +- (NSUInteger)numberOfQueuedChangeSets +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSUInteger count = 0; + [masterQueueLock lock]; + + count = [oldChangeSets count]; + + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + if (firstChangeSet.isInFlight) { + count--; + } + + [masterQueueLock unlock]; + return count; +} + +/** + * See header file for documentation. +**/ +- (NSUInteger)numberOfPendingChangeSets +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSUInteger count = 0; + [masterQueueLock lock]; + + count = [oldChangeSets count]; + + [masterQueueLock unlock]; + return count; +} + +/** + * Atomic access to all counts at once. +**/ +- (void)getNumberOfInFlightChangeSets:(NSUInteger *)numInFlightChangeSetsPtr + queuedChangeSets:(NSUInteger *)numQueuedChangeSetsPtr +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + + NSUInteger inFlightCount = 0; + NSUInteger queuedCount = 0; + + [masterQueueLock lock]; + + queuedCount = [oldChangeSets count]; + + YDBCKChangeSet *firstChangeSet = [oldChangeSets firstObject]; + if (firstChangeSet.isInFlight) { + inFlightCount++; + queuedCount--; + } + + [masterQueueLock unlock]; + + if (numInFlightChangeSetsPtr) *numInFlightChangeSetsPtr = inFlightCount; + if (numQueuedChangeSetsPtr) *numQueuedChangeSetsPtr = queuedCount; +} + +#pragma mark Utilities + +- (id)keyForDatabaseIdentifier:(NSString *)databaseIdentifier +{ + if (databaseIdentifier) + return databaseIdentifier; + else + return [NSNull null]; +} + +static BOOL CompareDatabaseIdentifiers(NSString *dbid1, NSString *dbid2) +{ + if (dbid1 == nil) { + return (dbid2 == nil); + } + else { + return [dbid1 isEqualToString:dbid2]; + } +} + +#pragma mark Merge Handling + +/** + * Check in pendingChangeSetsFromPreviousCommits to see what kind of changes are pending. +**/ +- (void)getHasPendingModification:(BOOL *)outHasPendingModification + hasPendingDelete:(BOOL *)outHasPendingDelete + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + BOOL hasPendingModification = NO; + BOOL hasPendingDelete = NO; + + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + + @try { + + for (YDBCKChangeSet *prevChangeSet in oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, prevChangeSet.databaseIdentifier)) + { + if ([prevChangeSet->modifiedRecords objectForKey:recordID]) + { + hasPendingModification = YES; + } + + if ([prevChangeSet->deletedRecordIDs containsObject:recordID]) + { + hasPendingDelete = YES; + } + } + } + + } @finally { + + [masterQueueLock unlock]; + } + + if (outHasPendingModification) *outHasPendingModification = hasPendingModification; + if (outHasPendingDelete) *outHasPendingDelete = hasPendingDelete; +} + +/** + * This method enumerates pendingChangeSetsFromPreviousCommits, from oldest commit to newest commit, + * and merges the changedKeys & values into the given record. + * Thus, if the value for a particular key has been changed multiple times, + * then the given record will end up with the most recent value for that key. + * + * The given record is expected to be a sanitized record. + * + * Returns YES if there were any pending records in the pendingChangeSetsFromPreviousCommits. +**/ +- (BOOL)mergeChangesForRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier + into:(YDBCKMergeInfo *)mergeInfo +{ + BOOL hasPendingChanges = NO; + + // Get lock for access to 'oldChangeSets' + [masterQueueLock lock]; + { + for (YDBCKChangeSet *prevChangeSet in oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, prevChangeSet.databaseIdentifier)) + { + YDBCKChangeRecord *prevRecord = [prevChangeSet->modifiedRecords objectForKey:recordID]; + if (prevRecord) + { + [mergeInfo mergeNewerRecord:prevRecord.record newerOriginalValues:prevRecord.originalValues]; + + hasPendingChanges = YES; + } + } + } + } + [masterQueueLock unlock]; + + return hasPendingChanges; +} + +#pragma mark Transaction Handling + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the record to the changeSet + * + * The following may be modified: + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withInsertedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + CKRecordID *recordID = record.recordID; + + // Create change record + + YDBCKChangeRecord *currentRecord = [[YDBCKChangeRecord alloc] initWithRecord:record]; + currentRecord.needsStoreFullRecord = NO; + + // Update current changeSet + + id key = [self keyForDatabaseIdentifier:databaseIdentifier]; + + YDBCKChangeSet *currentChangeSet = [pendingQueue->newChangeSetsDict objectForKey:key]; + if (currentChangeSet == nil) + { + currentChangeSet = [[YDBCKChangeSet alloc] initWithDatabaseIdentifier:databaseIdentifier]; + [pendingQueue->newChangeSetsDict setObject:currentChangeSet forKey:key]; + } + +#if DEBUG + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = [[YapDebugDictionary alloc] initWithKeyClass:[CKRecordID class] + objectClass:[YDBCKChangeRecord class]]; +#else + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = [[NSMutableDictionary alloc] init]; +#endif + + [currentChangeSet->modifiedRecords setObject:currentRecord forKey:recordID]; +} + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the record to the changeSet + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withModifiedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier + originalValues:(NSDictionary *)originalValues +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + CKRecordID *recordID = record.recordID; + + // Create change record + + YDBCKChangeRecord *currentRecord = [[YDBCKChangeRecord alloc] initWithRecord:record]; + currentRecord.needsStoreFullRecord = NO; + currentRecord.originalValues = originalValues; + + // Update previous changeSets (if needed) + + NSUInteger index = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + YDBCKChangeRecord *mqPrevRecord = [mqPrevChangeSet->modifiedRecords objectForKey:recordID]; + if (mqPrevRecord) + { + if (mqPrevRecord.needsStoreFullRecord == NO && + [mqPrevRecord.changedKeysSet intersectsSet:currentRecord.changedKeysSet]) + { + // The prevRecord is configured to only store the changedKeys array to disk. + // + // However, we're now seeing conflicting changes to the same CKRecord. + // For example: + // - a previous commit (not yet pushed to the cloud) changed CKRecord.firstName. + // - and this commit is also changing CKRecord.firstName. + // + // We can only use the changedKeys shortcut when it's possible for use to retrieve + // the corresponding values from the object. However, when this type of 'conflict' occurs, + // we can no longer use that shortcut. So we must modify the persisted information for + // the previous commit so that it stores the previous CKRecord in full, + // as opposed to just the changedKeys. + + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + YDBCKChangeRecord *pqPrevRecord = [pqPrevChangeSet->modifiedRecords objectForKey:recordID]; + pqPrevRecord.needsStoreFullRecord = YES; + } + } + } + + index++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in changeSets) + + // Update current changeSet + + id key = [self keyForDatabaseIdentifier:databaseIdentifier]; + + YDBCKChangeSet *currentChangeSet = [pendingQueue->newChangeSetsDict objectForKey:key]; + if (currentChangeSet == nil) + { + currentChangeSet = [[YDBCKChangeSet alloc] initWithDatabaseIdentifier:databaseIdentifier]; + [pendingQueue->newChangeSetsDict setObject:currentChangeSet forKey:key]; + } + +#if DEBUG + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = [[YapDebugDictionary alloc] initWithKeyClass:[CKRecordID class] + objectClass:[YDBCKChangeRecord class]]; +#else + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = [[NSMutableDictionary alloc] init]; +#endif + + [currentChangeSet->modifiedRecords setObject:currentRecord forKey:recordID]; +} + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withDetachedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + + // Update previous changeSets (if needed) + + NSUInteger index = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + YDBCKChangeRecord *mqPrevRecord = [mqPrevChangeSet->modifiedRecords objectForKey:recordID]; + if (mqPrevRecord) + { + if (mqPrevRecord.needsStoreFullRecord == NO) + { + // The masterPrevRecord is configured to only store the changedKeys array to disk. + // + // However, we're now detaching the rowid from the CKRecord. + // + // We can only use the changedKeys shortcut when it's possible for use to retrieve + // the corresponding values from the object. However, when the rowid is detached, + // we can no longer use that shortcut. So we must modify the persisted information for + // the previous commit so that it stores the previous CKRecord in full, + // as opposed to just the changedKeys. + + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + YDBCKChangeRecord *pqPrevRecord = [pqPrevChangeSet->modifiedRecords objectForKey:recordID]; + pqPrevRecord.needsStoreFullRecord = YES; + } + } + } + + index++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in changeSets) +} + +/** + * This method: + * - creates a changeSet for the given databaseIdentifier for the current commit (if needed) + * - adds the deleted recordID to the changeSet + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + + // Update previous changeSets (if needed) + + NSUInteger index = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + YDBCKChangeRecord *mqPrevRecord = [mqPrevChangeSet->modifiedRecords objectForKey:recordID]; + if (mqPrevRecord) + { + if (mqPrevRecord.needsStoreFullRecord == NO) + { + // The mqPrevRecord is configured to only store the changedKeys array to disk. + // + // However, we're now seeing conflicting changes to the same CKRecord. + // For example: + // - a previous commit (not yet pushed to the cloud) changed CKRecord.firstName. + // - and this commit is deleting the same CKRecord. + // + // We can only use the changedKeys shortcut when it's possible for use to retrieve + // the corresponding values from the object. However, when this type of 'conflict' occurs, + // we can no longer use that shortcut. So we must modify the persisted information for + // the previous commit so that it stores the previous CKRecord in full, + // as opposed to just the changedKeys. + + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + YDBCKChangeRecord *pqPrevRecord = [pqPrevChangeSet->modifiedRecords objectForKey:recordID]; + pqPrevRecord.needsStoreFullRecord = YES; + } + } + } + + index++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + + // Update current changeSet + + id key = [self keyForDatabaseIdentifier:databaseIdentifier]; + + YDBCKChangeSet *currentChangeSet = [pendingQueue->newChangeSetsDict objectForKey:key]; + if (currentChangeSet == nil) + { + currentChangeSet = [[YDBCKChangeSet alloc] initWithDatabaseIdentifier:databaseIdentifier]; + [pendingQueue->newChangeSetsDict setObject:currentChangeSet forKey:key]; + } + + [currentChangeSet->modifiedRecords removeObjectForKey:recordID]; + + if (currentChangeSet->deletedRecordIDs == nil) { + currentChangeSet->deletedRecordIDs = [[NSMutableArray alloc] init]; + } + + [currentChangeSet->deletedRecordIDs addObject:recordID]; +} + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed), + * if the mergedRecord disagrees with the pending record. + * - If the mergedRecord contains values that aren're represending in previous commits, + * then it creates a changeSet for the given databaseIdentifier for the current commit, + * and adds a record with the missing values. + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits + * - pendingQueue.changeSetsFromCurrentCommit +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withMergedRecord:(CKRecord *)mergedRecord + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + + // Update previous changeSets (if needed) + + NSSet *mergedRecordChangedKeysSet = [NSSet setWithArray:mergedRecord.changedKeys]; + NSMutableSet *mergedRecordHandledKeys = [NSMutableSet setWithCapacity:mergedRecord.changedKeys.count]; + + NSMutableSet *keysToRemove = nil; + NSMutableSet *keysToCompare = nil; + + CKRecordID *recordID = mergedRecord.recordID; + + NSUInteger index = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + YDBCKChangeRecord *mqPrevRecord = [mqPrevChangeSet->modifiedRecords objectForKey:recordID]; + if (mqPrevRecord) + { + CKRecord *localRecord = mqPrevRecord.record; + NSSet *localRecordChangedKeysSet = mqPrevRecord.changedKeysSet; + + if (keysToRemove == nil) + keysToRemove = [NSMutableSet setWithCapacity:localRecordChangedKeysSet.count]; + else + [keysToRemove removeAllObjects]; + + if (keysToCompare == nil) + keysToCompare = [NSMutableSet setWithCapacity:localRecordChangedKeysSet.count]; + else + [keysToCompare removeAllObjects]; + + for (NSString *key in localRecordChangedKeysSet) + { + if ([mergedRecordChangedKeysSet containsObject:key]) + [keysToCompare addObject:key]; + else + [keysToRemove addObject:key]; + } + + for (NSString *key in keysToCompare) + { + id localValue = [localRecord objectForKey:key]; + id mergedValue = [mergedRecord objectForKey:key]; + + if ((localValue == nil && mergedValue == nil) || [localValue isEqual:mergedValue]) + { + [mergedRecordHandledKeys addObject:key]; + } + else + { + [keysToRemove addObject:key]; + } + } + + // We need to get the system metadata from the mergedRecord, + // and inject the values from the localRecord. + CKRecord *newLocalRecord = [mergedRecord sanitizedCopy]; + + for (NSString *key in localRecord.changedKeys) + { + if (![keysToRemove containsObject:key]) + { + // Remember: nil is a valid value. + // It indicates removal of the value for the key, which is a valid action. + + id value = [localRecord objectForKey:key]; + [newLocalRecord setObject:value forKey:key]; + } + } + + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords + copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + if (newLocalRecord.changedKeys.count > 0) + { + // Update the record using the merged newLocalRecord + + YDBCKChangeRecord *pqPrevRecord = [pqPrevChangeSet->modifiedRecords objectForKey:recordID]; + pqPrevRecord.record = newLocalRecord; + } + else + { + // Remove the record from the change-set. + // There's no longer any need to upload it since we've dismissed all the queued changes. + + [pqPrevChangeSet->modifiedRecords removeObjectForKey:recordID]; + } + + } // end if (mqPrevRecord) + } // end if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + + index++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + + if (mergedRecordChangedKeysSet.count != mergedRecordHandledKeys.count) + { + // There are key/value pairs in the mergedRecord that aren't represented in any of the pendingLocalRecord's. + // So we need to add these to a new CKRecord, and queue that record for upload to the server. + + NSMutableSet *mergedRecordUnhandledKeys = [mergedRecordChangedKeysSet mutableCopy]; + [mergedRecordUnhandledKeys minusSet:mergedRecordHandledKeys]; + + CKRecord *newMergedRecord = [mergedRecord sanitizedCopy]; + + for (NSString *key in mergedRecordUnhandledKeys) + { + // Remember: nil is a valid value. + // It indicates removal of the value for the key, which is a valid action. + + id value = [mergedRecord objectForKey:key]; + [newMergedRecord setObject:value forKey:key]; + } + + // Add newMergedRecord to a new YDBCKChangeRecord, + // and add to newChangeSets for this transaction. + + YDBCKChangeRecord *currentRecord = [[YDBCKChangeRecord alloc] initWithRecord:newMergedRecord]; + currentRecord.needsStoreFullRecord = NO; + + id key = [self keyForDatabaseIdentifier:databaseIdentifier]; + + YDBCKChangeSet *currentChangeSet = [pendingQueue->newChangeSetsDict objectForKey:key]; + if (currentChangeSet == nil) + { + currentChangeSet = [[YDBCKChangeSet alloc] initWithDatabaseIdentifier:databaseIdentifier]; + [pendingQueue->newChangeSetsDict setObject:currentChangeSet forKey:key]; + } + + #if DEBUG + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithKeyClass:[CKRecordID class] + objectClass:[YDBCKChangeRecord class]]; + #else + if (currentChangeSet->modifiedRecords == nil) + currentChangeSet->modifiedRecords = [[NSMutableDictionary alloc] init]; + #endif + + [currentChangeSet->modifiedRecords setObject:currentRecord forKey:recordID]; + } +} + +/** + * This method: + * - modifies the changeSets from previous commits that also modified the same record (if needed) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withRemoteDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + + // Update previous changeSets (if needed) + + NSUInteger index = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + // Check to see if we have queued modifications to push for this item + + YDBCKChangeRecord *mqPrevRecord = [mqPrevChangeSet->modifiedRecords objectForKey:recordID]; + if (mqPrevRecord) + { + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + [pqPrevChangeSet->modifiedRecords removeObjectForKey:recordID]; + } + + // Check to see if we have queued deletion for this item + + if ([mqPrevChangeSet->deletedRecordIDs containsObject:recordID]) + { + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:index]; + if (pqPrevChangeSet->deletedRecordIDs == nil) + { + pqPrevChangeSet->deletedRecordIDs = [mqPrevChangeSet->deletedRecordIDs copy]; + pqPrevChangeSet.hasChangesToDeletedRecordIDs = YES; + } + + [pqPrevChangeSet->deletedRecordIDs removeObject:recordID]; + + } + + } // end if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + + index++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) +} + +/** + * This method + * - removes the record from the inFlightChangeSet (if isOpPartialCompletion) + * - if modifications for the same record are queued in other changeSets, then updates the base record (system metadata) + * for those records (such that the have the latest recordChangeTag, etc) + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withSavedRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier + isOpPartialCompletion:(BOOL)isOpPartialCompletion +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + CKRecordID *recordID = record.recordID; + + // Update inFlight changeSet of pendingQueue (if needed) + + if (isOpPartialCompletion) + { + YDBCKChangeSet *pqInFlightChangeSet = [pendingQueue->oldChangeSets firstObject]; + + if (pqInFlightChangeSet->modifiedRecords == nil) + { + YDBCKChangeSet *mqInFlightChangeSet = [masterQueue->oldChangeSets firstObject]; + + if (mqInFlightChangeSet->modifiedRecords) + { + #if DEBUG + pqInFlightChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqInFlightChangeSet->modifiedRecords copyItems:YES]; + #else + pqInFlightChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqInFlightChangeSet->modifiedRecords copyItems:YES]; + #endif + } + else + { + #if DEBUG + pqInFlightChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithKeyClass:[CKRecordID class] + objectClass:[YDBCKChangeRecord class]]; + #else + pqInFlightChangeSet->modifiedRecords = [[NSMutableDictionary alloc] init]; + #endif + } + + pqInFlightChangeSet.hasChangesToModifiedRecords = YES; + } + + [pqInFlightChangeSet->modifiedRecords removeObjectForKey:recordID]; + } + + // Update previous changeSets (if needed) + + CKRecord *sanitizedRecord = nil; + + NSUInteger i = 0; + for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) + { + // Skip inFlight changeSet + if (i == 0) { + i++; + continue; + } + + // Process other previous changeSets + + if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + { + if ([mqPrevChangeSet->modifiedRecords objectForKey:recordID]) + { + YDBCKChangeSet *pqPrevChangeSet = [pendingQueue->oldChangeSets objectAtIndex:i]; + + if (pqPrevChangeSet->modifiedRecords == nil) + { + #if DEBUG + pqPrevChangeSet->modifiedRecords = + [[YapDebugDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords copyItems:YES]; + #else + pqPrevChangeSet->modifiedRecords = + [[NSMutableDictionary alloc] initWithDictionary:mqPrevChangeSet->modifiedRecords copyItems:YES]; + #endif + + pqPrevChangeSet.hasChangesToModifiedRecords = YES; + } + + if (sanitizedRecord == nil) + { + sanitizedRecord = [record sanitizedCopy]; + } + + YDBCKChangeRecord *pqChangeRecord = [pqPrevChangeSet->modifiedRecords objectForKey:recordID]; + + CKRecord *originalRecord = pqChangeRecord.record; + CKRecord *mergedRecord = [sanitizedRecord safeCopy]; + + // The 'originalRecord' contains all the values we need to sync to the cloud. + // But the 'sanitizedRecord' contains the proper system fields within the CKRecord internals + // that reflect the proper sync state we have with the server. + // + // Because the internal sync-state stuff is private, we cannot access it. + // So we copy the needed values from the originalRecord into a new CKRecord container + // that already has the updated sync-state fields. + + for (NSString *changedKey in [originalRecord changedKeys]) + { + // Remember: nil is a valid value. + // It indicates removal of the value for the key, which is a valid action. + + id value = [originalRecord objectForKey:changedKey]; + [mergedRecord setObject:value forKey:changedKey]; + } + + pqChangeRecord.record = mergedRecord; + + } // end if ([mqPrevChangeSet->modifiedRecords objectForKey:recordID]) + } // end if (CompareDatabaseIdentifiers(databaseIdentifier, mqPrevChangeSet.databaseIdentifier)) + + i++; + } // end for (YDBCKChangeSet *mqPrevChangeSet in masterQueue->oldChangeSets) +} + +/** + * This method: + * - modifies the inFlightChangeSet by removing the given recordID from the deletedRecordIDs + * + * The following may be modified: + * - pendingQueue.changeSetsFromPreviousCommits +**/ +- (void)updatePendingQueue:(YDBCKChangeQueue *)pendingQueue + withSavedDeletedRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + NSAssert(self.isMasterQueue, @"Method can only be invoked on masterQueue"); + NSAssert(pendingQueue.isPendingQueue, @"Bad parameter: 'pendingQueue' is not a pendingQueue"); + NSAssert(pendingQueue->newChangeSets == nil, @"Cannot modify pendingQueue after newChangeSets has been fetched"); + NSAssert([self.lockUUID isEqualToString:pendingQueue.lockUUID], @"Bad state: Not locked for pendingQueue"); + + __unsafe_unretained typeof(self) masterQueue = self; + + // Update inFlight changeSet of pendingQueue + + YDBCKChangeSet *pqInFlightChangeSet = [pendingQueue->oldChangeSets firstObject]; + + if (pqInFlightChangeSet->deletedRecordIDs == nil) + { + YDBCKChangeSet *mqInFlightChangeSet = [masterQueue->oldChangeSets firstObject]; + + pqInFlightChangeSet->deletedRecordIDs = [mqInFlightChangeSet->deletedRecordIDs copy]; + } + + NSUInteger index = [pqInFlightChangeSet->deletedRecordIDs indexOfObject:recordID]; + if (index != NSNotFound) + { + [pqInFlightChangeSet->deletedRecordIDs removeObjectAtIndex:index]; + pqInFlightChangeSet.hasChangesToDeletedRecordIDs = YES; + } +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h new file mode 100644 index 0000000..6cf05ab --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.h @@ -0,0 +1,18 @@ +#import +#import + + +@interface YDBCKChangeRecord : NSObject + +- (instancetype)initWithRecord:(CKRecord *)record; + +@property (nonatomic, strong, readwrite) CKRecord *record; + +@property (nonatomic, assign, readwrite) BOOL needsStoreFullRecord; +@property (nonatomic, strong, readwrite) NSDictionary *originalValues; + +@property (nonatomic, readonly) CKRecordID *recordID; +@property (nonatomic, readonly) NSArray *changedKeys; +@property (nonatomic, readonly) NSSet *changedKeysSet; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.m new file mode 100644 index 0000000..8881535 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKChangeRecord.m @@ -0,0 +1,120 @@ +#import "YDBCKChangeRecord.h" +#import "YDBCKRecord.h" + +static NSString *const k_record = @"record"; +static NSString *const k_originalValues = @"originalValues"; +static NSString *const k_recordID = @"recordID"; +static NSString *const k_changedKeys = @"changedKeys"; + +@implementation YDBCKChangeRecord +{ + CKRecordID *recordID; + + NSArray *changedKeys; + NSSet *changedKeysSet; +} + +@synthesize record = record; +@synthesize needsStoreFullRecord = needsStoreFullRecord; +@synthesize originalValues = originalValues; + +@dynamic recordID; +@dynamic changedKeys; +@dynamic changedKeysSet; + +- (instancetype)initWithRecord:(CKRecord *)inRecord +{ + if ((self = [super init])) + { + record = inRecord; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone +{ + YDBCKChangeRecord *copy = [[YDBCKChangeRecord alloc] init]; + + // Important: We MUST make a copy of the record so each changeSet.record is unique ! + // This is to ensure that modifying changeRecords in the pendingQueue doesn't interfere with the masterQueue. + copy->record = [record safeCopy]; + + copy->needsStoreFullRecord = needsStoreFullRecord; + copy->originalValues = originalValues; + + copy->recordID = recordID; + copy->changedKeys = changedKeys; + + return copy; +} + +- (instancetype)initWithCoder:(NSCoder *)decoder +{ + if ((self = [super init])) + { + record = [decoder decodeObjectForKey:k_record]; + + originalValues = [decoder decodeObjectForKey:k_originalValues]; + + recordID = [decoder decodeObjectForKey:k_recordID]; + changedKeys = [decoder decodeObjectForKey:k_changedKeys]; + + if (record) + needsStoreFullRecord = YES; + else + needsStoreFullRecord = NO; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + if (needsStoreFullRecord) + { + [coder encodeObject:record forKey:k_record]; + } + else + { + [coder encodeObject:self.recordID forKey:k_recordID]; + [coder encodeObject:self.changedKeys forKey:k_changedKeys]; + } + + [coder encodeObject:originalValues forKey:k_originalValues]; +} + +- (void)setRecord:(CKRecord *)inRecord +{ + recordID = nil; + changedKeys = nil; + changedKeysSet = nil; + + record = inRecord; +} + +- (CKRecordID *)recordID +{ + if (recordID) + return recordID; + else + return record.recordID; +} + +- (NSArray *)changedKeys +{ + if (changedKeys) + return changedKeys; + else + return record.changedKeys; +} + +- (NSSet *)changedKeysSet +{ + if (changedKeysSet == nil) // Generated on-demand (if needed) + { + changedKeysSet = [[NSSet alloc] initWithArray:self.changedKeys]; + } + + return changedKeysSet; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h new file mode 100644 index 0000000..bcdf225 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.h @@ -0,0 +1,47 @@ +#import +#import + +@class YDBCKDirtyMappingTableInfo; + +@protocol YDBCKMappingTableInfo +@property (nonatomic, strong, readonly) NSString *current_recordTable_hash; +@end + +/** + * This class represents information about an unmodified row in the mapping table. + * + * YapDatabaseCloudKitConnection.cleanMappingTableInfo stores instances of this type: + * + * cleanMappingTableInfo.key = rowid (NSNumber) + * cleanMappingTableInfo.value = YDBCKCleanMappingTableInfo +**/ +@interface YDBCKCleanMappingTableInfo : NSObject + +- (instancetype)initWithRecordTableHash:(NSString *)hash; + +@property (nonatomic, strong, readonly) NSString *recordTable_hash; + +- (YDBCKDirtyMappingTableInfo *)dirtyCopy; + +@end + +#pragma mark - + +/** + * This class represents information about a modified row in the mapping table. + * + * YapDatabaseCloudKitConnection.dirtyMappingTableInfo stores instances of this type: + * + * dirtyMappingTableInfo.key = rowid (NSNumber) + * dirtyMappingTableInfo.value = YDBCKDirtyMappingTableInfo +**/ +@interface YDBCKDirtyMappingTableInfo : NSObject + +- (instancetype)initWithRecordTableHash:(NSString *)hash; + +@property (nonatomic, strong, readonly) NSString *clean_recordTable_hash; +@property (nonatomic, strong, readwrite) NSString *dirty_recordTable_hash; + +- (YDBCKCleanMappingTableInfo *)cleanCopy; + +@end \ No newline at end of file diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.m new file mode 100644 index 0000000..dde40be --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKMappingTableInfo.m @@ -0,0 +1,60 @@ +#import "YDBCKMappingTableInfo.h" + + +@implementation YDBCKCleanMappingTableInfo + +@synthesize recordTable_hash = recordTable_hash; + +- (instancetype)initWithRecordTableHash:(NSString *)hash +{ + if ((self = [super init])) + { + recordTable_hash = hash; + } + return self; +} + +- (NSString *)current_recordTable_hash { + return recordTable_hash; +} + +- (YDBCKDirtyMappingTableInfo *)dirtyCopy +{ + YDBCKDirtyMappingTableInfo *dirtyCopy = + [[YDBCKDirtyMappingTableInfo alloc] initWithRecordTableHash:recordTable_hash]; + + return dirtyCopy; +} + +@end + +#pragma mark - + +@implementation YDBCKDirtyMappingTableInfo + +@synthesize clean_recordTable_hash = clean_recordTable_hash; +@synthesize dirty_recordTable_hash = dirty_recordTable_hash; + +- (instancetype)initWithRecordTableHash:(NSString *)hash +{ + if ((self = [super init])) + { + clean_recordTable_hash = hash; + dirty_recordTable_hash = hash; + } + return self; +} + +- (NSString *)current_recordTable_hash { + return dirty_recordTable_hash; +} + +- (YDBCKCleanMappingTableInfo *)cleanCopy +{ + YDBCKCleanMappingTableInfo *cleanCopy = + [[YDBCKCleanMappingTableInfo alloc] initWithRecordTableHash:dirty_recordTable_hash]; + + return cleanCopy; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h new file mode 100644 index 0000000..44c3603 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.h @@ -0,0 +1,84 @@ +#import +#import + +@class YDBCKDirtyRecordTableInfo; + +@protocol YDBCKRecordTableInfo + +@property (nonatomic, readonly) NSString * databaseIdentifier; +@property (nonatomic, readonly) CKRecord * current_record; +@property (nonatomic, readonly) int64_t current_ownerCount; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This class represents information about an unmodified row in the record table. + * + * YapDatabaseCloudKitConnection.cleanRecordTableInfo stores objects of this type: + * + * cleanRecordTableInfo.key = Hash(CKRecordID + databaseIdentifier) + * cleanRecordTableInfo.value = YDBCKCleanRecordTableInfo +**/ +@interface YDBCKCleanRecordTableInfo : NSObject + +- (instancetype)initWithDatabaseIdentifier:(NSString *)databaseIdentifier + ownerCount:(int64_t)ownerCount + record:(CKRecord *)record; + +@property (nonatomic, readonly) NSString * databaseIdentifier; +@property (nonatomic, readonly) int64_t ownerCount; +@property (nonatomic, readonly) CKRecord * record; + +- (YDBCKDirtyRecordTableInfo *)dirtyCopy; + +- (YDBCKCleanRecordTableInfo *)cleanCopyWithSanitizedRecord:(CKRecord *)record; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This class represents information about a modified row in the record table. + * + * YapDatabaseCloudKitConnection.dirtyRecordTableInfo dictionary stores objects of this type: + * + * dirtyRecordTableInfo.key = Hash(CKRecordID + databaseIdentifier) + * dirtyRecordTableInfo.value = YDBCKDirtyRecordTableInfo +**/ +@interface YDBCKDirtyRecordTableInfo : NSObject + +- (instancetype)initWithDatabaseIdentifier:(NSString *)databaseIdentifier + recordID:(CKRecordID *)recordID + ownerCount:(int64_t)clean_ownerCount; + +@property (nonatomic, readonly) NSString *databaseIdentifier; +@property (nonatomic, readonly) CKRecordID *recordID; + +@property (nonatomic, readonly) int64_t clean_ownerCount; // represents what's on disk + +@property (nonatomic, assign, readonly) int64_t dirty_ownerCount; // represents new value (this transaction) +@property (nonatomic, strong, readwrite) CKRecord *dirty_record; // represents new value (this transaction) + +@property (nonatomic, assign, readwrite) BOOL skipUploadRecord; +@property (nonatomic, assign, readwrite) BOOL skipUploadDeletion; +@property (nonatomic, assign, readwrite) BOOL remoteDeletion; +@property (nonatomic, assign, readwrite) BOOL remoteMerge; + +@property (nonatomic, copy, readonly) NSDictionary *originalValues; +- (void)mergeOriginalValues:(NSDictionary *)inOriginalValues; + +- (void)incrementOwnerCount; +- (void)decrementOwnerCount; + +- (BOOL)ownerCountChanged; +- (BOOL)hasNilRecordOrZeroOwnerCount; + +- (YDBCKCleanRecordTableInfo *)cleanCopyWithSanitizedRecord:(CKRecord *)record; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.m new file mode 100644 index 0000000..8740cb0 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YDBCKRecordTableInfo.m @@ -0,0 +1,163 @@ +#import "YDBCKRecordTableInfo.h" +#import "YDBCKRecord.h" + + +@implementation YDBCKCleanRecordTableInfo + +@synthesize databaseIdentifier = databaseIdentifier; +@synthesize ownerCount = ownerCount; +@synthesize record = record; + +- (instancetype)initWithDatabaseIdentifier:(NSString *)inDatabaseIdentifier + ownerCount:(int64_t)inOwnerCount + record:(CKRecord *)inRecord +{ + if ((self = [super init])) + { + databaseIdentifier = inDatabaseIdentifier; + ownerCount = inOwnerCount; + record = inRecord; + } + return self; +} + +- (YDBCKDirtyRecordTableInfo *)dirtyCopy +{ + YDBCKDirtyRecordTableInfo *dirtyCopy = + [[YDBCKDirtyRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + recordID:record.recordID + ownerCount:ownerCount]; + + dirtyCopy.dirty_record = [record safeCopy]; + + return dirtyCopy; +} + +- (YDBCKCleanRecordTableInfo *)cleanCopyWithSanitizedRecord:(CKRecord *)newRecord +{ + YDBCKCleanRecordTableInfo *copy = [[YDBCKCleanRecordTableInfo alloc] init]; + copy->databaseIdentifier = databaseIdentifier; + copy->ownerCount = ownerCount; + copy->record = newRecord; + + return copy; +} + +- (CKRecord *)current_record { + return record; +} + +- (int64_t)current_ownerCount { + return ownerCount; +} + +@end + +#pragma mark - + +@implementation YDBCKDirtyRecordTableInfo + +@synthesize databaseIdentifier = databaseIdentifier; +@synthesize recordID = recordID; + +@synthesize clean_ownerCount = clean_ownerCount; + +@synthesize dirty_record = dirty_record; +@synthesize dirty_ownerCount = dirty_ownerCount; + +@synthesize skipUploadRecord; +@synthesize skipUploadDeletion; +@synthesize remoteDeletion; +@synthesize remoteMerge; + +@synthesize originalValues = originalValues; + +- (instancetype)initWithDatabaseIdentifier:(NSString *)inDatabaseIdentifier + recordID:(CKRecordID *)inRecordID + ownerCount:(int64_t)in_ownerCount +{ + if ((self = [super init])) + { + databaseIdentifier = [inDatabaseIdentifier copy]; + recordID = inRecordID; + + clean_ownerCount = in_ownerCount; + dirty_ownerCount = in_ownerCount; + } + return self; +} + +- (CKRecord *)current_record { + return dirty_record; +} + +- (int64_t)current_ownerCount { + return dirty_ownerCount; +} + +- (void)mergeOriginalValues:(NSDictionary *)inOriginalValues +{ + if (inOriginalValues == nil) return; + + if (originalValues == nil) + { + originalValues = [inOriginalValues copy]; + } + else + { + __block NSMutableDictionary *newOriginalValues = nil; + + [inOriginalValues enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + if ([originalValues objectForKey:key] == nil) + { + if (newOriginalValues == nil) + newOriginalValues = [originalValues mutableCopy]; + + [newOriginalValues setObject:obj forKey:key]; + } + }]; + + if (newOriginalValues) { + originalValues = [newOriginalValues copy]; + } + } +} + +- (void)incrementOwnerCount +{ + if (dirty_ownerCount < INT64_MAX) { + dirty_ownerCount++; + } +} + +- (void)decrementOwnerCount +{ + if (dirty_ownerCount > 0) { + dirty_ownerCount--; + } +} + +- (BOOL)ownerCountChanged +{ + return (clean_ownerCount != dirty_ownerCount); +} + +- (BOOL)hasNilRecordOrZeroOwnerCount +{ + if (dirty_record == 0) return YES; + if (dirty_ownerCount <= 0) return YES; + + return NO; +} + +- (YDBCKCleanRecordTableInfo *)cleanCopyWithSanitizedRecord:(CKRecord *)newRecord +{ + YDBCKCleanRecordTableInfo *cleanCopy = + [[YDBCKCleanRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + ownerCount:dirty_ownerCount + record:newRecord]; + return cleanCopy; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h new file mode 100644 index 0000000..b6473e1 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Internal/YapDatabaseCloudKitPrivate.h @@ -0,0 +1,251 @@ +#import + +#import "YapDatabase.h" +#import "YapDatabaseConnection.h" +#import "YapDatabaseTransaction.h" + +#import "YapDatabaseCloudKit.h" +#import "YapDatabaseCloudKitTypes.h" +#import "YapDatabaseCloudKitOptions.h" +#import "YapDatabaseCloudKitConnection.h" +#import "YapDatabaseCloudKitTransaction.h" + +#import "YDBCKRecordInfo.h" +#import "YDBCKRecordTableInfo.h" +#import "YDBCKMappingTableInfo.h" +#import "YDBCKChangeQueue.h" +#import "YDBCKChangeRecord.h" + +#import "YapDatabaseExtensionPrivate.h" +#import "YapCache.h" +#if DEBUG +#import "YapDebugDictionary.h" +#endif + +#import "sqlite3.h" + +/** + * This version number is stored in the yap2 table. + * If there is a major re-write to this class, then the version number will be incremented, + * and the class can automatically rebuild the tables as needed. +**/ +#define YAP_DATABASE_CLOUD_KIT_CLASS_VERSION 3 + +static NSString *const changeset_key_deletedRowids = @"deletedRowids"; // Array: rowid +static NSString *const changeset_key_deletedHashes = @"deletedHashes"; // Array: string +static NSString *const changeset_key_mappingTableInfo = @"mappingTableInfo"; // Dict : rowid -> CleanMappingTableInfo +static NSString *const changeset_key_recordTableInfo = @"recordTableInfo"; // Dict : string -> CleanRecordTableInfo +static NSString *const changeset_key_reset = @"reset"; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YDBCKRecordInfo () + +@property (nonatomic, strong, readwrite) id versionInfo; +@property (nonatomic, strong, readwrite) NSArray *keysToRestore; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YDBCKMergeInfo () + +@property (nonatomic, strong, readwrite) CKRecord *pendingLocalRecord; +@property (nonatomic, strong, readwrite) CKRecord *updatedPendingLocalRecord; + +- (void)mergeNewerRecord:(CKRecord *)newerRecord newerOriginalValues:(NSDictionary *)newerOriginalValues; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseCloudKit () { +@public + + YapDatabaseCloudKitRecordBlock recordBlock; + YapDatabaseCloudKitBlockType recordBlockType; + + YapDatabaseCloudKitMergeBlock mergeBlock; + YapDatabaseCloudKitOperationErrorBlock opErrorBlock; + YapDatabaseCloudKitDatabaseIdentifierBlock databaseIdentifierBlock; + + NSString *versionTag; + id versionInfo; + + YapDatabaseCloudKitOptions *options; + + YDBCKChangeQueue *masterQueue; +} + +- (NSString *)mappingTableName; +- (NSString *)recordTableName; +- (NSString *)queueTableName; + +- (void)asyncMaybeDispatchNextOperation:(BOOL)forceNotification; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseCloudKitConnection () { +@protected + + id sharedKeySetForInternalChangeset; + +@public + + __strong YapDatabaseCloudKit *parent; + __unsafe_unretained YapDatabaseConnection *databaseConnection; + + YapCache *cleanMappingTableInfoCache; + YapCache *cleanRecordTableInfoCache; + + NSMutableDictionary *dirtyMappingTableInfoDict; + NSMutableDictionary *dirtyRecordTableInfoDict; + + YapCache *recordKeysCache; + + BOOL reset; + BOOL isOperationCompletionTransaction; + BOOL isOperationPartialCompletionTransaction; + + NSMutableDictionary *pendingAttachRequests; + + NSMutableSet *changeset_deletedRowids; + NSMutableSet *changeset_deletedHashes; + NSMutableDictionary *changeset_mappingTableInfo; + NSMutableDictionary *changeset_recordTableInfo; +} + +- (id)initWithParent:(YapDatabaseCloudKit *)inCloudKit databaseConnection:(YapDatabaseConnection *)inDbC; + +- (void)postCommitCleanup; +- (void)postRollbackCleanup; + +- (sqlite3_stmt *)mappingTable_insertStatement; +- (sqlite3_stmt *)mappingTable_updateForRowidStatement; +- (sqlite3_stmt *)mappingTable_getInfoForRowidStatement; +- (sqlite3_stmt *)mappingTable_enumerateForHashStatement; +- (sqlite3_stmt *)mappingTable_removeForRowidStatement; +- (sqlite3_stmt *)mappingTable_removeAllStatement; + +- (sqlite3_stmt *)recordTable_insertStatement; +- (sqlite3_stmt *)recordTable_updateOwnerCountStatement; +- (sqlite3_stmt *)recordTable_updateMetadataStatement; +- (sqlite3_stmt *)recordTable_updateRecordStatement; +- (sqlite3_stmt *)recordTable_getInfoForHashStatement; +- (sqlite3_stmt *)recordTable_getOwnerCountForHashStatement; +- (sqlite3_stmt *)recordTable_getCountForHashStatement; +- (sqlite3_stmt *)recordTable_enumerateStatement; +- (sqlite3_stmt *)recordTable_removeForHashStatement; +- (sqlite3_stmt *)recordTable_removeAllStatement; + +- (sqlite3_stmt *)queueTable_insertStatement; +- (sqlite3_stmt *)queueTable_updateDeletedRecordIDsStatement; +- (sqlite3_stmt *)queueTable_updateModifiedRecordsStatement; +- (sqlite3_stmt *)queueTable_updateBothStatement; +- (sqlite3_stmt *)queueTable_removeForUuidStatement; +- (sqlite3_stmt *)queueTable_removeAllStatement; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseCloudKitTransaction () { +@protected + + __unsafe_unretained YapDatabaseCloudKitConnection *parentConnection; + __unsafe_unretained YapDatabaseReadTransaction *databaseTransaction; +} + +- (id)initWithParentConnection:(YapDatabaseCloudKitConnection *)parentConnection + databaseTransaction:(YapDatabaseReadTransaction *)databaseTransaction; + +- (void)handlePartiallyCompletedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)savedRecords + deletedRecordIDs:(NSArray *)deletedRecordIDs; + +- (void)handleCompletedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)savedRecords + deletedRecordIDs:(NSArray *)deletedRecordIDs; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This class represents a row in the queue table. + * Every row contains the following columns: + * + * - uuid : The unique primary key + * - prev : The previous row, representing the commit prior to this one (reverse linked-list style) + * + * - databaseIdentifier : The databaseIdentifier for all deleted CKRecordIDs & modified CKRecords + * + * - deletedRecordIDs : Array of CKRecordID's + * - modifiedRecords : Array of YDBCKChangeRecord's (storing either a CKRecord or just changedKeys array) +**/ +@interface YDBCKChangeSet () { +@public + + NSMutableArray *deletedRecordIDs; + +#if DEBUG + YapDebugDictionary *modifiedRecords; +#else + NSMutableDictionary *modifiedRecords; +#endif +} + +- (instancetype)initWithUUID:(NSString *)uuid + prev:(NSString *)prev + databaseIdentifier:(NSString *)databaseIdentifier + deletedRecordIDs:(NSData *)serializedRecordIDs + modifiedRecords:(NSData *)serializedModifiedRecords; + +- (instancetype)initWithDatabaseIdentifier:(NSString *)databaseIdentifier; + +- (instancetype)emptyCopy; +- (instancetype)fullCopy; + +// Inherited: +// +// @property (atomic, readonly) BOOL isInFlight; +// +// @property (nonatomic, readonly) NSString *databaseIdentifier; +// +// @property (nonatomic, readonly) NSArray *recordIDsToDelete; // Array of CKRecordID's for CKModifyRecordsOperation +// @property (nonatomic, readonly) NSArray *recordsToSave; // Array of CKRecord's for CKModifyRecordsOperation + +@property (atomic, readwrite) BOOL isInFlight; + +@property (nonatomic, strong, readwrite) NSString *uuid; +@property (nonatomic, strong, readwrite) NSString *prev; + +@property (nonatomic, readonly) NSArray *recordsToSave_noCopy; + +@property (nonatomic, readwrite) BOOL hasChangesToDeletedRecordIDs; +@property (nonatomic, readwrite) BOOL hasChangesToModifiedRecords; + +// Blob to go in 'deletedRecordIDs' column of database row. +- (NSData *)serializeDeletedRecordIDs; + +// Blob to go in 'modifiedRecords' column of database row. +- (NSData *)serializeModifiedRecords; + +- (void)enumerateMissingRecordsWithBlock:(CKRecord* (^)(CKRecordID *recordID, NSArray *changedKeys))block; + +@end + diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h new file mode 100644 index 0000000..dd48df3 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.h @@ -0,0 +1,29 @@ +#import + +/** + * A change-set represents the set of changes that will be given to a CKModifyRecordsOperation. + * + * A change-set is automatically generated by a readWriteTransaction + * that makes one or more changes that result in modifications that need to be pushed to the CloudKit server. + * + * Changes are grouped by databaseIdentifier. + * So if a single readWriteTransaction makes several modifications that span multiple databaseIdentifiers, + * then the transaction will result in multiple generated change-sets. + * + * You are free to inspect the change-set, however, it is not possible to modify it. +**/ +@interface YDBCKChangeSet : NSObject + +@property (nonatomic, readonly) NSString *databaseIdentifier; +@property (nonatomic, readonly) NSString *uuid; + +@property (nonatomic, readonly) BOOL isInFlight; + +@property (nonatomic, readonly) NSArray *recordIDsToDelete; // Array of CKRecordID's for CKModifyRecordsOperation +@property (nonatomic, readonly) NSArray *recordsToSave; // Array of CKRecord's for CKModifyRecordsOperation +@property (nonatomic, readonly) NSArray *recordIDsToSave; // Array of CKRecordID's (from recordsToSave) + +@property (nonatomic, readonly) NSUInteger recordIDsToDeleteCount; // shortcut if you just want the count +@property (nonatomic, readonly) NSUInteger recordsToSaveCount; // shortcut if you just want the count + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.m new file mode 100644 index 0000000..d4c0ca7 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKChangeSet.m @@ -0,0 +1,241 @@ +#import "YDBCKChangeSet.h" +#import "YDBCKChangeRecord.h" +#import "YDBCKRecord.h" +#import "YapDatabaseCloudKitPrivate.h" +#if DEBUG +#import "YapDebugDictionary.h" +#endif + + +@implementation YDBCKChangeSet + +@synthesize uuid = uuid; +@synthesize prev = prev; + +@synthesize databaseIdentifier = databaseIdentifier; +@synthesize isInFlight = isInFlight; + +@dynamic recordIDsToDelete; +@dynamic recordsToSave; +@dynamic recordsToSave_noCopy; + +@dynamic recordIDsToDeleteCount; +@dynamic recordsToSaveCount; + +@synthesize hasChangesToDeletedRecordIDs; +@synthesize hasChangesToModifiedRecords; + +- (id)initWithUUID:(NSString *)inUuid + prev:(NSString *)inPrev +databaseIdentifier:(NSString *)inDatabaseIdentifier + deletedRecordIDs:(NSData *)serializedDeletedRecordIDs + modifiedRecords:(NSData *)serializedModifiedRecords +{ + if ((self = [super init])) + { + uuid = inUuid; + prev = inPrev; + + databaseIdentifier = inDatabaseIdentifier; + isInFlight = NO; + + [self deserializeDeletedRecordIDs:serializedDeletedRecordIDs]; + [self deserializeModifiedRecords:serializedModifiedRecords]; + } + return self; +} + +- (instancetype)initWithDatabaseIdentifier:(NSString *)inDatabaseIdentifier +{ + if ((self = [super init])) + { + databaseIdentifier = inDatabaseIdentifier; + isInFlight = NO; + + uuid = nil; // Will be set later when the changeSets are ordered + prev = nil; // Will be set later when the changeSets are ordered + } + return self; +} + +- (instancetype)emptyCopy +{ + YDBCKChangeSet *emptyCopy = [[YDBCKChangeSet alloc] init]; + emptyCopy->uuid = uuid; + emptyCopy->prev = prev; + emptyCopy->databaseIdentifier = databaseIdentifier; + emptyCopy->isInFlight = isInFlight; + + return emptyCopy; +} + +- (instancetype)fullCopy +{ + YDBCKChangeSet *fullCopy = [self emptyCopy]; + + if (deletedRecordIDs) + { + fullCopy->deletedRecordIDs = [deletedRecordIDs mutableCopy]; + } + + if (modifiedRecords) + { + #if DEBUG + fullCopy->modifiedRecords = [[YapDebugDictionary alloc] initWithDictionary:modifiedRecords copyItems:YES]; + #else + fullCopy->modifiedRecords = [[NSMutableDictionary alloc] initWithDictionary:modifiedRecords copyItems:YES]; + #endif + } + + return fullCopy; +} + +/** + * Array of CKRecordID's for CKModifyRecordsOperation +**/ +- (NSArray *)recordIDsToDelete +{ + return [deletedRecordIDs copy]; +} + +/** + * Array of CKRecord's for CKModifyRecordsOperation. +**/ +- (NSArray *)recordsToSave +{ + NSUInteger modifiedRecordsCount = modifiedRecords.count; + if (modifiedRecordsCount == 0) return nil; + + NSMutableArray *array = [NSMutableArray arrayWithCapacity:modifiedRecordsCount]; + + for (YDBCKChangeRecord *changeRecord in [modifiedRecords objectEnumerator]) + { + [array addObject:[changeRecord.record safeCopy]]; + } + + return array; +} + +/** + * Private API for YapDatabaseCloudKit extension internals only. + * NOT for external use under any circumstances !!! +**/ +- (NSArray *)recordsToSave_noCopy +{ + if (modifiedRecords.count == 0) return nil; + + NSMutableArray *array = [NSMutableArray arrayWithCapacity:[modifiedRecords count]]; + + for (YDBCKChangeRecord *changeRecord in [modifiedRecords objectEnumerator]) + { + [array addObject:changeRecord.record]; + } + + return array; +} + +/** + * Array of CKRecordID's (from recordsToSave). +**/ +- (NSArray *)recordIDsToSave +{ + NSUInteger modifiedRecordsCount = modifiedRecords.count; + if (modifiedRecordsCount == 0) return 0; + + NSMutableArray *array = [NSMutableArray arrayWithCapacity:modifiedRecordsCount]; + + for (YDBCKChangeRecord *changeRecord in [modifiedRecords objectEnumerator]) + { + [array addObject:changeRecord.recordID]; + } + + return array; +} + +/** + * Shortcut if you just want the count (for CKModifyRecordsOperation.recordIDsToDelete). +**/ +- (NSUInteger)recordIDsToDeleteCount +{ + return deletedRecordIDs.count; +} + +/** + * Shortcut if you just want the count (for CKModifyRecordsOperation.recordsToSave). +**/ +- (NSUInteger)recordsToSaveCount +{ + return modifiedRecords.count; +} + +- (NSData *)serializeDeletedRecordIDs +{ + if ([deletedRecordIDs count] > 0) + return [NSKeyedArchiver archivedDataWithRootObject:deletedRecordIDs]; + else + return nil; +} + +- (void)deserializeDeletedRecordIDs:(NSData *)serializedDeletedRecordIDs +{ + if (serializedDeletedRecordIDs) + deletedRecordIDs = [NSKeyedUnarchiver unarchiveObjectWithData:serializedDeletedRecordIDs]; + else + deletedRecordIDs = nil; + + if (deletedRecordIDs) { + NSAssert([deletedRecordIDs isKindOfClass:[NSMutableArray class]], @"Deserialized object is wrong class"); + } +} + +- (NSData *)serializeModifiedRecords +{ + if (modifiedRecords.count == 0) + return nil; + else + return [NSKeyedArchiver archivedDataWithRootObject:[modifiedRecords allValues]]; +} + +- (void)deserializeModifiedRecords:(NSData *)serializedModifiedRecords +{ + NSArray *modifiedRecordsArray = nil; + + if (serializedModifiedRecords) { + modifiedRecordsArray = [NSKeyedUnarchiver unarchiveObjectWithData:serializedModifiedRecords]; + } + + if (modifiedRecordsArray) { + NSAssert([modifiedRecordsArray isKindOfClass:[NSArray class]], @"Deserialized object is wrong class"); + } + +#if DEBUG + modifiedRecords = [[YapDebugDictionary alloc] initWithKeyClass:[CKRecordID class] + objectClass:[YDBCKChangeRecord class] + capacity:[modifiedRecordsArray count]]; +#else + modifiedRecords = [[NSMutableDictionary alloc] initWithCapacity:[modifiedRecordsArray count]]; +#endif + + for (YDBCKChangeRecord *changeRecord in modifiedRecordsArray) + { + CKRecordID *recordID = changeRecord.recordID; + if (recordID) { + [modifiedRecords setObject:changeRecord forKey:recordID]; + } + } +} + +- (void)enumerateMissingRecordsWithBlock:(CKRecord* (^)(CKRecordID *recordID, NSArray *changedKeys))block +{ + for (YDBCKChangeRecord *changeRecord in [modifiedRecords objectEnumerator]) + { + if (changeRecord.record == nil) + { + CKRecord *record = block(changeRecord.recordID, changeRecord.changedKeys); + + changeRecord.record = record; + } + } +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h new file mode 100644 index 0000000..14e3190 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.h @@ -0,0 +1,68 @@ +#import +#import + + +/** + * This utility class is used by the YapDatabaseCloudKitMergeBlock. +**/ +@interface YDBCKMergeInfo : NSObject + +/** + * Apple's CloudKit framework does NOT tell us which properties of a CKRecord were remotely changed. + * That is, when we fetch CKRecords that have been changed by a different device, we are only given: + * + * - The CKRecord that was changed + * - The most recent key/value pairs for the CKRecord (all key value pairs, even those that didn't change) + * + * This becomes problematic when we are tasked with performing a merge. + * For example: + * + * - We change contact.firstName property + * - We attempt to upload the corresponding CKRecord + * - CloudKit gives us an error - record is out-of-date (changed remotely) + * - We then pull down the latest version of the CKRecord + * - And we are now tasked with merging this version with our version + * + * The big question is: Did the remote device change the firstName property ??? + * + * Unfortunately, this is not possible to answer this question with only the following information: + * - The latest version of the CKRecord from the server + * - The latest version of the CKRecord locally (pending upload) + * - The list of properties that were changed locally (pending upload) + * + * There is one critical piece of information that is missing: + * - The original values for the properties that were changed locally + * + * With this critical piece of information in hand, we can: + * - Enumerate the key/value pairs of the CKRecord from the server + * - Compare each value with our own local value + * - If they match, then we don't have any problems + * - If they don't match, and we didn't change the value locally, then we can simply accept the new value from remote + * - If they don't match, and we did change the value locally: + * - If the remote value matches our original value, + * then the remote device didn't change the value, and we can keep our local change. + * - If the remote value doesn't match our original value, + * then we have a conflict, and we'll need to choose which value to keep. (generally remote wins) + * + * So how do we go about storing the originalValues ? + * YapDatabaseCloudKit will store it for you if you provide the info via the recordBlock. + * That is, the recordBlock has a YDBCKRecordInfo parameter. + * And YDBCKRecordInfo has an originalValues property that you can set. + * If you set this, then YapDatabaseCloudKit will handle everything else for you. + * + * See MyDatabaseObject for an example of how you might use KVO to track originalValue(s). + * See CloudKitTodo sample project for a complete Xcode project example. +**/ +@property (nonatomic, strong, readonly) NSDictionary *originalValues; + +/** + * +**/ +@property (nonatomic, strong, readonly) CKRecord *pendingLocalRecord; + +/** + * +**/ +@property (nonatomic, strong, readonly) CKRecord *updatedPendingLocalRecord; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.m new file mode 100644 index 0000000..2eff5c9 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKMergeInfo.m @@ -0,0 +1,65 @@ +#import "YDBCKMergeInfo.h" +#import "YapDatabaseCloudKitPrivate.h" + + +@implementation YDBCKMergeInfo +{ + NSMutableDictionary *originalValues; +} + +// See header file for documentation + +@dynamic originalValues; + +@synthesize pendingLocalRecord = pendingLocalRecord; +@synthesize updatedPendingLocalRecord = updatedPendingLocalRecord; + +- (NSDictionary *)originalValues +{ + return originalValues; +} + +// Private API + +- (void)mergeNewerRecord:(CKRecord *)newerRecord newerOriginalValues:(NSDictionary *)newerOriginalValues +{ + // Merge into pendingLocalRecord + // + // Note: For pendingLocalRecord, the most recent value wins. + + if (newerRecord) + { + for (NSString *changedKey in newerRecord.changedKeys) + { + // Remember: nil is a valid value. + // It indicates removal of the value for the key, which is a valid action. + + id value = [newerRecord objectForKey:changedKey]; + [pendingLocalRecord setObject:value forKey:changedKey]; + } + } + + // Merge into originalValues + // + // Note: For originalValues, the least recent value wins. + + if (newerOriginalValues) + { + if (originalValues == nil) + { + originalValues = [newerOriginalValues mutableCopy]; + } + else + { + [newerOriginalValues enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + if ([originalValues objectForKey:key] == nil) + { + [originalValues setObject:obj forKey:key]; + } + }]; + } + } +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h new file mode 100644 index 0000000..0d9f12b --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.h @@ -0,0 +1,49 @@ +#import +#import + + +@interface CKRecord (YapDatabaseCloudKit) + +/** + * Returns a "sanitized" copy of the given record. + * That is, a copy that ONLY includes the "system fields" of the record. + * It will NOT contain any key/value pairs from the original record. +**/ +- (id)sanitizedCopy; + +/** + * Calling [ckRecord copy] is COMPLETELY BROKEN. + * This is a MAJOR BUG in Apple's CloudKit framework (as I see it). + * + * Until this is fixed, we're forced to use this workaround. +**/ +- (id)safeCopy; + +@end + +#pragma mark - + +@interface YDBCKRecord : NSObject + +/** + * This method serializes just the "system fields" of the given record. + * That is, it won't store any of the user-created key/value pairs. + * It only stores the CloudKit specific stuff, such as the versioning info, syncing info, etc. +**/ ++ (NSData *)serializeRecord:(CKRecord *)record; + +/** + * Deserialize the given record data. + * + * If the record data came from [YDBCKRecord serializeRecord:], + * then the returned record will only contain the "system fields". +**/ ++ (CKRecord *)deserializeRecord:(NSData *)data; + +#pragma mark Instance + +- (instancetype)initWithRecord:(CKRecord *)record; + +@property (nonatomic, strong, readonly) CKRecord *record; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.m new file mode 100644 index 0000000..30b7ab8 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecord.m @@ -0,0 +1,153 @@ +#import "YDBCKRecord.h" + +@implementation CKRecord (YapDatabaseCloudKit) + +/** + * Returns a "sanitized" copy of the given record. + * That is, a copy that ONLY includes the "system fields" of the record. + * It will NOT contain any key/value pairs from the original record. +**/ +- (id)sanitizedCopy +{ + // This is the ONLY way in which I know how to accomplish this task. + // + // Other techniques, such as making a copy and removing all the values, + // ends up giving us a record with a bunch of changedKeys. Not what we want. + + return [YDBCKRecord deserializeRecord:[YDBCKRecord serializeRecord:self]]; +} + +/** + * Calling [ckRecord copy] is COMPLETELY BROKEN. + * This is a MAJOR BUG in Apple's CloudKit framework (as I see it). + * + * Until this is fixed, we're forced to use this workaround. +**/ +- (id)safeCopy +{ + NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:self]; + return [NSKeyedUnarchiver unarchiveObjectWithData:archive]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation YDBCKRecord + +/** + * This method serializes just the "system fields" of the given record. + * That is, it won't store any of the user-created key/value pairs. + * It only stores the CloudKit specific stuff, such as the versioning info, syncing info, etc. +**/ ++ (NSData *)serializeRecord:(CKRecord *)record +{ + if (record == nil) return nil; + + YDBCKRecord *recordWrapper = [[YDBCKRecord alloc] initWithRecord:record]; + return [NSKeyedArchiver archivedDataWithRootObject:recordWrapper]; +} + +/** + * Deserialized the given record data. + * + * If the record data came from [YDBCKRecord serializeRecord:], + * then the returned record will only contain the "system fields". +**/ ++ (CKRecord *)deserializeRecord:(NSData *)data +{ + if (data) + return [NSKeyedUnarchiver unarchiveObjectWithData:data]; + else + return nil; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark YDBCKRecord Class +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@synthesize record = record; + +- (instancetype)initWithRecord:(CKRecord *)inRecord +{ + if ((self = [super init])) + { + record = inRecord; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)decoder +{ + return nil; // This shouldn't happen, as obj will be decoded as a straight CKRecord object. +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [record encodeSystemFieldsWithCoder:coder]; +} + +/** + * When this object is decoded, it should decode it as a straight CKRecord object. +**/ +- (Class)classForKeyedArchiver +{ + return [CKRecord class]; +} + +/** + * I think this method is largely replaced by classForKeyedArchiver. + * But it may be used by other 'coders', so it's included just in case. +**/ +- (Class)classForCoder +{ + return [CKRecord class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//#pragma mark YDBCKRecord_KeyedUnarchiver +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// +// This technique can be used to clear the changedKeys property of a CKRecord. +// +/* +@interface YDBCKRecord_KeyedUnarchiver : NSKeyedUnarchiver +@end + +@implementation YDBCKRecord_KeyedUnarchiver + ++ (id)unarchiveObjectWithData:(NSData *)data +{ + YDBCKRecord_KeyedUnarchiver *unarchiver = [[YDBCKRecord_KeyedUnarchiver alloc] initForReadingWithData:data]; + + id obj = [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey]; + [unarchiver finishDecoding]; + + return obj; +} + +- (id)decodeObjectForKey:(NSString *)key +{ +// NSLog(@"decodeObjectForKey: %@", key); + + if ([key isEqualToString:@"ChangedKeys"]) + { + // At the time of this writing, + // CKRecord.changedKeys is a NSMutableSet. + + id obj = [super decodeObjectForKey:key]; + return [[[obj class] alloc] init]; + } + else + { + return [super decodeObjectForKey:key]; + } +} + +@end +*/ diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h new file mode 100644 index 0000000..9a6116c --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.h @@ -0,0 +1,88 @@ +#import + + +/** + * This utility class is used by the YapDatabaseCloudKitRecordBlock. + * It provides metadata about the CKRecord. + * + * There are only 4 properties, which can be broken up into 2 sections: + * + * - Properties you can optionally SET (within the recordBlock): + * + * - databaseIdentifier + * - originalValues + * + * - Properties you need to CHECK (within the recordBlock): + * + * - keysToRestore + * - versionInfo +**/ +@interface YDBCKRecordInfo : NSObject + +/** + * This property allows you to specify the associated CKDatabase for the record. + * + * In order for YapDatabaseCloudKit to be able to upload the CKRecord to the cloud, + * it must know which CKDatabase the record is associated with. + * + * If unspecified, the private database of the app’s default container is used. + * That is: [[CKContainer defaultContainer] privateCloudDatabase] + * + * If you want to use a different CKDatabase, + * then you need to set recordInfo.databaseIdentifier within your recordBlock. + * + * Important: + * If you specify a databaseIdentifier here, + * then you MUST also configure the YapDatabaseCloudKit instance with a databaseIdentifier block. + * Failure to do so will result in an exception. +**/ +@property (nonatomic, copy, readwrite) NSString *databaseIdentifier; + +/** + * If you make changes to the CKRecord, you can optionally choose to store the original key/value pairs. + * That is, the original key/value pairs for the key(s) that were changed. + * + * This dictionary will be stored alongside the modified CKRecord within the queue. + * And will be made available during merge operations via YDBCKMergeInfo.originalValues. +**/ +@property (nonatomic, strong, readwrite) NSDictionary *originalValues; + +/** + * When this property is non-nil, the recordHandler MUST restore the specified keys. + * + * YapDatabaseCloudKit uses various storage optimization techniques to reduce disk IO, + * and reduce the amount of duplicate data that gets stored in the database. + * Essentially it skips storing any values that are already stored within the original database object(s). + * And so, if the application quits before all uploads have made it to the CloudKit server, + * then YapDatabaseCloudKit will need to restore some CKRecords, and may need to restore certain values. + * + * You MUST check for this property within your recordHandler implementation. +**/ +@property (nonatomic, strong, readonly) NSArray *keysToRestore; + +/** + * This property comes directly from the [YapDatabaseCloudKit init...] method. + * + * As your application evolves, there may be times that you need to change the CKRecord format. + * And there are a couple ways in which you can achieve this. + * + * 1. Simply wait until the corresponding object(s) are naturally updated, + * and then push the new fields to the cloud at that time. + * 2. Push all the updated fields for all the objects right away. + * + * The versionInfo is useful in achieving option #2. + * Here's how it works: + * + * You initialize YapDatabaseCloudKit with an bumped/incremented/changed versionTag, + * and you also supply versionInfo that relays information you can use within the recordHandler. + * + * When YapDatabaseCloudKit is initialized for the first time (first launch, not subsequent launch), + * or its versionTag is changed, it will enumerate the objects in the database and invoke the recordHandler. + * During this enumeration (and only this enumeration) the recordHandler will be passed the versionInfo + * from the init method. Thus the recordHandler can discern between the initial population/repopulation, + * and a normal user-initiated readWriteTransaction that's modifying an object in the database. + * And it can then use the versionInfo to create the proper CKRecord. +**/ +@property (nonatomic, strong, readonly) id versionInfo; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.m new file mode 100644 index 0000000..9749a2e --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/Utilities/YDBCKRecordInfo.m @@ -0,0 +1,13 @@ +#import "YDBCKRecordInfo.h" +#import "YapDatabaseCloudKitPrivate.h" + + +@implementation YDBCKRecordInfo + +@synthesize databaseIdentifier; +@synthesize originalValues; + +@synthesize keysToRestore; +@synthesize versionInfo; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h new file mode 100644 index 0000000..40dcccb --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.h @@ -0,0 +1,199 @@ +#import +#import + +#import "YapDatabaseExtension.h" +#import "YapDatabaseCloudKitTypes.h" +#import "YapDatabaseCloudKitOptions.h" +#import "YapDatabaseCloudKitConnection.h" +#import "YapDatabaseCloudKitTransaction.h" + +#import "YDBCKChangeSet.h" + +extern NSString *const YapDatabaseCloudKitSuspendCountChangedNotification; +extern NSString *const YapDatabaseCloudKitInFlightChangeSetChangedNotification; + +/** + * Welcome to YapDatabase! + * + * https://github.com/yapstudios/YapDatabase + * + * The project wiki has a wealth of documentation if you have any questions. + * https://github.com/yapstudios/YapDatabase/wiki + * + * YapDatabaseCloudKit is an extension that allows you to sync + * objects in YapDatabase with Apple's CloudKit service. + * + * For the full documentation on Views, please see the related wiki article: + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseCloudKit +**/ +@interface YapDatabaseCloudKit : YapDatabaseExtension + + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)mergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)opErrorBlock; + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)mergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)opErrorBlock + versionTag:(NSString *)versionTag + versionInfo:(id)versionInfo; + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)mergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)opErrorBlock + versionTag:(NSString *)versionTag + versionInfo:(id)versionInfo + options:(YapDatabaseCloudKitOptions *)options; + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)mergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)opErrorBlock + databaseIdentifierBlock:(YapDatabaseCloudKitDatabaseIdentifierBlock)databaseIdentifierBlock + versionTag:(NSString *)versionTag + versionInfo:(id)versionInfo + options:(YapDatabaseCloudKitOptions *)options; + +@property (nonatomic, strong, readonly) YapDatabaseCloudKitRecordBlock recordBlock; +@property (nonatomic, assign, readonly) YapDatabaseCloudKitBlockType recordBlockType; + +@property (nonatomic, strong, readonly) YapDatabaseCloudKitMergeBlock mergeBlock; +@property (nonatomic, strong, readonly) YapDatabaseCloudKitOperationErrorBlock operationErrorBlock; + +@property (nonatomic, copy, readonly) NSString *versionTag; + +@property (nonatomic, copy, readonly) YapDatabaseCloudKitOptions *options; + +#pragma mark Suspend & Resume + +/** + * Returns YES if the upload operation queue is suspended. + * + * @see suspend + * @see resume +**/ +@property (atomic, readonly) BOOL isSuspended; + +/** + * Returns the current suspendCount. + * If the suspendCount is zero, that means isSuspended == NO; + * if the suspendCount is non-zero, that means isSuspended == YES; + * + * @see suspend + * @see resume +**/ +@property (atomic, readonly) NSUInteger suspendCount; + +/** + * Before the CloudKit stack can begin pushing changes to the cloud, there are generally several steps that + * must be taken first. These include general configuration steps, as well as querying the server to + * pull down changes from other devices that occurred while the app was offline. + * + * Some example steps that may need to be performed prior to taking the extension "online": + * - registering for push notifications + * - creating the needed CKRecordZone's (if needed) + * - creating the zone subscriptions (if needed) + * - pulling changes via CKFetchRecordChangesOperation + * + * It's important that all these tasks get completed before the YapDatabaseCloudKit extension begins attempting + * to push data to the cloud. For example, if the proper CKRecordZone's haven't been created yet, then attempting + * to insert objects into those missing zones will fail. And if, after after being offline, we begin pushing our + * changes to the server before we pull others' changes, then we'll likely just get a bunch of failures & conflicts. + * Not to mention waste a lot of bandwidth in the process. + * + * For this reason, there is a flexible mechanism to "suspend" the upload process. + * + * That is, if YapDatabaseCloudKit is "suspended", it still remains fully functional. + * That is, it's still "listening" for changes in the database, and invoking the recordHandler block to track + * changes to CKRecord's, etc. However, while suspended, it operates in a slightly different mode, wherein it + * it only QUEUES its CKModifyRecords operations. (It suspends its internal master operationQueue.) And where it + * may dynamically modify its pending queue in response to merges and continued changes to the database. + * + * You MUST match every call to suspend with a matching call to resume. + * For example, if you invoke suspend 3 times, then the extension won't resume until you've invoked resume 3 times. + * + * Use this to your advantage if you have multiple tasks to complete before you want to resume the extension. + * From the example above, one would create and register the extension as usual when setting up YapDatabase + * and all the normal extensions needed by the app. However, they would invoke the suspend method 3 times before + * registering the extension with the database. And then, as each of the 3 required steps complete, they would + * invoke the resume method. Therefore, the extension will be available immediately to start monitoring for changes + * in the database. However, it won't start pushing any changes to the cloud until the 3 required step + * have all completed. + * + * @return + * The current suspend count. + * This will be 1 if the extension was previously active, and is now suspended due to this call. + * Otherwise it will be greater than one, meaning it was previously suspended, + * and you just incremented the suspend count. +**/ +- (NSUInteger)suspend; + +/** + * This method operates the same as invoking the suspend method the given number of times. + * That is, it increments the suspend count by the given number. + * + * You can invoke this method with a zero parameter in order to obtain the current suspend count, without modifying it. + * + * @see suspend +**/ +- (NSUInteger)suspendWithCount:(NSUInteger)suspendCountIncrement; + +/** + * See the suspend method for a description of the suspend/resume architecture. + * + * @return + * The current suspend count. + * This will be 0 if the extension was previously suspended, and is now resumed due to this call. + * Otherwise it will be greater than one, meaning it's still suspended, + * and you just decremented the suspend count. +**/ +- (NSUInteger)resume; + +#pragma mark Change-Sets + +/** + * Returns an array of YDBCKChangeSet objects, which represent the pending (and in-flight) change-sets. + * The array is ordered, such that: + * - the first item in the array is either in-flight or the next to be uploaded + * - the last item in the array represents the most recent change-set + * + * From this array you'll be able to see exactly what YapDatabaseCloudKit is uploading (or intends to upload). + * + * This is also useful if you want to perform a "dry run" test. + * You can simply run a few tests with a debug database, + * and keep the YapDatabaseCloudKit extension suspended the whole time. + * Then just inspect the change-sets to ensure that everything is working as you expect. +**/ +- (NSArray *)pendingChangeSets; + +/** + * Faster access if you just want to get the counts. + * + * - numberOfInFlightChangeSets: + * YDBCKChangeSets that have been dispatched to CloudKit Framework. + * These may or may not succeed, depending upon network conditions & other factors. + * + * - numberOfQueuedChangeSets: + * YDBCKChangeSets that have not been dispatched to CloudKit Framework. + * They are waiting for the current inFlight change-sets to succeed, or for YDBCK to be resumed. + * + * - numberOfPendingChangeSets: + * Includes all YDBCKChangeSets, both inFlight & queued. + * + * In mathematical notion, the relationships are: + * + * numberOfInFlightChangeSets == numberOfPendingChangeSets - numberOfQueuedChangeSets + * numberOfQueuedChangeSets == numberOfPendingChangeSets - numberOfInFlightChangeSets + * numberOfPendingChangeSets == numberOfInFlightChangeSets + numberOfQueuedChangeSets +**/ +@property (atomic, readonly) NSUInteger numberOfInFlightChangeSets; +@property (atomic, readonly) NSUInteger numberOfQueuedChangeSets; +@property (atomic, readonly) NSUInteger numberOfPendingChangeSets; + +/** + * Atomic access to all counts at once. +**/ +- (void)getNumberOfInFlightChangeSets:(NSUInteger *)numInFlightChangeSetsPtr + queuedChangeSets:(NSUInteger *)numQueuedChangeSetsPtr; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.m new file mode 100644 index 0000000..d4accdd --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKit.m @@ -0,0 +1,786 @@ +#import "YapDatabaseCloudKitPrivate.h" +#import "YapDatabasePrivate.h" +#import "YapDatabaseLogging.h" + +#import + +/** + * Define log level for this file: OFF, ERROR, WARN, INFO, VERBOSE + * See YapDatabaseLogging.h for more information. +**/ +#if DEBUG + static const int ydbLogLevel = YDB_LOG_LEVEL_VERBOSE | YDB_LOG_FLAG_TRACE; +#else + static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; +#endif +#pragma unused(ydbLogLevel) + +NSString *const YapDatabaseCloudKitSuspendCountChangedNotification = @"YDBCK_SuspendCountChanged"; +NSString *const YapDatabaseCloudKitInFlightChangeSetChangedNotification = @"YDBCK_InFlightChangeSetChanged"; + +@implementation YapDatabaseCloudKit +{ + NSUInteger suspendCount; + OSSpinLock suspendCountLock; + + NSOperationQueue *masterOperationQueue; + + YapDatabaseConnection *completionDatabaseConnection; + YapCache *databaseCache; +} + +/** + * Subclasses MUST implement this method. + * + * This method is used when unregistering an extension in order to drop the related tables. + * + * @param registeredName + * The name the extension was registered using. + * The extension should be able to generated the proper table name(s) using the given registered name. + * + * @param transaction + * A readWrite transaction for proper database access. + * + * @param wasPersistent + * If YES, then the extension should drop tables from sqlite. + * If NO, then the extension should unregister the proper YapMemoryTable(s). +**/ ++ (void)dropTablesForRegisteredName:(NSString *)registeredName + withTransaction:(YapDatabaseReadWriteTransaction *)transaction + wasPersistent:(BOOL)wasPersistent +{ + sqlite3 *db = transaction->connection->db; + + NSArray *tableNames = @[ + [self mappingTableNameForRegisteredName:registeredName], + [self recordTableNameForRegisteredName:registeredName], + [self recordTableNameForRegisteredName:registeredName] + ]; + + for (NSString *tableName in tableNames) + { + NSString *dropTable = [NSString stringWithFormat:@"DROP TABLE IF EXISTS \"%@\";", tableName]; + + int status = sqlite3_exec(db, [dropTable UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ - Failed dropping table (%@): %d %s", + THIS_METHOD, tableName, status, sqlite3_errmsg(db)); + } + } +} + ++ (NSString *)mappingTableNameForRegisteredName:(NSString *)registeredName +{ + return [NSString stringWithFormat:@"cloudKit_mapping_%@", registeredName]; +} + ++ (NSString *)recordTableNameForRegisteredName:(NSString *)registeredName +{ + return [NSString stringWithFormat:@"cloudKit_record_%@", registeredName]; +} + ++ (NSString *)queueTableNameForRegisteredName:(NSString *)registeredName +{ + return [NSString stringWithFormat:@"cloudKit_queue_%@", registeredName]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Init +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@synthesize recordBlock = recordBlock; +@synthesize recordBlockType = recordBlockType; + +@synthesize mergeBlock = mergeBlock; +@synthesize operationErrorBlock = opErrorBlock; + +@synthesize versionTag = versionTag; + +@dynamic options; +@dynamic isSuspended; + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)inMergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)inOpErrorBlock +{ + return [self initWithRecordHandler:recordHandler + mergeBlock:inMergeBlock + operationErrorBlock:inOpErrorBlock + databaseIdentifierBlock:NULL + versionTag:nil + versionInfo:nil + options:nil]; +} + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)inMergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)inOpErrorBlock + versionTag:(NSString *)inVersionTag + versionInfo:(id)inVersionInfo +{ + return [self initWithRecordHandler:recordHandler + mergeBlock:inMergeBlock + operationErrorBlock:inOpErrorBlock + databaseIdentifierBlock:NULL + versionTag:inVersionTag + versionInfo:inVersionInfo + options:nil]; +} + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)inMergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)inOpErrorBlock + versionTag:(NSString *)inVersionTag + versionInfo:(id)inVersionInfo + options:(YapDatabaseCloudKitOptions *)inOptions +{ + return [self initWithRecordHandler:recordHandler + mergeBlock:inMergeBlock + operationErrorBlock:inOpErrorBlock + databaseIdentifierBlock:NULL + versionTag:inVersionTag + versionInfo:inVersionInfo + options:inOptions]; +} + +- (instancetype)initWithRecordHandler:(YapDatabaseCloudKitRecordHandler *)recordHandler + mergeBlock:(YapDatabaseCloudKitMergeBlock)inMergeBlock + operationErrorBlock:(YapDatabaseCloudKitOperationErrorBlock)inOpErrorBlock + databaseIdentifierBlock:(YapDatabaseCloudKitDatabaseIdentifierBlock)inDatabaseIdentifierBlock + versionTag:(NSString *)inVersionTag + versionInfo:(id)inVersionInfo + options:(YapDatabaseCloudKitOptions *)inOptions +{ + if ((self = [super init])) + { + recordBlock = recordHandler.recordBlock; + recordBlockType = recordHandler.recordBlockType; + + mergeBlock = inMergeBlock; + opErrorBlock = inOpErrorBlock; + databaseIdentifierBlock = inDatabaseIdentifierBlock; + + versionTag = inVersionTag ? [inVersionTag copy] : @""; + versionInfo = inVersionInfo; + + options = inOptions ? [inOptions copy] : [[YapDatabaseCloudKitOptions alloc] init]; + + masterQueue = [[YDBCKChangeQueue alloc] initMasterQueue]; + + masterOperationQueue = [[NSOperationQueue alloc] init]; + masterOperationQueue.maxConcurrentOperationCount = 1; + + suspendCountLock = OS_SPINLOCK_INIT; + } + return self; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Custom Properties +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (YapDatabaseCloudKitOptions *)options +{ + return [options copy]; // Our copy must remain immutable +} + +- (BOOL)isSuspended +{ + return ([self suspendCount] > 0); +} + +- (NSUInteger)suspendCount +{ + NSUInteger currentSuspendCount = 0; + + OSSpinLockLock(&suspendCountLock); + { + currentSuspendCount = suspendCount; + } + OSSpinLockUnlock(&suspendCountLock); + + return currentSuspendCount; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Suspend & Resume +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Before the CloudKit stack can begin pushing changes to the cloud, there are generally several steps that + * must be taken first. These include general configuration steps, as well as querying the server to + * pull down changes from other devices that occurred while the app was offline. + * + * Some example steps that may need to be performed prior to taking the extension "online": + * - registering for push notifications + * - creating the needed CKRecordZone's (if needed) + * - creating the zone subscriptions (if needed) + * - pulling changes via CKFetchRecordChangesOperation + * + * It's important that all these tasks get completed before the YapDatabaseCloudKit extension begins attempting + * to push data to the cloud. For example, if the proper CKRecordZone's haven't been created yet, then attempting + * to insert objects into those missing zones will fail. And if, after after being offline, we begin pushing our + * changes to the server before we pull others' changes, then we'll likely just get a bunch of failures & conflicts. + * Not to mention waste a lot of bandwidth in the process. + * + * For this reason, there is a flexible mechanism to "suspend" the upload process. + * + * That is, if YapDatabaseCloudKit is "suspended", it still remains fully functional. + * That is, it's still "listening" for changes in the database, and invoking the recordHandler block to track + * changes to CKRecord's, etc. However, while suspended, it operates in a slightly different mode, wherein it + * it only QUEUES its CKModifyRecords operations. (It suspends its internal master operationQueue.) And where it + * may dynamically modify its pending queue in response to merges and continued changes to the database. + * + * You MUST match every call to suspend with a matching call to resume. + * For example, if you invoke suspend 3 times, then the extension won't resume until you've invoked resume 3 times. + * + * Use this to your advantage if you have multiple tasks to complete before you want to resume the extension. + * From the example above, one would create and register the extension as usual when setting up YapDatabase + * and all the normal extensions needed by the app. However, they would invoke the suspend method 3 times before + * registering the extension with the database. And then, as each of the 3 required steps complete, they would + * invoke the resume method. Therefore, the extension will be available immediately to start monitoring for changes + * in the database. However, it won't start pushing any changes to the cloud until the 3 required step + * have all completed. + * + * @return + * The current suspend count. + * This will be 1 if the extension was previously active, and is now suspended due to this call. + * Otherwise it will be greater than one, meaning it was previously suspended, + * and you just incremented the suspend count. +**/ +- (NSUInteger)suspend +{ + return [self suspendWithCount:1]; +} + +/** + * This method operates the same as invoking the suspend method the given number of times. + * That is, it increments the suspend count by the given number. + * + * You can invoke this method with a zero parameter in order to obtain the current suspend count, without modifying it. + * + * @see suspend +**/ +- (NSUInteger)suspendWithCount:(NSUInteger)suspendCountIncrement +{ + BOOL overflow = NO; + NSUInteger oldSuspendCount = 0; + NSUInteger newSuspendCount = 0; + + OSSpinLockLock(&suspendCountLock); + { + oldSuspendCount = suspendCount; + + if (suspendCount <= (NSUIntegerMax - suspendCountIncrement)) + suspendCount += suspendCountIncrement; + else { + suspendCount = NSUIntegerMax; + overflow = YES; + } + + newSuspendCount = suspendCount; + } + OSSpinLockUnlock(&suspendCountLock); + + if (overflow) + { + YDBLogWarn(@"%@ - The suspendCount has reached NSUIntegerMax!", THIS_METHOD); + } + else if (suspendCountIncrement > 0) + { + YDBLogInfo(@"=> SUSPENDED : incremented suspendCount == %lu", (unsigned long)newSuspendCount); + + [self postSuspendCountChangedNotification]; + } + + return newSuspendCount; +} + +- (NSUInteger)resume +{ + BOOL underflow = 0; + NSUInteger newSuspendCount = 0; + + OSSpinLockLock(&suspendCountLock); + { + if (suspendCount > 0) + suspendCount--; + else + underflow = YES; + + newSuspendCount = suspendCount; + } + OSSpinLockUnlock(&suspendCountLock); + + if (underflow) + { + YDBLogWarn(@"%@ - Attempting to resume with suspendCount already at zero.", THIS_METHOD); + } + else + { + if (newSuspendCount == 0) + YDBLogInfo(@"=> RESUMED"); + else + YDBLogInfo(@"=> SUSPENDED : decremented suspendCount == %lu", (unsigned long)newSuspendCount); + + [self postSuspendCountChangedNotification]; + } + + if (newSuspendCount == 0 && !underflow) + { + BOOL forceNotification = NO; + [self asyncMaybeDispatchNextOperation:forceNotification]; + } + + return newSuspendCount; +} + +- (void)postSuspendCountChangedNotification +{ + dispatch_block_t block = ^{ @autoreleasepool { + + [[NSNotificationCenter defaultCenter] postNotificationName:YapDatabaseCloudKitSuspendCountChangedNotification + object:self]; + }}; + + if ([NSThread isMainThread]) + block(); + else + dispatch_async(dispatch_get_main_queue(), block); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Change-Sets +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Returns an array of YDBCKChangeSet objects, which represent the pending (and in-flight) change-sets. + * The array is ordered, such that: + * - the first item in the array is either in-flight or the next to be uploaded + * - the last item in the array represents the most recent change-set + * + * From this array you'll be able to see exactly what YapDatabaseCloudKit is uploading (or intends to upload). + * + * This is also useful if you want to perform a "dry run" test. + * You can simply run a few tests with a debug database, + * and keep the YapDatabaseCloudKit extension suspended the whole time. + * Then just inspect the change-sets to ensure that everything is working as you expect. +**/ +- (NSArray *)pendingChangeSets +{ + // Implementation Note: + // The changeSetsFromPreviousCommits method is thread-safe, + // and also creates fullCopies of all the change-sets so the user receives immutable copies. + return [masterQueue changeSetsFromPreviousCommits]; +} + +/** + * Faster access if you just want to get the counts. + * + * - numberOfInFlightChangeSets: + * YDBCKChangeSets that have been dispatched to CloudKit Framework. + * These may or may not succeed, depending upon network conditions & other factors. + * + * - numberOfQueuedChangeSets: + * YDBCKChangeSets that have not been dispatched to CloudKit Framework. + * They are waiting for the current inFlight change-sets to succeed, or for YDBCK to be resumed. + * + * - numberOfPendingChangeSets: + * Includes all YDBCKChangeSets, both inFlight & queued. + * + * In mathematical notion, the relationships are: + * + * numberOfInFlightChangeSets == numberOfPendingChangeSets - numberOfQueuedChangeSets + * numberOfQueuedChangeSets == numberOfPendingChangeSets - numberOfInFlightChangeSets + * numberOfPendingChangeSets == numberOfPendingChangeSets + numberOfQueuedChangeSets +**/ +- (NSUInteger)numberOfInFlightChangeSets +{ + return [masterQueue numberOfInFlightChangeSets]; +} +- (NSUInteger)numberOfQueuedChangeSets { + return [masterQueue numberOfQueuedChangeSets]; +} +- (NSUInteger)numberOfPendingChangeSets { + return [masterQueue numberOfPendingChangeSets]; +} +- (void)getNumberOfInFlightChangeSets:(NSUInteger *)numInFlightChangeSetsPtr + queuedChangeSets:(NSUInteger *)numQueuedChangeSetsPtr +{ + return [masterQueue getNumberOfInFlightChangeSets:numInFlightChangeSetsPtr + queuedChangeSets:numQueuedChangeSetsPtr]; +} + +- (void)postInFlightChangeSetChangedNotification:(NSString *)newChangeSetUUID +{ + dispatch_block_t block = ^{ @autoreleasepool { + + NSDictionary *details = nil; + if (newChangeSetUUID) { + details = @{ @"uuid" : newChangeSetUUID }; + } + + [[NSNotificationCenter defaultCenter] + postNotificationName:YapDatabaseCloudKitInFlightChangeSetChangedNotification + object:self + userInfo:details]; + }}; + + if ([NSThread isMainThread]) + block(); + else + dispatch_async(dispatch_get_main_queue(), block); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark YapDatabaseExtension Protocol +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Subclasses MUST implement this method. + * Returns a proper instance of the YapDatabaseExtensionConnection subclass. +**/ +- (YapDatabaseExtensionConnection *)newConnection:(YapDatabaseConnection *)databaseConnection +{ + return [[YapDatabaseCloudKitConnection alloc] initWithParent:self databaseConnection:databaseConnection]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Table Name +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (NSString *)mappingTableName +{ + return [[self class] mappingTableNameForRegisteredName:self.registeredName]; +} + +- (NSString *)recordTableName +{ + return [[self class] recordTableNameForRegisteredName:self.registeredName]; +} + +- (NSString *)queueTableName +{ + return [[self class] queueTableNameForRegisteredName:self.registeredName]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Private API +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)asyncMaybeDispatchNextOperation:(BOOL)forceNotification +{ + YDBLogAutoTrace(); + + // The 'forceNotification' parameter will be YES when this method + // is being called after successfully completing a previous operation. + + dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_async(bgQueue, ^{ @autoreleasepool { + + if (self.isSuspended) // this method is thread-safe + { + YDBLogVerbose(@"Skipping dispatch operation - suspended"); + + if (forceNotification) { + [self postInFlightChangeSetChangedNotification:[masterQueue currentChangeSetUUID]]; + } + return; + } + + BOOL isAlreadyInFlight = NO; + YDBCKChangeSet *nextChangeSet = nil; + + nextChangeSet = [masterQueue makeInFlightChangeSet:&isAlreadyInFlight]; // this method is thread-safe + if (nextChangeSet == nil) + { + if (isAlreadyInFlight) + YDBLogVerbose(@"Skipping dispatch operation - upload in progress"); + else + YDBLogVerbose(@"Skipping dispatch operation - nothing to upload"); + + if (forceNotification) { + [self postInFlightChangeSetChangedNotification:[masterQueue currentChangeSetUUID]]; + } + return; + } + + if ([nextChangeSet->deletedRecordIDs count] == 0 && + [nextChangeSet->modifiedRecords count] == 0) + { + YDBLogVerbose(@"Dropping empty queued operation: %@", nextChangeSet); + + NSString *changeSetUUID = nextChangeSet.uuid; + + [self handleCompletedOperationWithChangeSet:nextChangeSet savedRecords:nil deletedRecordIDs:nil]; + [self postInFlightChangeSetChangedNotification:changeSetUUID]; + } + else + { + YDBLogVerbose(@"Queueing operation: %@", nextChangeSet); + + NSString *changeSetUUID = nextChangeSet.uuid; + + [self queueOperationForChangeSet:nextChangeSet]; + [self postInFlightChangeSetChangedNotification:changeSetUUID]; + } + }}); +} + + +- (YapDatabaseConnection *)completionDatabaseConnection +{ + if (completionDatabaseConnection == nil) + { + completionDatabaseConnection = [self.registeredDatabase newConnection]; + completionDatabaseConnection.objectCacheEnabled = NO; + completionDatabaseConnection.metadataCacheEnabled = NO; + } + + return completionDatabaseConnection; +} + +- (CKDatabase *)databaseForIdentifier:(id)dbID +{ + if (dbID == nil || dbID == [NSNull null]) + { + return [[CKContainer defaultContainer] privateCloudDatabase]; + } + else + { + NSAssert([dbID isKindOfClass:[NSString class]], @"Invalid databaseIdentifier"); + + NSString *databaseIdentifier = (NSString *)dbID; + + CKDatabase *database = [databaseCache objectForKey:databaseIdentifier]; + if (database == nil) + { + if (databaseIdentifierBlock == nil) { + @throw [self missingDatabaseIdentifierBlockException:databaseIdentifier]; + } + + database = databaseIdentifierBlock(databaseIdentifier); + if (database == nil) { + @throw [self missingCKDatabaseException:databaseIdentifier]; + } + + if (databaseCache == nil) { + databaseCache = [[YapCache alloc] initWithCountLimit:4]; + databaseCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + databaseCache.allowedObjectClasses = [NSSet setWithObject:[CKDatabase class]]; + } + + [databaseCache setObject:database forKey:databaseIdentifier]; + } + + return database; + } +} + +- (void)queueOperationForChangeSet:(YDBCKChangeSet *)changeSet +{ + YDBLogAutoTrace(); + + CKDatabase *database = [self databaseForIdentifier:changeSet.databaseIdentifier]; + + NSArray *recordsToSave = changeSet.recordsToSave_noCopy; + NSArray *recordIDsToDelete = changeSet.recordIDsToDelete; + + YDBLogVerbose(@"CKModifyRecordsOperation UPLOADING: databaseIdentifier = %@:\n" + @" recordsToSave: %@\n" + @" recordIDsToDelete: %@", + changeSet.databaseIdentifier, recordsToSave, recordIDsToDelete); + + CKModifyRecordsOperation *modifyRecordsOperation = + [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave recordIDsToDelete:recordIDsToDelete]; + modifyRecordsOperation.database = database; + modifyRecordsOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged; + + __weak YapDatabaseCloudKit *weakSelf = self; + + modifyRecordsOperation.modifyRecordsCompletionBlock = + ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *operationError) + { + #pragma clang diagnostic push + #pragma clang diagnostic warning "-Wimplicit-retain-self" + + __strong YapDatabaseCloudKit *strongSelf = weakSelf; + if (strongSelf == nil) return; + + if (operationError) + { + if (operationError.code == CKErrorPartialFailure) + { + YDBLogInfo(@"CKModifyRecordsOperation partial error: databaseIdentifier = %@\n" + @" error = %@", changeSet.databaseIdentifier, operationError); + + [strongSelf handlePartiallyFailedOperationWithChangeSet:changeSet + savedRecords:savedRecords + deletedRecordIDs:deletedRecordIDs + error:operationError]; + } + else + { + YDBLogInfo(@"CKModifyRecordsOperation error: databaseIdentifier = %@\n" + @" error = %@", changeSet.databaseIdentifier, operationError); + + [strongSelf handleFailedOperationWithChangeSet:changeSet + error:operationError]; + } + } + else + { + YDBLogVerbose(@"CKModifyRecordsOperation COMPLETE: databaseIdentifier = %@:\n" + @" savedRecords: %@\n" + @" deletedRecordIDs: %@", + changeSet.databaseIdentifier, savedRecords, deletedRecordIDs); + + [strongSelf handleCompletedOperationWithChangeSet:changeSet + savedRecords:savedRecords + deletedRecordIDs:deletedRecordIDs]; + } + + #pragma clang diagnostic pop + }; + + [masterOperationQueue addOperation:modifyRecordsOperation]; +} + +- (void)handleFailedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + error:(NSError *)operationError +{ + YDBLogAutoTrace(); + + // First, we suspend ourself. + // It is the responsibility of the delegate to resume us at the appropriate time. + + [self suspend]; + + // Then we reset changeSet.isInFlight to NO (since it failed). + // + // Note: For partially failed operations this step is done elsewhere. + // Specifically, it's performed at the end of the databaseTransaction that removes the items that did complete. + + [masterQueue resetFailedInFlightChangeSet]; + [self postInFlightChangeSetChangedNotification:changeSet.uuid]; + + // Inform the user about the problem via the operationErrorBlock. + + NSString *databaseIdentifier = changeSet.databaseIdentifier; + dispatch_async(dispatch_get_main_queue(), ^{ + + opErrorBlock(databaseIdentifier, operationError); + }); +} + +- (void)handlePartiallyFailedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)attempted_savedRecords + deletedRecordIDs:(NSArray *)attempted_deletedRecordIDs + error:(NSError *)operationError +{ + // First, we suspend ourself. + // It is the responsibility of the delegate to resume us at the appropriate time. + + [self suspend]; + + // We need to figure out what succeeded. + // So first we get a set of the recordIDs that failed. + + NSDictionary *partialErrorsByItemID = [operationError.userInfo objectForKey:CKPartialErrorsByItemIDKey]; + NSMutableSet *failedRecordIDs = [NSMutableSet setWithCapacity:[partialErrorsByItemID count]]; + + [partialErrorsByItemID enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + __unsafe_unretained CKRecordID *recordID = (CKRecordID *)key; + // __unsafe_unretained NSError *recordError = (NSError *)obj; + + [failedRecordIDs addObject:recordID]; + }]; + + // Then we remove the failed items from the attempted items. + + NSUInteger sCapacity = attempted_savedRecords.count; + NSUInteger dCapacity = attempted_deletedRecordIDs.count; + + NSMutableArray *success_savedRecords = [NSMutableArray arrayWithCapacity:sCapacity]; + NSMutableArray *success_deletedRecordIDs = [NSMutableArray arrayWithCapacity:dCapacity]; + + for (CKRecord *record in attempted_savedRecords) + { + if (![failedRecordIDs containsObject:record.recordID]) + { + [success_savedRecords addObject:record]; + } + } + for (CKRecordID *recordID in attempted_deletedRecordIDs) + { + if (![failedRecordIDs containsObject:recordID]) + { + [success_deletedRecordIDs addObject:recordID]; + } + } + + // Start the database transaction to update the queue(s) by removing those items that have succeeded. + + NSString *extName = self.registeredName; + NSString *databaseIdentifier = changeSet.databaseIdentifier; + + [[self completionDatabaseConnection] asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + + [[transaction ext:extName] handlePartiallyCompletedOperationWithChangeSet:changeSet + savedRecords:success_savedRecords + deletedRecordIDs:success_deletedRecordIDs]; + + } completionBlock:^{ + + // Inform the user about the problem via the operationErrorBlock. + + opErrorBlock(databaseIdentifier, operationError); + }]; +} + +- (void)handleCompletedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)savedRecords + deletedRecordIDs:(NSArray *)deletedRecordIDs +{ + YDBLogAutoTrace(); + + NSString *extName = self.registeredName; + + [[self completionDatabaseConnection] asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + + [[transaction ext:extName] handleCompletedOperationWithChangeSet:changeSet + savedRecords:savedRecords + deletedRecordIDs:deletedRecordIDs]; + }]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Exceptions +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (NSException *)missingDatabaseIdentifierBlockException:(NSString *)databaseIdentifier +{ + NSString *reason = [NSString stringWithFormat: + @"The YapDatabaseCloudKit instance was not configured with a databaseIdentifierBlock." + @" However, we encountered an object with a non-nil databaseIdentifier (%@)." + @" The databaseIdentifierBlock is required in order to discover the proper CKDatabase for the databaseIdentifier." + @" Without the CKDatabase, we don't know where to send the corresponding CKRecord/CKRecordID.", + databaseIdentifier]; + + return [NSException exceptionWithName:@"YapDatabaseCloudKit" reason:reason userInfo:nil]; +} + +- (NSException *)missingCKDatabaseException:(NSString *)databaseIdentifier +{ + NSString *reason = [NSString stringWithFormat: + @"The databaseIdentifierBlock returned nil for databaseIdentifier (%@)." + @" The databaseIdentifierBlock is required to return the proper CKDatabase for the databaseIdentifier." + @" Without the CKDatabase, we don't know where to send the corresponding CKRecord/CKRecordID.", + databaseIdentifier]; + + return [NSException exceptionWithName:@"YapDatabaseCloudKit" reason:reason userInfo:nil]; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h new file mode 100644 index 0000000..3820042 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.h @@ -0,0 +1,14 @@ +#import +#import "YapDatabaseExtensionConnection.h" + +@class YapDatabaseCloudKit; + + +@interface YapDatabaseCloudKitConnection : YapDatabaseExtensionConnection + +/** + * Returns the parent view instance. +**/ +@property (nonatomic, strong, readonly) YapDatabaseCloudKit *cloudKit; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.m new file mode 100644 index 0000000..17d9771 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitConnection.m @@ -0,0 +1,821 @@ +#import "YapDatabaseCloudKitPrivate.h" +#import "YapDatabasePrivate.h" +#import "YapDatabaseString.h" +#import "YapDatabaseLogging.h" + +/** + * Define log level for this file: OFF, ERROR, WARN, INFO, VERBOSE + * See YapDatabaseLogging.h for more information. +**/ +#if DEBUG + static const int ydbLogLevel = YDB_LOG_LEVEL_VERBOSE | YDB_LOG_FLAG_TRACE; +#else + static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; +#endif +#pragma unused(ydbLogLevel) + + +@implementation YapDatabaseCloudKitConnection +{ + sqlite3_stmt *mappingTable_insertStatement; + sqlite3_stmt *mappingTable_updateForRowidStatement; + sqlite3_stmt *mappingTable_getInfoForRowidStatement; + sqlite3_stmt *mappingTable_enumerateForHashStatement; + sqlite3_stmt *mappingTable_removeForRowidStatement; + sqlite3_stmt *mappingTable_removeAllStatement; + + sqlite3_stmt *recordTable_insertStatement; + sqlite3_stmt *recordTable_updateOwnerCountStatement; + sqlite3_stmt *recordTable_updateMetadataStatement; + sqlite3_stmt *recordTable_updateRecordStatement; + sqlite3_stmt *recordTable_getInfoForHashStatement; + sqlite3_stmt *recordTable_getOwnerCountForHashStatement; + sqlite3_stmt *recordTable_getCountForHashStatement; + sqlite3_stmt *recordTable_enumerateStatement; + sqlite3_stmt *recordTable_removeForHashStatement; + sqlite3_stmt *recordTable_removeAllStatement; + + sqlite3_stmt *queueTable_insertStatement; + sqlite3_stmt *queueTable_updateDeletedRecordIDsStatement; + sqlite3_stmt *queueTable_updateModifiedRecordsStatement; + sqlite3_stmt *queueTable_updateBothStatement; + sqlite3_stmt *queueTable_removeForUuidStatement; + sqlite3_stmt *queueTable_removeAllStatement; +} + +@synthesize cloudKit = parent; + +- (id)initWithParent:(YapDatabaseCloudKit *)inCloudKit databaseConnection:(YapDatabaseConnection *)inDbC +{ + if ((self = [super init])) + { + parent = inCloudKit; + databaseConnection = inDbC; + + cleanMappingTableInfoCache = [[YapCache alloc] initWithCountLimit:100]; + cleanMappingTableInfoCache.allowedKeyClasses = [NSSet setWithObject:[NSNumber class]]; + cleanMappingTableInfoCache.allowedObjectClasses = + [NSSet setWithObjects:[YDBCKCleanMappingTableInfo class], [NSNull class], nil]; + + cleanRecordTableInfoCache = [[YapCache alloc] initWithCountLimit:100]; + cleanRecordTableInfoCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + cleanRecordTableInfoCache.allowedObjectClasses = + [NSSet setWithObjects:[YDBCKCleanRecordTableInfo class], [NSNull class], nil]; + + recordKeysCache = [[YapCache alloc] initWithCountLimit:20]; + recordKeysCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + recordKeysCache.allowedObjectClasses = [NSSet setWithObject:[NSArray class]]; + + sharedKeySetForInternalChangeset = [NSDictionary sharedKeySetForKeys:[self internalChangesetKeys]]; + } + return self; +} + +- (void)dealloc +{ + [self _flushStatements]; +} + +- (void)_flushStatements +{ + sqlite_finalize_null(&mappingTable_insertStatement); + sqlite_finalize_null(&mappingTable_updateForRowidStatement); + sqlite_finalize_null(&mappingTable_getInfoForRowidStatement); + sqlite_finalize_null(&mappingTable_enumerateForHashStatement); + sqlite_finalize_null(&mappingTable_removeForRowidStatement); + sqlite_finalize_null(&mappingTable_removeAllStatement); + + sqlite_finalize_null(&recordTable_insertStatement); + sqlite_finalize_null(&recordTable_updateOwnerCountStatement); + sqlite_finalize_null(&recordTable_updateMetadataStatement); + sqlite_finalize_null(&recordTable_updateRecordStatement); + sqlite_finalize_null(&recordTable_getInfoForHashStatement); + sqlite_finalize_null(&recordTable_getOwnerCountForHashStatement); + sqlite_finalize_null(&recordTable_getCountForHashStatement); + sqlite_finalize_null(&recordTable_enumerateStatement); + sqlite_finalize_null(&recordTable_removeForHashStatement); + sqlite_finalize_null(&recordTable_removeAllStatement); + + sqlite_finalize_null(&queueTable_insertStatement); + sqlite_finalize_null(&queueTable_updateDeletedRecordIDsStatement); + sqlite_finalize_null(&queueTable_updateModifiedRecordsStatement); + sqlite_finalize_null(&queueTable_updateBothStatement); + sqlite_finalize_null(&queueTable_removeForUuidStatement); + sqlite_finalize_null(&queueTable_removeAllStatement); +} + +/** + * Required override method from YapDatabaseExtensionConnection +**/ +- (void)_flushMemoryWithFlags:(YapDatabaseConnectionFlushMemoryFlags)flags +{ + if (flags & YapDatabaseConnectionFlushMemoryFlags_Caches) + { + [cleanMappingTableInfoCache removeAllObjects]; + [cleanRecordTableInfoCache removeAllObjects]; + } + + if (flags & YapDatabaseConnectionFlushMemoryFlags_Statements) + { + [self _flushStatements]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Accessors +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Required override method from YapDatabaseExtensionConnection. +**/ +- (YapDatabaseExtension *)extension +{ + return parent; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Transactions +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Required override method from YapDatabaseExtensionConnection. +**/ +- (id)newReadTransaction:(YapDatabaseReadTransaction *)databaseTransaction +{ + YDBLogAutoTrace(); + + YapDatabaseCloudKitTransaction *transaction = + [[YapDatabaseCloudKitTransaction alloc] initWithParentConnection:self + databaseTransaction:databaseTransaction]; + + return transaction; +} + +/** + * Required override method from YapDatabaseExtensionConnection. +**/ +- (id)newReadWriteTransaction:(YapDatabaseReadWriteTransaction *)databaseTransaction +{ + YDBLogAutoTrace(); + + YapDatabaseCloudKitTransaction *transaction = + [[YapDatabaseCloudKitTransaction alloc] initWithParentConnection:self + databaseTransaction:databaseTransaction]; + + [self prepareForReadWriteTransaction]; + return transaction; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Changeset Architecture +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Initializes any ivars that a read-write transaction may need. +**/ +- (void)prepareForReadWriteTransaction +{ + if (dirtyMappingTableInfoDict == nil) + dirtyMappingTableInfoDict = [[NSMutableDictionary alloc] init]; + + if (dirtyRecordTableInfoDict == nil) + dirtyRecordTableInfoDict = [[NSMutableDictionary alloc] init]; +} + +/** + * Invoked by our YapDatabaseCloudKitTransaction at the completion of the commitTransaction method. +**/ +- (void)postCommitCleanup +{ + YDBLogAutoTrace(); + + // Now that the commit has hit the disk, + // we can create all the NSOperation(s) with all the changes, and hand them to CloudKit. + + if (isOperationCompletionTransaction) + { + BOOL forceNotification = YES; // inFlightChangeSet is changing (new changeSet or nil) + + [parent->masterQueue removeCompletedInFlightChangeSet]; + [parent asyncMaybeDispatchNextOperation:forceNotification]; + } + else if (isOperationPartialCompletionTransaction) + { + BOOL forceNotification = YES; // inFlightChangeSet is changing (no longer inFlight) + + [parent->masterQueue resetFailedInFlightChangeSet]; + [parent asyncMaybeDispatchNextOperation:forceNotification]; + } + else if (changeset_deletedRowids.count > 0 || + changeset_deletedHashes.count > 0 || + changeset_mappingTableInfo.count > 0 || + changeset_recordTableInfo.count > 0 || + reset) + { + BOOL forceNotification = NO; + [parent asyncMaybeDispatchNextOperation:forceNotification]; + } + + dirtyMappingTableInfoDict = nil; + dirtyRecordTableInfoDict = nil; + pendingAttachRequests = nil; + + reset = NO; + isOperationCompletionTransaction = NO; + isOperationPartialCompletionTransaction = NO; + + changeset_deletedRowids = nil; + changeset_deletedHashes = nil; + changeset_mappingTableInfo = nil; + changeset_recordTableInfo = nil; +} + +/** + * Invoked by our YapDatabaseViewTransaction at the completion of the rollbackTransaction method. +**/ +- (void)postRollbackCleanup +{ + YDBLogAutoTrace(); + + [cleanMappingTableInfoCache removeAllObjects]; + [cleanRecordTableInfoCache removeAllObjects]; + + dirtyMappingTableInfoDict = nil; + dirtyRecordTableInfoDict = nil; + pendingAttachRequests = nil; + + reset = NO; + isOperationCompletionTransaction = NO; + isOperationPartialCompletionTransaction = NO; + + changeset_deletedRowids = nil; + changeset_deletedHashes = nil; + changeset_mappingTableInfo = nil; + changeset_recordTableInfo = nil; +} + +- (NSArray *)internalChangesetKeys +{ + return @[ changeset_key_deletedRowids, + changeset_key_deletedHashes, + changeset_key_mappingTableInfo, + changeset_key_recordTableInfo, + changeset_key_reset ]; +} + +/** + * Required override method from YapDatabaseExtensionConnection. +**/ +- (void)getInternalChangeset:(NSMutableDictionary **)internalChangesetPtr + externalChangeset:(NSMutableDictionary **)externalChangesetPtr + hasDiskChanges:(BOOL *)hasDiskChangesPtr +{ + YDBLogAutoTrace(); + + NSMutableDictionary *internalChangeset = nil; + BOOL hasDiskChanges = NO; + + if (isOperationCompletionTransaction || isOperationPartialCompletionTransaction) + hasDiskChanges = YES; + + if (changeset_deletedRowids.count > 0 || + changeset_deletedHashes.count > 0 || + changeset_mappingTableInfo.count > 0 || + changeset_recordTableInfo.count > 0 || + reset) + { + internalChangeset = [NSMutableDictionary dictionaryWithSharedKeySet:sharedKeySetForInternalChangeset]; + + if (changeset_deletedRowids.count > 0) + { + internalChangeset[changeset_key_deletedRowids] = changeset_deletedRowids; + } + + if (changeset_deletedHashes.count > 0) + { + internalChangeset[changeset_key_deletedHashes] = changeset_deletedHashes; + } + + if (changeset_mappingTableInfo.count > 0) + { + internalChangeset[changeset_key_mappingTableInfo] = changeset_mappingTableInfo; + } + + if (changeset_recordTableInfo.count > 0) + { + internalChangeset[changeset_key_recordTableInfo] = changeset_recordTableInfo; + } + + if (reset) + { + internalChangeset[changeset_key_reset] = @(reset); + } + + hasDiskChanges = YES; + } + + *internalChangesetPtr = internalChangeset; + *externalChangesetPtr = nil; + *hasDiskChangesPtr = hasDiskChanges; +} + +- (void)processChangeset:(NSDictionary *)changeset +{ + YDBLogAutoTrace(); + + NSSet *in_changeset_deletedRowids = changeset[changeset_key_deletedRowids]; + NSSet *in_changeset_deletedHashes = changeset[changeset_key_deletedHashes]; + + NSDictionary *in_changeset_mappingTableInfo = changeset[changeset_key_mappingTableInfo]; + NSDictionary *in_changeset_recordTableInfo = changeset[changeset_key_recordTableInfo]; + + BOOL in_changeset_reset = [changeset[changeset_key_reset] boolValue]; + + // Update cleanMappingTableInfo + + if (in_changeset_reset && (in_changeset_mappingTableInfo.count == 0)) + { + // Shortcut + + [cleanMappingTableInfoCache removeAllObjects]; + } + else if (in_changeset_reset || (in_changeset_deletedRowids.count > 0) || (in_changeset_mappingTableInfo.count > 0)) + { + // Enumerate the objects in the cache, and update them as needed + + NSUInteger removeCapacity; + NSUInteger updateCapacity; + + removeCapacity = in_changeset_reset ? cleanMappingTableInfoCache.count : in_changeset_deletedRowids.count; + updateCapacity = MIN(cleanMappingTableInfoCache.count, in_changeset_mappingTableInfo.count); + + NSMutableArray *keysToRemove = [NSMutableArray arrayWithCapacity:removeCapacity]; + NSMutableArray *keysToUpdate = [NSMutableArray arrayWithCapacity:updateCapacity]; + + [cleanMappingTableInfoCache enumerateKeysWithBlock:^(id key, BOOL *stop) { + + // Order matters. + // Consider the following database change: + // + // [transaction removeAllObjects]; + // [transaction setObject:obj forKey:key]; + + if ([in_changeset_mappingTableInfo objectForKey:key]) + [keysToUpdate addObject:key]; + else if (in_changeset_reset || [in_changeset_deletedRowids containsObject:key]) + [keysToRemove addObject:key]; + }]; + + [cleanMappingTableInfoCache removeObjectsForKeys:keysToRemove]; + + for (NSString *key in keysToUpdate) + { + YDBCKCleanMappingTableInfo *cleanMappingTableInfo = [in_changeset_mappingTableInfo objectForKey:key]; + + if (cleanMappingTableInfo) + [cleanMappingTableInfoCache setObject:cleanMappingTableInfo forKey:key]; + else + [cleanMappingTableInfoCache removeObjectForKey:key]; + } + } + + // Update cleanRecordTableInfo + + if (in_changeset_reset && (in_changeset_recordTableInfo.count == 0)) + { + // Shortcut + + [cleanRecordTableInfoCache removeAllObjects]; + } + else if (in_changeset_reset || (in_changeset_deletedHashes.count > 0) || (in_changeset_recordTableInfo.count > 0)) + { + // Enumerate the objects in the cache, and update them as needed + + NSUInteger removeCapacity; + NSUInteger updateCapacity; + + removeCapacity = in_changeset_reset ? cleanRecordTableInfoCache.count : in_changeset_deletedHashes.count; + updateCapacity = MIN(cleanRecordTableInfoCache.count, in_changeset_recordTableInfo.count); + + NSMutableArray *keysToRemove = [NSMutableArray arrayWithCapacity:removeCapacity]; + NSMutableArray *keysToUpdate = [NSMutableArray arrayWithCapacity:updateCapacity]; + + [cleanRecordTableInfoCache enumerateKeysWithBlock:^(id key, BOOL *stop) { + + // Order matters. + // Consider the following database change: + // + // [transaction removeAllObjects]; + // [transaction setObject:obj forKey:key]; + + if ([in_changeset_recordTableInfo objectForKey:key]) + [keysToUpdate addObject:key]; + else if (in_changeset_reset || [in_changeset_deletedHashes containsObject:key]) + [keysToRemove addObject:key]; + }]; + + [cleanRecordTableInfoCache removeObjectsForKeys:keysToRemove]; + + for (NSString *key in keysToUpdate) + { + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = [in_changeset_recordTableInfo objectForKey:key]; + + if (cleanRecordTableInfo) + [cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:key]; + else + [cleanRecordTableInfoCache removeObjectForKey:key]; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Statements - Utilities +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)prepareStatement:(sqlite3_stmt **)statement withString:(NSString *)stmtString caller:(SEL)caller_cmd +{ + sqlite3 *db = databaseConnection->db; + YapDatabaseString stmt; MakeYapDatabaseString(&stmt, stmtString); + + int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@: Error creating prepared statement: %d %s", + NSStringFromSelector(caller_cmd), status, sqlite3_errmsg(db)); + } + + FreeYapDatabaseString(&stmt); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Statements - MappingTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * CREATE TABLE IF NOT EXISTS "mappingTableName" ( + * "rowid" INTEGER PRIMARY KEY, + * "recordTable_hash" TEXT NOT NULL + * ); +**/ + +- (sqlite3_stmt *)mappingTable_insertStatement +{ + sqlite3_stmt **statement = &mappingTable_insertStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"INSERT OR REPLACE INTO \"%@\"" + @" (\"rowid\", \"recordTable_hash\") VALUES (?, ?);", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)mappingTable_updateForRowidStatement +{ + sqlite3_stmt **statement = &mappingTable_updateForRowidStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"recordTable_hash\" = ? WHERE \"rowid\" = ?;", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)mappingTable_getInfoForRowidStatement +{ + sqlite3_stmt **statement = &mappingTable_getInfoForRowidStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT \"recordTable_hash\" FROM \"%@\" WHERE \"rowid\" = ?;", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)mappingTable_enumerateForHashStatement +{ + sqlite3_stmt **statement = &mappingTable_enumerateForHashStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT \"rowid\" FROM \"%@\" WHERE \"recordTable_hash\" = ?;", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)mappingTable_removeForRowidStatement +{ + sqlite3_stmt **statement = &mappingTable_removeForRowidStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\" WHERE \"rowid\" = ?;", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)mappingTable_removeAllStatement +{ + sqlite3_stmt **statement = &mappingTable_removeAllStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\";", + [parent mappingTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Statements - RecordTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * CREATE TABLE IF NOT EXISTS "recordTableName" ( + * "hash" TEXT PRIMARY KEY, + * "databaseIdentifier" TEXT, + * "ownerCount" INTEGER, + * "record" BLOB + * ); +**/ + +- (sqlite3_stmt *)recordTable_insertStatement +{ + sqlite3_stmt **statement = &recordTable_insertStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"INSERT OR REPLACE INTO \"%@\"" + @" (\"hash\", \"databaseIdentifier\", \"ownerCount\", \"record\")" + @" VALUES (?, ?, ?, ?);", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_updateOwnerCountStatement +{ + sqlite3_stmt **statement = &recordTable_updateOwnerCountStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"ownerCount\" = ? WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_updateMetadataStatement +{ + sqlite3_stmt **statement = &recordTable_updateMetadataStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"ownerCount\" = ? WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_updateRecordStatement +{ + sqlite3_stmt **statement = &recordTable_updateRecordStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"record\" = ? WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_getInfoForHashStatement +{ + sqlite3_stmt **statement = &recordTable_getInfoForHashStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT \"databaseIdentifier\", \"ownerCount\", \"record\"" + @" FROM \"%@\"" + @" WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_getOwnerCountForHashStatement +{ + sqlite3_stmt **statement = &recordTable_getOwnerCountForHashStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT \"ownerCount\" FROM \"%@\" WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_getCountForHashStatement +{ + sqlite3_stmt **statement = &recordTable_getCountForHashStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"hash\" = ?;", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_enumerateStatement +{ + sqlite3_stmt **statement = &recordTable_enumerateStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"SELECT \"hash\", \"databaseIdentifier\", \"ownerCount\", \"recordTable_hash\", \"record\" FROM \"%@\";", + [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_removeForHashStatement +{ + sqlite3_stmt **statement = &recordTable_removeForHashStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\" WHERE \"hash\" = ?;", [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)recordTable_removeAllStatement +{ + sqlite3_stmt **statement = &recordTable_removeAllStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\";", [parent recordTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Statements - QueueTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * CREATE TABLE IF NOT EXISTS "queueTableName" ( + * "uuid" TEXT PRIMARY KEY NOT NULL, + * "prev" TEXT, + * "databaseIdentifier" TEXT, + * "deletedRecordIDs" BLOB, + * "modifiedRecords" BLOB + * ); +**/ + +- (sqlite3_stmt *)queueTable_insertStatement +{ + sqlite3_stmt **statement = &queueTable_insertStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"INSERT INTO \"%@\"" + @" (\"uuid\", \"prev\", \"databaseIdentifier\", \"deletedRecordIDs\", \"modifiedRecords\")" + @" VALUES (?, ?, ?, ?, ?);", + [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)queueTable_updateDeletedRecordIDsStatement +{ + sqlite3_stmt **statement = &queueTable_updateDeletedRecordIDsStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"deletedRecordIDs\" = ? WHERE \"uuid\" = ?;", + [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)queueTable_updateBothStatement +{ + sqlite3_stmt **statement = &queueTable_updateBothStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"deletedRecordIDs\" = ?, \"modifiedRecords\" = ? WHERE \"uuid\" = ?;", + [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)queueTable_updateModifiedRecordsStatement +{ + sqlite3_stmt **statement = &queueTable_updateModifiedRecordsStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"UPDATE \"%@\" SET \"modifiedRecords\" = ? WHERE \"uuid\" = ?;", + [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)queueTable_removeForUuidStatement +{ + sqlite3_stmt **statement = &queueTable_removeForUuidStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\" WHERE \"uuid\" = ?;", [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +- (sqlite3_stmt *)queueTable_removeAllStatement +{ + sqlite3_stmt **statement = &queueTable_removeAllStatement; + if (*statement == NULL) + { + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\";", [parent queueTableName]]; + + [self prepareStatement:statement withString:string caller:_cmd]; + } + + return *statement; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h new file mode 100644 index 0000000..e12bad7 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.h @@ -0,0 +1,32 @@ +#import +#import "YapWhitelistBlacklist.h" + + +@interface YapDatabaseCloudKitOptions : NSObject + +/** + * You can configure the extension to pre-filter all but a subset of collections. + * + * The primary motivation for this is to reduce the overhead when first setting up the extension. + * For example, if you're only syncing objects from a single collection, + * then you could specify that collection here. So when the extension first populates itself, + * it will enumerate over just the allowedCollections, as opposed to enumerating over all collections. + * And enumerating a small subset of the entire database during initial setup can improve speed, + * especially with larger databases. + * + * In addition to reducing the overhead during initial setup, + * the allowedCollections will pre-filter while you're making changes to the database. + * So if you add a new object to the database, and the associated collection isn't in allowedCollections, + * then the GetRecordBlock will never be invoked, and the extension will act as if the block returned nil. + * + * For all rows whose collection is in the allowedCollections, the extension acts normally. + * So the GetRecordBlock would still be invoked as normal. + * + * The default value is nil. +**/ +@property (nonatomic, strong, readwrite) YapWhitelistBlacklist *allowedCollections; + + +// Todo: Need ability to set default options for CKModifyRecordsOperation + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.m new file mode 100644 index 0000000..ce40839 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitOptions.m @@ -0,0 +1,15 @@ +#import "YapDatabaseCloudKitOptions.h" + +@implementation YapDatabaseCloudKitOptions + +@synthesize allowedCollections = allowedCollections; + +- (id)copyWithZone:(NSZone *)zone +{ + YapDatabaseCloudKitOptions *copy = [[[self class] alloc] init]; // [self class] required to support subclassing + copy->allowedCollections = allowedCollections; + + return copy; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h new file mode 100644 index 0000000..a481bf4 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.h @@ -0,0 +1,339 @@ +#import +#import "YapDatabaseExtensionTransaction.h" + + +@interface YapDatabaseCloudKitTransaction : YapDatabaseExtensionTransaction + +/** + * This method is used to associate an existing CKRecord with a row in the database. + * There are two primary use cases for this method. + * + * 1. To associate a discovered/pulled CKRecord with a row in the database before you insert it the row. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a record that was inserted by another device. + * - You need to add a corresponding row to the database, + * but you also need to inform the YapDatabaseCloudKit extension about the existing record, + * so it won't bother invoking the recordHandler, or attempting to upload the existing record. + * - So you invoke this method FIRST. + * - And THEN you insert the corresponding object into the database via the + * normal setObject:forKey:inCollection: method (or similar methods). + * + * 2. To assist in the migration process when switching to YapDatabaseCloudKit. + * In particular, for the following situation: + * + * - You've been handling CloudKit manually (not via YapDatabaseCloudKit). + * - And you now want YapDatabaseCloudKit to manage the CKRecord for you. + * - So you can invoke this method for an object that already exists in the database, + * OR you can invoke this method FIRST, and then insert the new object that you want linked to the record. + * + * Thus, this method works as a simple "hand-off" of the CKRecord to the YapDatabaseCloudKit extension. + * + * In other words, YapDatbaseCloudKit will write the system fields of the given CKRecord to its internal table, + * and associate it with the given collection/key tuple. + * + * @param record + * The CKRecord to associate with the collection/key tuple. + * + * @param databaseIdentifer + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * @param key + * The key of the row to associate the record with. + * + * @param collection + * The collection of the row to associate the record with. + * + * @param shouldUpload + * If NO, then the record is simply associated with the collection/key, + * and YapDatabaseCloudKit doesn't attempt to push the record to the cloud. + * If YES, then the record is associated with the collection/key, + * and YapDatabaseCloutKit assumes the given record is dirty and will push the record to the cloud. + * + * @return + * YES if the record was associated with the given collection/key. + * NO if one of the following errors occurred. + * + * The following errors will prevent this method from succeeding: + * - The given record is nil. + * - The given collection/key is already associated with a different record (so must detach it first). + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (BOOL)attachRecord:(CKRecord *)record + databaseIdentifier:(NSString *)databaseIdentifier + forKey:(NSString *)key + inCollection:(NSString *)collection + shouldUploadRecord:(BOOL)shouldUploadRecord; + +/** + * This method is used to unassociate an existing CKRecord with a row in the database. + * There are three primary use cases for this method. + * + * 1. To properly handle CKRecordID's that are reported as deleted from the server. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a recordID that was deleted by another device. + * - You need to remove the associated record from the database, + * but you also need to inform the YapDatabaseCloudKit extension that it was remotely deleted, + * so it won't bother attempting to upload the already deleted recordID. + * - So you invoke this method FIRST. + * - And THEN you can remove the corresponding object from the database via the + * normal removeObjectForKey:inCollection: method (or similar methods) (if needed). + * + * 2. To assist in various migrations, such as version migrations. + * For example: + * + * - In version 2 of your app, you need to move a few CKRecords into a new zone. + * - But you don't want to delete the items from the old zone, + * because you need to continue supporting v1.X for awhile. + * - So you invoke this method first in order to drop the previous record association(s). + * - And then you can attach the new CKRecord(s), + * and have YapDatabaseCloudKit upload the new records (to their new zone). + * + * 3. To "move" an object from the cloud to "local-only". + * For example: + * + * - You're making a Notes app that allows user to stores notes locally, or in the cloud. + * - The user moves an existing note from the cloud, to local-only storage. + * - This method can be used to delete the item from the cloud without deleting it locally. + * + * @param key + * The key of the row associated with the record to detach. + * + * @param collection + * The collection of the row associated with the record to detach. + * + * @param wasRemoteDeletion + * Did the server notify you of a deleted CKRecordID? + * Then make sure you set this parameter to YES. + * This allows the extension to properly modify any changeSets that are still queued for upload + * so that it can remove potential modifications for this recordID. + * + * Note: If a record was deleted remotely, and the record was associated with MULTIPLE items in the database, + * then you should be sure to invoke this method for each attached collection/key. + * + * @param shouldUpload + * Whether or not the extension should push a deleted CKRecordID to the cloud. + * In use case #2 (from the above discussion, concerning migration), you'd pass NO. + * In use case #3 (from the above discussion, concerning moving), you'd pass YES. + * This parameter is ignored if wasRemoteDeletion is YES (in which it will force shouldUpload to be NO). + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. + * + * @see getKey:collection:forRecordID:databaseIdentifier: +**/ +- (void)detachRecordForKey:(NSString *)key + inCollection:(NSString *)collection + wasRemoteDeletion:(BOOL)wasRemoteDeletion + shouldUploadDeletion:(BOOL)shouldUploadDeletion; + +/** + * This method is used to merge a pulled record from the server with what's in the database. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a record that was modified by another device. + * - You need to properly merge the changes with your own version of the object in the database, + * and you also need to inform YapDatabaseCloud extension about the merger + * so it can properly handle any changes that were pending a push to the cloud. + * + * Thus, you should use this method, which will invoke your mergeBlock with the appropriate parameters. + * + * @param remoteRecord + * A record that was modified remotely, and discovered via CKFetchRecordChangesOperation (or similar). + * This value will be passed as the remoteRecord parameter to the mergeBlock. + * + * @param databaseIdentifier + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (void)mergeRecord:(CKRecord *)remoteRecord databaseIdentifier:(NSString *)databaseIdentifer; + +/** + * This method allows you to manually modify a CKRecord. + * + * This is useful for tasks such as migrations, debugging, and various one-off tasks during the development lifecycle. + * For example, you added a property to some on of your model classes in the database, + * but you forgot to add the code that creates the corresponding property in the CKRecord. + * So you might whip up some code that uses this method, and forces that property to get uploaded to the server + * for all the corresponding model objects that you already updated. + * + * Returns NO if the given recordID/databaseIdentifier is unknown. + * That is, such a record has not been given to YapDatabaseCloudKit (via the recordHandler), + * or has not previously been associated with a collection/key, + * or the record was deleted earlier in this transaction. + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (BOOL)saveRecord:(CKRecord *)record databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * If the given recordID & databaseIdentifier are associated with a row in the database, + * then this method will return YES, and set the collectionPtr/keyPtr with the collection/key of the associated row. + * + * @param keyPtr (optional) + * If non-null, and this method returns YES, then the keyPtr will be set to the associated row's key. + * + * @param collectionPtr (optional) + * If non-null, and this method returns YES, then the collectionPtr will be set to the associated row's collection. + * + * @param recordID + * The CKRecordID to look for. + * + * @param databaseIdentifier + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * @return + * YES if the given recordID & databaseIdentifier are associated with a row in the database. + * NO otherwise. + * + * + * Note: + * It's possible to associate multiple items in the database with a single CKRecord/databaseIdentifier. + * This is completely legal, and supported by YapDatabaseCloudKit extension. + * However, if you do this keep in mind that this method will only return 1 of the associated items. + * Further, which item it returns is not guaranteed, and may change between method invocations. + * So, in this particular case, you likely should be using 'collectionKeysForRecordID:databaseIdentifier:'. +**/ +- (BOOL)getKey:(NSString **)keyPtr collection:(NSString **)collectionPtr + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * It's possible to associate multiple items in the database with a single CKRecord/databaseIdentifier. + * This is completely legal, and supported by YapDatabaseCloudKit extension. + * + * This method returns an array of YapCollectionKey objects, + * each associated with the given recordID/databaseIdentifier. + * + * @see YapCollectionKey +**/ +- (NSArray *)collectionKeysForRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * If the given key/collection tuple is associated with a record, + * then this method returns YES, and sets the recordIDPtr & databaseIdentifierPtr accordingly. + * + * @param recordIDPtr (optional) + * If non-null, and this method returns YES, then the recordIDPtr will be set to the associated recordID. + * + * @param databaseIdentifierPtr (optional) + * If non-null, and this method returns YES, then the databaseIdentifierPtr will be set to the associated value. + * Keep in mind that nil is a valid databaseIdentifier, + * and is generally used to signify the defaultContainer/privateCloudDatabase. + * + * @param key + * The key of the row in the database. + * + * @param collection + * The collection of the row in the database. + * + * @return + * YES if the given collection/key is associated with a CKRecord. + * NO otherwise. +**/ +- (BOOL)getRecordID:(CKRecordID **)recordIDPtr + databaseIdentifier:(NSString **)databaseIdentifierPtr + forKey:(NSString *)key + inCollection:(NSString *)collection; + +/** + * Returns a copy of the CKRcord for the given recordID/databaseIdentifier. + * + * Keep in mind that YapDatabaseCloudKit stores ONLY the system fields of a CKRecord. + * That is, it does NOT store any key/value pairs. + * It only stores "system fields", which is the internal metadata that CloudKit uses to handle sync state. + * + * So if you invoke this method from within a read-only transaction, + * then you will receive a "base" CKRecord, which is really only useful for extracting "system field" metadata, + * such as the 'recordChangeTag'. + * + * If you invoke this method from within a read-write transaction, + * then you will receive the "base" CKRecord, along with any modifications that have been made to the CKRecord + * during the current read-write transaction. + * + * Also keep in mind that you are receiving a copy of the record which YapDatabaseCloudKit is using internally. + * If you intend to manually modify the CKRecord directly, + * then you need to save those changes back into YapDatabaseCloudKit via 'saveRecord:databaseIdentifier'. + * + * @see saveRecord:databaseIdentifier: +**/ +- (CKRecord *)recordForRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * Convenience method. + * Combines the following two methods into a single call: + * + * - getRecordID:databaseIdentifier:forKey:inCollection: + * - recordForRecordID:databaseIdentifier: + * + * @see recordForRecordID:databaseIdentifier: +**/ +- (CKRecord *)recordForKey:(NSString *)key inCollection:(NSString *)collection; + +/** + * High performance lookup method, if you only need to know if YapDatabaseCloudKit has a + * record for the given recordID/databaseIdentifier. + * + * This method is much faster than invoking recordForRecordID:databaseIdentifier:, + * if you don't actually need the record. + * + * @return + * Whether or not YapDatabaseCloudKit is currently managing a record for the given recordID/databaseIdentifer. + * That is, whether or not there is currently one or more rows in the database attached to the CKRecord. +**/ +- (BOOL)containsRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier; + +/** + * Use this method during CKFetchRecordChangesOperation.fetchRecordChangesCompletionBlock. + * The values returned by this method will help you determine how to process each reported changedRecord. + * + * @param outRecordChangeTag + * If YapDatabaseRecord is managing a record for the given recordID/databaseIdentifier, + * this this will be set to the local record.recordChangeTag value. + * Remember that CloudKit tells us about changes that we made. + * It doesn't do so via push notification, but it still does when we use a CKFetchRecordChangesOperation. + * Thus its advantageous for us to ignore our own changes. + * This can be done by comparing the changedRecord.recordChangeTag vs outRecordChangeTag. + * If they're the same, then we already have this CKRecord (this change) in our system, and we can ignore it. + * + * Note: Sometimes during development, we may screw up some merge operations. + * This may happen when we're changing our data model(s) and record. + * If this happens, you can ignore the recordChangeTag, + * and force another merge by invoking mergeRecord:databaseIdentifier: again. + * + * @param outPendingModifications + * Tells you if there are changes in the queue for the given recordID/databaseIdentifier. + * That is, whether or not this record has been modified, and we have modifications that are still + * pending upload to the CloudKit servers. + * If this value is YES, then you MUST invoke mergeRecord:databaseIdentifier:. + * + * Note: It's possible for this value to be YES, and for outRecordChangeTag to be nil. + * This may happen if the user modified a record, deleted it, and neither of these changes have hit the server yet. + * Thus YDBCK no longer actively manages the record, but it does have changes for it sitting in the queue. + * Failure to observe this value could result in an infinite loop: + * attempt upload, partial error, fetch changes, failure to invoke merge properly, attempt upload, partial error... + * + * @param outPendingDelete + * Tells you if there is a pending delete of the record in the queue. + * That is, if we deleted the item locally, and the delete operation is pending upload to the cloudKit server. + * If this value is YES, then you may not want to create a new database item for the record. +**/ +- (void)getRecordChangeTag:(NSString **)outRecordChangeTag + hasPendingModifications:(BOOL *)outPendingModifications + hasPendingDelete:(BOOL *)outPendingDelete + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.m new file mode 100644 index 0000000..74b4652 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTransaction.m @@ -0,0 +1,4532 @@ +#import "YapDatabaseCloudKitPrivate.h" +#import "YapDatabasePrivate.h" +#import "YDBCKRecord.h" +#import "YDBCKAttachRequest.h" + +#import "YapDatabaseString.h" +#import "YapDatabaseLogging.h" + +#import "NSDictionary+YapDatabase.h" + +#import + +/** + * Define log level for this file: OFF, ERROR, WARN, INFO, VERBOSE + * See YapDatabaseLogging.h for more information. +**/ +#if DEBUG + static const int ydbLogLevel = YDB_LOG_LEVEL_VERBOSE | YDB_LOG_FLAG_TRACE; +#else + static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; +#endif +#pragma unused(ydbLogLevel) + +static NSString *const ExtKey_classVersion = @"classVersion"; +static NSString *const ExtKey_versionTag = @"versionTag"; + +typedef NS_OPTIONS(NSUInteger, YDBCKProcessRecordBitMask) { + YDBCK_skipUploadRecord = 1 << 0, + YDBCK_skipUploadDeletion = 1 << 1, + YDBCK_remoteDeletion = 1 << 2, + YDBCK_remoteMerge = 1 << 3, +}; + +@implementation YapDatabaseCloudKitTransaction +{ + NSSet *rowidsInMidMerge; +} + +- (id)initWithParentConnection:(YapDatabaseCloudKitConnection *)inParentConnection + databaseTransaction:(YapDatabaseReadTransaction *)inDatabaseTransaction +{ + if ((self = [super init])) + { + parentConnection = inParentConnection; + databaseTransaction = inDatabaseTransaction; + } + return self; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Extension Lifecycle +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static BOOL ClassVersionsAreCompatible(int oldClassVersion, int newClassVersion) +{ + if (oldClassVersion == 1 && newClassVersion == 3) + { + // In version 2, I added a bunch of stuff to try to combat an Apple bug that was plaguing the system. + // However, I eventually discovered the root cause of the bug, and came up with a better workaround. + // So in version 3, I reverted all the database architecture changes back to their original v1 form. + return YES; + } + else + { + return (oldClassVersion == newClassVersion); + } +} + +/** + * This method is called to create any necessary tables, + * as well as populate the view by enumerating over the existing rows in the database. + * + * Return YES if completed successfully, or if already prepared. + * Return NO if some kind of error occured. +**/ +- (BOOL)createIfNeeded +{ + YDBLogAutoTrace(); + + // Capture NEW values + // + // classVersion - the internal version number of YapDatabaseView implementation + // versionTag - user specified versionTag, used to force upgrade mechanisms + + int classVersion = YAP_DATABASE_CLOUD_KIT_CLASS_VERSION; + + NSString *versionTag = parentConnection->parent->versionTag; + + // Fetch OLD values + // + // - hasOldClassVersion - will be YES if the extension exists from a previous run of the app + + int oldClassVersion = 0; + BOOL hasOldClassVersion = [self getIntValue:&oldClassVersion forExtensionKey:ExtKey_classVersion persistent:YES]; + + NSString *oldVersionTag = [self stringValueForExtensionKey:ExtKey_versionTag persistent:YES]; + + if (!hasOldClassVersion) + { + // First time registration + + if (![self createTables]) return NO; + if (![self createNewMasterChangeQueue]) return NO; + if (![self populateTables]) return NO; + + [self setIntValue:classVersion forExtensionKey:ExtKey_classVersion persistent:YES]; + [self setStringValue:versionTag forExtensionKey:ExtKey_versionTag persistent:YES]; + } + else if (!ClassVersionsAreCompatible(oldClassVersion, classVersion)) + { + // Upgrading from older codebase + // + // Reserved for potential future use. + // Code would likely need to do something similar to the following: + // + // - restoreMasterChangeQueue + // - migrate table(s) + // - repopulateTables + + NSAssert(NO, @"Attempting invalid upgrade path !"); + return NO; + } + else if (![versionTag isEqualToString:oldVersionTag]) + { + // Handle user-indicated change + + if (![self restoreMasterChangeQueue]) return NO; + if (![self repopulateTables]) return NO; + + [self setStringValue:versionTag forExtensionKey:ExtKey_versionTag persistent:YES]; + } + else + { + // Restoring an up-to-date extension from a previous run. + + if (![self restoreMasterChangeQueue]) return NO; + } + + return YES; +} + +/** + * This method is called to prepare the transaction for use. + * + * Remember, an extension transaction is a very short lived object. + * Thus it stores the majority of its state within the extension connection (the parent). + * + * Return YES if completed successfully, or if already prepared. + * Return NO if some kind of error occured. +**/ +- (BOOL)prepareIfNeeded +{ + YDBLogAutoTrace(); + + // Nothing to do here for this extension. + + return YES; +} + +- (BOOL)createTables +{ + YDBLogAutoTrace(); + + sqlite3 *db = databaseTransaction->connection->db; + + NSString *mappingTableName = [self mappingTableName]; + NSString *recordTableName = [self recordTableName]; + NSString *queueTableName = [self queueTableName]; + + int status; + + // Mapping Table + // + // | rowid | recordTable_hash | + + YDBLogVerbose(@"Creating cloudKit table for registeredName(%@): %@", [self registeredName], mappingTableName); + + NSString *createMappingTable = [NSString stringWithFormat: + @"CREATE TABLE IF NOT EXISTS \"%@\"" + @"(\"rowid\" INTEGER PRIMARY KEY," + @" \"recordTable_hash\" TEXT NOT NULL" + @" );", mappingTableName]; + + NSString *createMappingTableIndex = [NSString stringWithFormat: + @"CREATE INDEX IF NOT EXISTS \"recordTable_hash\" ON \"%@\" (\"recordTable_hash\");", mappingTableName]; + + YDBLogVerbose(@"%@", createMappingTable); + status = sqlite3_exec(db, [createMappingTable UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ - Failed creating table (%@): %d %s", + THIS_METHOD, mappingTableName, status, sqlite3_errmsg(db)); + return NO; + } + + YDBLogVerbose(@"%@", createMappingTableIndex); + status = sqlite3_exec(db, [createMappingTableIndex UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ - Failed creating index on table (%@): %d %s", + THIS_METHOD, mappingTableName, status, sqlite3_errmsg(db)); + return NO; + } + + // Record Table + // + // | hash | ownerCount | databaseIdentifier | record | + + YDBLogVerbose(@"Creating cloudKit table for registeredName(%@): %@", [self registeredName], recordTableName); + + NSString *createRecordTable = [NSString stringWithFormat: + @"CREATE TABLE IF NOT EXISTS \"%@\"" + @" (\"hash\" TEXT PRIMARY KEY NOT NULL," // custom hash of CKRecordID & databaseIdentifier (for lookups) + @" \"databaseIdentifier\" TEXT," // user specified databaseIdentifier (null for default) + @" \"ownerCount\" INTEGER," // used for mapped records + @" \"record\" BLOB" // CKRecord (system fields only for mapped records) + @" );", recordTableName]; + + YDBLogVerbose(@"%@", createRecordTable); + status = sqlite3_exec(db, [createRecordTable UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ - Failed creating table (%@): %d %s", + THIS_METHOD, recordTableName, status, sqlite3_errmsg(db)); + return NO; + } + + // Queue Table + // + // | uuid | prev | deletedRecordIDs | modifiedRecords | + + YDBLogVerbose(@"Creating cloudKit table for registeredName(%@): %@", [self registeredName], queueTableName); + + NSString *createQueueTable = [NSString stringWithFormat: + @"CREATE TABLE IF NOT EXISTS \"%@\"" + @" (\"uuid\" TEXT PRIMARY KEY NOT NULL," + @" \"prev\" TEXT," + @" \"databaseIdentifier\" TEXT," + @" \"deletedRecordIDs\" BLOB," + @" \"modifiedRecords\" BLOB" + @" );", queueTableName]; + + YDBLogVerbose(@"%@", createQueueTable); + status = sqlite3_exec(db, [createQueueTable UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ - Failed creating table (%@): %d %s", + THIS_METHOD, queueTableName, status, sqlite3_errmsg(db)); + return NO; + } + + return YES; +} + +/** + * Shortcut when creating an extension for the first time. + * (No need to restore the masterChangeQueue when we know it doesn't exist.) +**/ +- (BOOL)createNewMasterChangeQueue +{ + parentConnection->parent->masterQueue = [[YDBCKChangeQueue alloc] initMasterQueue]; + + return YES; +} + +/** + * This method restores the masterChangeQueue from a previous app run. + * This allows us to pick up where we left off, and ensure all requested changes make it up to the cloud. +**/ +- (BOOL)restoreMasterChangeQueue +{ + YDBLogAutoTrace(); + + // Enumerate the rows in the queue table, + // and extract the row information into YDBCKChangeSet objects. + + sqlite3 *db = databaseTransaction->connection->db; + sqlite3_stmt *statement; + int status; + + NSMutableDictionary *changeSetsDict = [NSMutableDictionary dictionaryWithCapacity:1]; + YDBCKChangeSet *lastChangeSetFromEnumeration = nil; + + NSString *enumerate = [NSString stringWithFormat: + @"SELECT \"uuid\", \"prev\", \"databaseIdentifier\", \"deletedRecordIDs\", \"modifiedRecords\" FROM \"%@\";", + [self queueTableName]]; + + int col_uuid = SQLITE_COL_START + 0; + int col_prev = SQLITE_COL_START + 1; + int col_dbid = SQLITE_COL_START + 2; + int col_deletedRecordIDs = SQLITE_COL_START + 3; + int col_modifiedRecords = SQLITE_COL_START + 4; + + status = sqlite3_prepare_v2(db, [enumerate UTF8String], -1, &statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); + + return NO; + } + + while ((status = sqlite3_step(statement)) == SQLITE_ROW) + { + NSString *uuid = nil; + NSString *prev = nil; + NSString *dbid = nil; + NSData *blob1 = nil; + NSData *blob2 = nil; + + const unsigned char *_uuid = sqlite3_column_text(statement, col_uuid); + int _uuidLen = sqlite3_column_bytes(statement, col_uuid); + + uuid = [[NSString alloc] initWithBytes:_uuid length:_uuidLen encoding:NSUTF8StringEncoding]; + + int column_type; + + column_type = sqlite3_column_type(statement, col_prev); + if (column_type != SQLITE_NULL) + { + const unsigned char *_prev = sqlite3_column_text(statement, col_prev); + int _prevLen = sqlite3_column_bytes(statement, col_prev); + + prev = [[NSString alloc] initWithBytes:_prev length:_prevLen encoding:NSUTF8StringEncoding]; + } + + column_type = sqlite3_column_type(statement, col_dbid); + if (column_type != SQLITE_NULL) + { + const unsigned char *_dbid = sqlite3_column_text(statement, col_dbid); + int _dbidLen = sqlite3_column_bytes(statement, col_dbid); + + dbid = [[NSString alloc] initWithBytes:_dbid length:_dbidLen encoding:NSUTF8StringEncoding]; + } + + column_type = sqlite3_column_type(statement, col_deletedRecordIDs); + if (column_type != SQLITE_NULL) + { + const void *_blob1 = sqlite3_column_blob(statement, col_deletedRecordIDs); + int _blob1Len = sqlite3_column_bytes(statement, col_deletedRecordIDs); + + blob1 = [NSData dataWithBytesNoCopy:(void *)_blob1 length:_blob1Len freeWhenDone:NO]; + } + + column_type = sqlite3_column_type(statement, col_modifiedRecords); + if (column_type != SQLITE_NULL) + { + const void *_blob2 = sqlite3_column_blob(statement, col_modifiedRecords); + int _blob2Len = sqlite3_column_bytes(statement, col_modifiedRecords); + + blob2 = [NSData dataWithBytesNoCopy:(void *)_blob2 length:_blob2Len freeWhenDone:NO]; + } + + YDBCKChangeSet *changeSet = [[YDBCKChangeSet alloc] initWithUUID:uuid + prev:prev + databaseIdentifier:dbid + deletedRecordIDs:blob1 + modifiedRecords:blob2]; + + [changeSetsDict setObject:changeSet forKey:uuid]; + lastChangeSetFromEnumeration = changeSet; + } + + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_finalize(statement); + statement = NULL; + + // Put the changeSets into the correct order. + // + // We have a reverse linked-list, where every element points to the previous one. + // The first item in the linked-list will point to an item that no longer exists. + // That is, when an item is removed from the front of the linked list, + // we don't attempt to set next.prev = nil. (That would be unnecessary disk IO.) + // + // Also note that it's highly likely that the changeSets were enumerated in-order by sqlite. + // This is because sqlite likely enumerated the rows by rowid, + // and its very very likely the the highest rowid is the most recently inserted changeSet. + // + // So here's our algorithm: + // + // - Start with the lastChangeSetFromEnumeration. + // - Add it to the array. + // - Work backwards, looping, and adding prevChangeSet to the front of the array. + // - At this point we have an array that contains the range [firstChangeSet, lastChangeSetFromEnumeration]. + // - If lastChangeSetFromEnumeration was indeed the lastChangeSet, then we're done. + // - Otherwise we grab another changeSet from the dictionary, + // - add it to the end of the array, and then begin working backwards again. + + NSMutableArray *orderedChangeSets = [NSMutableArray arrayWithCapacity:[changeSetsDict count]]; + + YDBCKChangeSet *aChangeSet = lastChangeSetFromEnumeration; + NSUInteger offset = 0; + + while (aChangeSet != nil) + { + // Add the changeSet to the end of the ordered array (and remove from dictionary) + [orderedChangeSets addObject:aChangeSet]; + [changeSetsDict removeObjectForKey:aChangeSet.uuid]; + + // Work backwards, filling in all previous changeSets + do + { + aChangeSet = [changeSetsDict objectForKey:aChangeSet.prev]; + if (aChangeSet) + { + [orderedChangeSets insertObject:aChangeSet atIndex:offset]; + [changeSetsDict removeObjectForKey:aChangeSet.uuid]; + } + + } while (aChangeSet != nil); + + // Check to see if there are more in the dictionary, + // and keep going if needed. + + __block YDBCKChangeSet *remainingChangeSet = nil; + [changeSetsDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + remainingChangeSet = (YDBCKChangeSet *)obj; + *stop = YES; + }]; + + aChangeSet = remainingChangeSet; + offset = [orderedChangeSets count]; + } + + // Sanity check 1: Did we drain the changeSetsDict? + + if ([changeSetsDict count] != 0) + { + YDBLogError(@"Error restoring masterChangeQueue: Reverse-linked list corruption ! (A)"); + return NO; + } + + // Sanity check 2: The changeSets are all in order + + NSString *prevUuid = [[orderedChangeSets firstObject] uuid]; + + for (NSUInteger i = 1; i < [orderedChangeSets count]; i++) + { + YDBCKChangeSet *orderedChangeSet = [orderedChangeSets objectAtIndex:i]; + if (![orderedChangeSet.prev isEqualToString:prevUuid]) + { + YDBLogError(@"Error restoring masterChangeQueue: Reverse-linked-list corruption ! (B)"); + return NO; + } + + prevUuid = orderedChangeSet.uuid; + } + + // Restore CKRecords as needed + + void (^RestoreRecordBlock)(int64_t rowid, CKRecord **inOutRecord, YDBCKRecordInfo *recordInfo); + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithKeyBlock recordBlock = + (YapDatabaseCloudKitRecordWithKeyBlock)parentConnection->parent->recordBlock; + + RestoreRecordBlock = ^(int64_t rowid, CKRecord **inOutRecord, YDBCKRecordInfo *recordInfo) { + + YapCollectionKey *ck = [databaseTransaction collectionKeyForRowid:rowid]; + if (ck) + { + recordBlock(inOutRecord, recordInfo, ck.collection, ck.key); + } + }; + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + RestoreRecordBlock = ^(int64_t rowid, CKRecord **inOutRecord, YDBCKRecordInfo *recordInfo) { + + YapCollectionKey *ck = nil; + id object = nil; + + if ([databaseTransaction getCollectionKey:&ck object:&object forRowid:rowid]) + { + recordBlock(inOutRecord, recordInfo, ck.collection, ck.key, object); + } + }; + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + RestoreRecordBlock = ^(int64_t rowid, CKRecord **inOutRecord, YDBCKRecordInfo *recordInfo) { + + YapCollectionKey *ck = nil; + id metadata = nil; + + if ([databaseTransaction getCollectionKey:&ck metadata:&metadata forRowid:rowid]) + { + recordBlock(inOutRecord, recordInfo, ck.collection, ck.key, metadata); + } + }; + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + RestoreRecordBlock = ^(int64_t rowid, CKRecord **inOutRecord, YDBCKRecordInfo *recordInfo) { + + YapCollectionKey *ck = nil; + id object = nil; + id metadata = nil; + + if ([databaseTransaction getCollectionKey:&ck object:&object metadata:&metadata forRowid:rowid]) + { + recordBlock(inOutRecord, recordInfo, ck.collection, ck.key, object, metadata); + } + }; + } + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + + [orderedChangeSets enumerateObjectsUsingBlock:^(YDBCKChangeSet *changeSet, NSUInteger idx, BOOL *stop) { + + NSString *databaseIdentifier = changeSet.databaseIdentifier; + + recordInfo.databaseIdentifier = databaseIdentifier; + [changeSet enumerateMissingRecordsWithBlock:^CKRecord *(CKRecordID *recordID, NSArray *changedKeys) { + + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + + NSSet *rowids = [self mappingTableRowidsForRecordTableHash:hash]; + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + __block CKRecord *record = [cleanRecordTableInfo.record safeCopy]; + + recordInfo.keysToRestore = changedKeys; + for (NSNumber *rowidNumber in rowids) + { + int64_t rowid = [rowidNumber longLongValue]; + RestoreRecordBlock(rowid, &record, recordInfo); + } + + return record; + }]; + }]; + + // Restore the changeSets (set them as the oldChangeSets in the masterQueue) + + [parentConnection->parent->masterQueue restoreOldChangeSets:orderedChangeSets]; + + // Restart the uploads (if needed) + + BOOL forceNotification = NO; + [parentConnection->parent asyncMaybeDispatchNextOperation:forceNotification]; + + // Done! + return YES; +} + +- (BOOL)populateTables +{ + YDBLogAutoTrace(); + + void (^InsertRecord)(CKRecord*, YDBCKRecordInfo*, int64_t); + InsertRecord = ^(CKRecord *record, YDBCKRecordInfo *recordInfo, int64_t rowid) { + + NSString *databaseIdentifier = recordInfo.databaseIdentifier; + NSString *hash = [self hashRecordID:record.recordID databaseIdentifier:databaseIdentifier]; + + // Add row for mapping table + + YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo; + + dirtyMappingTableInfo = [[YDBCKDirtyMappingTableInfo alloc] initWithRecordTableHash:nil]; + dirtyMappingTableInfo.dirty_recordTable_hash = hash; + + [parentConnection->cleanMappingTableInfoCache removeObjectForKey:@(rowid)]; + [parentConnection->dirtyMappingTableInfoDict setObject:dirtyMappingTableInfo forKey:@(rowid)]; + + // Add/Update row for record table + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + [parentConnection->dirtyRecordTableInfoDict objectForKey:hash]; + + if (dirtyRecordTableInfo == nil) + { + dirtyRecordTableInfo = + [[YDBCKDirtyRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + recordID:nil + ownerCount:0]; + + dirtyRecordTableInfo.dirty_record = record; + [dirtyRecordTableInfo incrementOwnerCount]; + [dirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:@(rowid)]; + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:@(rowid)]; + } + else + { + [self mergeChangedValuesFromRecord:record intoRecord:dirtyRecordTableInfo.dirty_record]; + [dirtyRecordTableInfo incrementOwnerCount]; + [dirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + } + }; + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.versionInfo = parentConnection->parent->versionInfo; + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithKeyBlock recordBlock = + (YapDatabaseCloudKitRecordWithKeyBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, BOOL *stop) { + + CKRecord *record = nil; + recordInfo.databaseIdentifier = nil; + recordInfo.originalValues = nil; + + recordBlock(&record, recordInfo, collection, key); + + if (record) { + InsertRecord(record, recordInfo, rowid); + } + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysInAllCollectionsUsingBlock:enumBlock]; + } + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id object, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id object, BOOL *stop) { + + CKRecord *record = nil; + recordInfo.databaseIdentifier = nil; + recordInfo.originalValues = nil; + + recordBlock(&record, recordInfo, collection, key, object); + + if (record) { + InsertRecord(record, recordInfo, rowid); + } + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndObjectsInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:enumBlock]; + } + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id metadata, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id metadata, BOOL *stop) { + + CKRecord *record = nil; + recordInfo.databaseIdentifier = nil; + recordInfo.originalValues = nil; + + recordBlock(&record, recordInfo, collection, key, metadata); + + if (record) { + InsertRecord(record, recordInfo, rowid); + } + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndMetadataInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:enumBlock]; + } + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id object, id metadata, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id object, id metadata, BOOL *stop) { + + CKRecord *record = nil; + recordInfo.databaseIdentifier = nil; + recordInfo.originalValues = nil; + + recordBlock(&record, recordInfo, collection, key, object, metadata); + + if (record) { + InsertRecord(record, recordInfo, rowid); + } + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateRowsInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:enumBlock]; + } + } + + return YES; +} + +- (BOOL)repopulateTables +{ + YDBLogAutoTrace(); + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.versionInfo = parentConnection->parent->versionInfo; + + __block id mappingTableInfo = nil; + __block id recordTableInfo = nil; + __block CKRecord *record = nil; + + void (^enumHelperBlock)(int64_t) = ^(int64_t rowid) + { + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:YES]; + + recordInfo.databaseIdentifier = recordTableInfo.databaseIdentifier; + recordInfo.originalValues = nil; + + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordInfo; + + record = [cleanRecordTableInfo.record safeCopy]; + } + else if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + record = dirtyRecordTableInfo.dirty_record; + } + else + { + record = nil; + } + }; + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithKeyBlock recordBlock = + (YapDatabaseCloudKitRecordWithKeyBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, BOOL *stop) { + + enumHelperBlock(rowid); + recordBlock(&record, recordInfo, collection, key); + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysInAllCollectionsUsingBlock:enumBlock]; + } + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id object, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id object, BOOL *stop) { + + enumHelperBlock(rowid); + recordBlock(&record, recordInfo, collection, key, object); + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndObjectsInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:enumBlock]; + } + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id metadata, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id metadata, BOOL *stop) { + + enumHelperBlock(rowid); + recordBlock(&record, recordInfo, collection, key, metadata); + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndMetadataInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:enumBlock]; + } + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + void (^enumBlock)(int64_t rowid, NSString *collection, NSString *key, id object, id metadata, BOOL *stop); + enumBlock = ^(int64_t rowid, NSString *collection, NSString *key, id object, id metadata, BOOL *stop) { + + enumHelperBlock(rowid); + recordBlock(&record, recordInfo, collection, key, object, metadata); + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; + }; + + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateRowsInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; + } + else + { + [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:enumBlock]; + } + } + + return YES; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Accessors +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Required override method from YapDatabaseExtensionTransaction. +**/ +- (YapDatabaseReadTransaction *)databaseTransaction +{ + return databaseTransaction; +} + +/** + * Required override method from YapDatabaseExtensionTransaction. +**/ +- (YapDatabaseExtensionConnection *)extensionConnection +{ + return parentConnection; +} + +- (NSString *)registeredName +{ + return [parentConnection->parent registeredName]; +} + +- (NSString *)mappingTableName +{ + return [parentConnection->parent mappingTableName]; +} + +- (NSString *)recordTableName +{ + return [parentConnection->parent recordTableName]; +} + +- (NSString *)queueTableName +{ + return [parentConnection->parent queueTableName]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Utilities - General +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This method hashes the given recordID & databaseIdentifier into a 160 bit hash, + * and then returns a base64 representation of the hash. +**/ +- (NSString *)hashRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier +{ + // Edge case: + // Same recordID, but different databaseIdentifier. + // One is nil, the other is an empty string. + // + // We should try to make collisions nearly impossible + // when using the same recordID across different databaseIdentifiers. + + NSString *rcd1 = recordID.recordName; + NSString *rcd2 = recordID.zoneID.zoneName; + NSString *rcd3 = recordID.zoneID.ownerName; + + __unsafe_unretained NSString *dbid = databaseIdentifier; + + if (rcd1 == nil) rcd1 = @""; + if (rcd2 == nil) rcd2 = @""; + if (rcd3 == nil) rcd3 = @""; + // If dbid is nil, it stays nil + + NSUInteger maxLen = 2; + + maxLen = MAX(maxLen, [rcd1 lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + maxLen = MAX(maxLen, [rcd2 lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + maxLen = MAX(maxLen, [rcd3 lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + maxLen = MAX(maxLen, [dbid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + + int maxStackSize = 1024 * 2; + + uint8_t bufferStack[maxStackSize]; + void *buffer = NULL; + + if (maxLen <= maxStackSize) + buffer = bufferStack; + else + buffer = malloc((size_t)maxLen); + + CC_SHA1_CTX ctx; + CC_SHA1_Init(&ctx); + + NSUInteger used = 0; + + [rcd1 getBytes:buffer + maxLength:maxLen + usedLength:&used + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(0, [rcd1 length]) remainingRange:NULL]; + + CC_SHA1_Update(&ctx, buffer, (CC_LONG)used); + + [rcd2 getBytes:buffer + maxLength:maxLen + usedLength:&used + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(0, [rcd2 length]) remainingRange:NULL]; + + CC_SHA1_Update(&ctx, buffer, (CC_LONG)used); + + [rcd3 getBytes:buffer + maxLength:maxLen + usedLength:&used + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(0, [rcd3 length]) remainingRange:NULL]; + + CC_SHA1_Update(&ctx, buffer, (CC_LONG)used); + + if (dbid) + { + memcpy(buffer, (void *)'_', 1); // prefix with underscore to differentiate between nil & empty-string + + [dbid getBytes:(buffer + 1) + maxLength:(maxLen - 1) + usedLength:&used + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(0, [dbid length]) remainingRange:NULL]; + + CC_SHA1_Update(&ctx, buffer, (CC_LONG)(used + 1)); + } + + unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1_Final(hashBytes, &ctx); + + NSData *hashData = [NSData dataWithBytesNoCopy:(void *)hashBytes length:CC_SHA1_DIGEST_LENGTH freeWhenDone:NO]; + NSString *hashStr = [hashData base64EncodedStringWithOptions:0]; + + if (maxLen > maxStackSize) { + free(buffer); + } + return hashStr; +} + +- (void)mergeChangedValuesFromRecord:(CKRecord *)fromRecord intoRecord:(CKRecord *)toRecord +{ + for (NSString *key in fromRecord.changedKeys) + { + id value = [fromRecord objectForKey:key]; + + // The value may be nil. + // This is ok, as it just means the modification was to remove the value. + + [toRecord setObject:value forKey:key]; + } +} + +- (void)processRecord:(CKRecord *)record recordInfo:(YDBCKRecordInfo *)recordInfo + preCalculatedHash:(NSString *)preCalculatedRecordTableHash + forRowid:(int64_t)rowid + withPrevMappingTableInfo:(id )prevMappingTableInfo + prevRecordTableInfo:(id )prevRecordTableInfo + flags:(YDBCKProcessRecordBitMask)flags +{ + // Scenarios: + // + // - Rowid was not previously associated with record, and still is not. + // - Rowid was not previously associated with record, but now it is. + // - Rowid was previously associated with record, but now it is not. + // - Rowid was previously associated with record, but is now associated with a different record. + // - Rowid was previously associated with record, is still associated with same record, and made changes to record. + + NSString *prevRecordTableHash = prevMappingTableInfo.current_recordTable_hash; + + BOOL recordTableHashChangedForRowid = NO; + NSString *newRecordTableHash = nil; + + if (prevRecordTableHash) + { + if (record) + { + // Is the rowid associated with a new/different {recordID, databaseIdentifier} tuple ? + + if (preCalculatedRecordTableHash) + newRecordTableHash = preCalculatedRecordTableHash; + else + newRecordTableHash = [self hashRecordID:record.recordID + databaseIdentifier:recordInfo.databaseIdentifier]; + + if (![newRecordTableHash isEqualToString:prevRecordTableHash]) + { + // Rowid is now associated with a different record. + recordTableHashChangedForRowid = YES; + } + } + else + { + // Rowid is no longer associated with a record. + recordTableHashChangedForRowid = YES; + } + } + else if (record) + { + // Rowid is now associated with a record. (previously was not) + + if (preCalculatedRecordTableHash) + newRecordTableHash = preCalculatedRecordTableHash; + else + newRecordTableHash = [self hashRecordID:record.recordID + databaseIdentifier:recordInfo.databaseIdentifier]; + + recordTableHashChangedForRowid = YES; + } + + + if (recordTableHashChangedForRowid) + { + // Update mapping + + if ([prevMappingTableInfo isKindOfClass:[YDBCKDirtyMappingTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo = + (YDBCKDirtyMappingTableInfo *)prevMappingTableInfo; + + dirtyMappingTableInfo.dirty_recordTable_hash = newRecordTableHash; + } + else + { + YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo; + + dirtyMappingTableInfo = [[YDBCKDirtyMappingTableInfo alloc] initWithRecordTableHash:prevRecordTableHash]; + dirtyMappingTableInfo.dirty_recordTable_hash = newRecordTableHash; + + [parentConnection->cleanMappingTableInfoCache removeObjectForKey:@(rowid)]; + [parentConnection->dirtyMappingTableInfoDict setObject:dirtyMappingTableInfo forKey:@(rowid)]; + } + } + + if (recordTableHashChangedForRowid && prevRecordTableInfo) + { + // Rowid is no longer associated with record. + // Need to decrement ownerCount. + // If ownerCount drops to zero, then the record will be removed during commit processing. + + BOOL remoteDeletion = (flags & YDBCK_remoteDeletion) ? YES : NO; + BOOL skipUploadDeletion = (flags & YDBCK_skipUploadDeletion) ? YES : NO; + + if ([prevRecordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)prevRecordTableInfo; + + [dirtyRecordTableInfo decrementOwnerCount]; + + if (remoteDeletion) dirtyRecordTableInfo.remoteDeletion = remoteDeletion; + if (skipUploadDeletion) dirtyRecordTableInfo.skipUploadDeletion = skipUploadDeletion; + } + else + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)prevRecordTableInfo; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = [cleanRecordTableInfo dirtyCopy]; + [dirtyRecordTableInfo decrementOwnerCount]; + + if (remoteDeletion) dirtyRecordTableInfo.remoteDeletion = remoteDeletion; + if (skipUploadDeletion) dirtyRecordTableInfo.skipUploadDeletion = skipUploadDeletion; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:prevRecordTableHash]; + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:prevRecordTableHash]; + } + } + + if (recordTableHashChangedForRowid && newRecordTableHash) + { + // Rowid is associated with new record. + // Need to either create new entry in record table, + // or increment ownerCount of existing entry in record table (and merge any record changes). + + id newRecordTableInfo = [self recordTableInfoForHash:newRecordTableHash cacheResult:NO]; + + BOOL recordHasChangedValues = ([record.changedKeys count] > 0); + + BOOL remoteMerge = (flags & YDBCK_remoteMerge) ? YES : NO; + BOOL skipUploadRecord = (flags & YDBCK_skipUploadRecord) ? YES : NO; + + if ([newRecordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *newDirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)newRecordTableInfo; + + [self mergeChangedValuesFromRecord:record intoRecord:newDirtyRecordTableInfo.dirty_record]; + [newDirtyRecordTableInfo incrementOwnerCount]; + [newDirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + if (remoteMerge) newDirtyRecordTableInfo.remoteMerge = YES; + + if (newDirtyRecordTableInfo.skipUploadRecord && recordHasChangedValues && !skipUploadRecord) { + newDirtyRecordTableInfo.skipUploadRecord = NO; + } + } + else if ([newRecordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *newCleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)newRecordTableInfo; + + YDBCKDirtyRecordTableInfo *newDirtyRecordTableInfo = [newCleanRecordTableInfo dirtyCopy]; + + [self mergeChangedValuesFromRecord:record intoRecord:newDirtyRecordTableInfo.dirty_record]; + [newDirtyRecordTableInfo incrementOwnerCount]; + [newDirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + if (remoteMerge) newDirtyRecordTableInfo.remoteMerge = YES; + if (skipUploadRecord) newDirtyRecordTableInfo.skipUploadRecord = YES; + + if (!recordHasChangedValues) { // association only + newDirtyRecordTableInfo.skipUploadRecord = YES; + } + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:newRecordTableHash]; + [parentConnection->dirtyRecordTableInfoDict setObject:newDirtyRecordTableInfo forKey:newRecordTableHash]; + } + else + { + YDBCKDirtyRecordTableInfo *newDirtyRecordTableInfo = + [[YDBCKDirtyRecordTableInfo alloc] initWithDatabaseIdentifier:recordInfo.databaseIdentifier + recordID:nil + ownerCount:0]; + + newDirtyRecordTableInfo.dirty_record = record; + [newDirtyRecordTableInfo incrementOwnerCount]; + [newDirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + if (remoteMerge) newDirtyRecordTableInfo.remoteMerge = YES; + if (skipUploadRecord) newDirtyRecordTableInfo.skipUploadRecord = YES; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:newRecordTableHash]; + [parentConnection->dirtyRecordTableInfoDict setObject:newDirtyRecordTableInfo forKey:newRecordTableHash]; + } + } + + if (!recordTableHashChangedForRowid && ([record.changedKeys count] > 0)) + { + if ([prevRecordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)prevRecordTableInfo; + + [self mergeChangedValuesFromRecord:record intoRecord:dirtyRecordTableInfo.dirty_record]; + [dirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + } + else if ([prevRecordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)prevRecordTableInfo; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = [cleanRecordTableInfo dirtyCopy]; + + [self mergeChangedValuesFromRecord:record intoRecord:dirtyRecordTableInfo.dirty_record]; + [dirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:newRecordTableHash]; + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:newRecordTableHash]; + } + else + { + YDBCKDirtyRecordTableInfo *newDirtyRecordTableInfo = + [[YDBCKDirtyRecordTableInfo alloc] initWithDatabaseIdentifier:recordInfo.databaseIdentifier + recordID:nil + ownerCount:0]; + + newDirtyRecordTableInfo.dirty_record = record; + [newDirtyRecordTableInfo incrementOwnerCount]; + [newDirtyRecordTableInfo mergeOriginalValues:recordInfo.originalValues]; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:newRecordTableHash]; + [parentConnection->dirtyRecordTableInfoDict setObject:newDirtyRecordTableInfo forKey:newRecordTableHash]; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Utilities - MappingTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (id )mappingTableInfoForRowid:(int64_t)rowid cacheResult:(BOOL)cacheResult +{ + YDBLogAutoTrace(); + + NSNumber *rowidNumber = @(rowid); + YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo = nil; + YDBCKCleanMappingTableInfo *cleanMappingTableInfo = nil; + + // Check dirtyMappingTableInfo (modified info) + + dirtyMappingTableInfo = [parentConnection->dirtyMappingTableInfoDict objectForKey:rowidNumber]; + if (dirtyMappingTableInfo) { + return dirtyMappingTableInfo; + } + + // Check cleanMappingTableInfo (cache) + + cleanMappingTableInfo = [parentConnection->cleanMappingTableInfoCache objectForKey:rowidNumber]; + if (cleanMappingTableInfo) + { + if (cleanMappingTableInfo == (id)[NSNull null]) + return nil; + else + return cleanMappingTableInfo; + } + + // Fetch from disk + + sqlite3_stmt *statement = [parentConnection mappingTable_getInfoForRowidStatement]; + if (statement == NULL) { + return nil; + } + + // SELECT "recordTable_hash" FROM "mappingTableName" WHERE "rowid" = ?; + + int col_recordTable_hash = SQLITE_COL_START + 0; + int bind_rowid = SQLITE_BIND_START + 0; + + sqlite3_bind_int64(statement, bind_rowid, rowid); + + NSString *recordTable_hash = nil; + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + int textSize = sqlite3_column_bytes(statement, col_recordTable_hash); + if (textSize > 0) + { + const unsigned char *text = sqlite3_column_text(statement, col_recordTable_hash); + + recordTable_hash = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding]; + } + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'mappingTable_getInfoForRowidStatement': %d %s", + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + + if (recordTable_hash) + { + cleanMappingTableInfo = [[YDBCKCleanMappingTableInfo alloc] initWithRecordTableHash:recordTable_hash]; + + if (cacheResult){ + [parentConnection->cleanMappingTableInfoCache setObject:cleanMappingTableInfo forKey:rowidNumber]; + } + return cleanMappingTableInfo; + } + else + { + if (cacheResult) { + [parentConnection->cleanMappingTableInfoCache setObject:[NSNull null] forKey:rowidNumber]; + } + return nil; + } +} + +/** + * This method is called from handleRemoveObjectsForKeys:inCollection:withRowids:. + * + * It's used to fetch all the mappingTableInfo items for all the given rowids. + * This information is used in order to determine which rowids are mapped to a CKRecords (in the record table). +**/ +- (NSDictionary *)mappingTableInfoForRowids:(NSArray *)rowids +{ + YDBLogAutoTrace(); + + NSUInteger rowidsCount = rowids.count; + + if (rowidsCount == 0) return nil; + if (rowidsCount == 1) { + + int64_t rowid = [[rowids firstObject] longLongValue]; + id mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:NO]; + + if (mappingTableInfo) + return @{ @(rowid) : mappingTableInfo }; + else + return nil; + } + + NSMutableDictionary *foundRowids = [NSMutableDictionary dictionaryWithCapacity:rowidsCount]; + NSMutableArray *remainingRowids = [NSMutableArray arrayWithCapacity:rowidsCount]; + + for (NSNumber *rowidNumber in rowids) + { + YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo = nil; + YDBCKCleanMappingTableInfo *cleanMappingTableInfo = nil; + + // Check dirtyMappingTableInfo (modified info) + + dirtyMappingTableInfo = [parentConnection->dirtyMappingTableInfoDict objectForKey:rowidNumber]; + if (dirtyMappingTableInfo) + { + [foundRowids setObject:dirtyMappingTableInfo forKey:rowidNumber]; + continue; + } + + // Check cleanMappingTableInfo (cache) + + cleanMappingTableInfo = [parentConnection->cleanMappingTableInfoCache objectForKey:rowidNumber]; + if (cleanMappingTableInfo) + { + if (cleanMappingTableInfo != (id)[NSNull null]) + { + [foundRowids setObject:cleanMappingTableInfo forKey:rowidNumber]; + } + + continue; + } + + // Need to fetch from disk + + [remainingRowids addObject:rowidNumber]; + } + + NSUInteger count = [remainingRowids count]; + if (count > 0) + { + sqlite3 *db = databaseTransaction->connection->db; + + // Note: + // The handleRemoveObjectsForKeys:inCollection:withRowids: has the following guarantee: + // count <= (SQLITE_LIMIT_VARIABLE_NUMBER - 1) + // + // So we don't have to worry about sqlite's upper bound on host parameters. + + // SELECT "recordTable_hash" FROM "mappingTableName" WHERE "rowid" IN (?, ?, ...); + + NSUInteger capacity = 100 + (count * 3); + NSMutableString *query = [NSMutableString stringWithCapacity:capacity]; + + [query appendString:@"SELECT \"rowid\", \"recordTable_hash\""]; + [query appendFormat:@" FROM \"%@\" WHERE \"rowid\" IN (", [self mappingTableName]]; + + int col_rowid = SQLITE_COL_START + 0; + int col_recordTable_hash = SQLITE_COL_START + 1; + + for (NSUInteger i = 0; i < count; i++) + { + if (i == 0) + [query appendFormat:@"?"]; + else + [query appendFormat:@", ?"]; + } + + [query appendString:@");"]; + + sqlite3_stmt *statement; + int status; + + status = sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ (%@): Error creating statement\n" + @" - status(%d), errmsg: %s\n" + @" - query: %@", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db), query); + + return foundRowids; + } + + for (NSUInteger i = 0; i < count; i++) + { + int64_t rowid = [[remainingRowids objectAtIndex:i] longLongValue]; + + sqlite3_bind_int64(statement, (int)(SQLITE_BIND_START + i), rowid); + } + + while ((status = sqlite3_step(statement)) == SQLITE_ROW) + { + int64_t rowid = 0; + NSString *recordTable_hash = nil; + + rowid = sqlite3_column_int64(statement, col_rowid); + + int textLen = sqlite3_column_bytes(statement, col_recordTable_hash); + const unsigned char *text = sqlite3_column_text(statement, col_recordTable_hash); + + recordTable_hash = [[NSString alloc] initWithBytes:text length:textLen encoding:NSUTF8StringEncoding]; + + if (recordTable_hash) + { + YDBCKCleanMappingTableInfo *cleanMappingTableInfo = + [[YDBCKCleanMappingTableInfo alloc] initWithRecordTableHash:recordTable_hash]; + + [foundRowids setObject:cleanMappingTableInfo forKey:@(rowid)]; + } + } + + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ (%@): Error executing statement: %d %s", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db)); + } + + sqlite3_finalize(statement); + } + + return foundRowids; +} + +- (void)insertOrUpdateMappingTableRowWithRowid:(int64_t)rowid info:(YDBCKDirtyMappingTableInfo *)dirtyMappingTableInfo +{ + if (dirtyMappingTableInfo.clean_recordTable_hash == nil) + { + // Insert row + + NSAssert(dirtyMappingTableInfo.dirty_recordTable_hash != nil, @"Logic error"); + + sqlite3_stmt *statement = [parentConnection mappingTable_insertStatement]; + if (statement == NULL) { + return; + } + + // INSERT OR REPLACE INTO "mappingTableName" ("rowid", "recordTable_hash") VALUES (?, ?); + + int bind_rowid = SQLITE_BIND_START + 0; + int bind_recordTable_hash = SQLITE_BIND_START + 1; + + sqlite3_bind_int64(statement, bind_rowid, rowid); + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, dirtyMappingTableInfo.dirty_recordTable_hash); + sqlite3_bind_text(statement, bind_recordTable_hash, _hash.str, _hash.length, SQLITE_STATIC); + + YDBLogVerbose(@"Inserting 1 row in mapping table with rowid(%lld)...", rowid); + + int status = sqlite3_step(statement); + if (status == SQLITE_ERROR) + { + YDBLogError(@"%@ - Error executing statement (insert): %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + } + else + { + // Update row + + NSAssert(dirtyMappingTableInfo.dirty_recordTable_hash != nil, @"Logic error"); + + sqlite3_stmt *statement = [parentConnection mappingTable_updateForRowidStatement]; + if (statement == NULL) { + return; + } + + // UPDATE "mappingTableName" SET "recordTable_hash" = ? WHERE "rowid" = ?; + + int bind_recordTable_hash = SQLITE_BIND_START + 0; + int bind_rowid = SQLITE_BIND_START + 1; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, dirtyMappingTableInfo.dirty_recordTable_hash); + sqlite3_bind_text(statement, bind_recordTable_hash, _hash.str, _hash.length, SQLITE_STATIC); + + sqlite3_bind_int64(statement, bind_rowid, rowid); + + YDBLogVerbose(@"Updating 1 row in mapping table with rowid(%lld)...", rowid); + + int status = sqlite3_step(statement); + if (status == SQLITE_ERROR) + { + YDBLogError(@"%@ - Error executing statement (insert): %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + } +} + +- (void)removeMappingTableRowWithRowid:(int64_t)rowid +{ + sqlite3_stmt *statement = [parentConnection mappingTable_removeForRowidStatement]; + if (statement == NULL) { + return; + } + + // DELETE FROM "mappingTableName" WHERE "rowid" = ?; + + int bind_rowid = SQLITE_BIND_START + 0; + + sqlite3_bind_int64(statement, bind_rowid, rowid); + + YDBLogVerbose(@"Deleting 1 row from mapping table with rowid(%lld)...", rowid); + + int status = sqlite3_step(statement); + if (status == SQLITE_ERROR) + { + YDBLogError(@"%@ - Error executing statement (remove): %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); +} + +- (void)removeAllMappingTableRows +{ + YDBLogAutoTrace(); + + sqlite3_stmt *statement = [parentConnection mappingTable_removeAllStatement]; + if (statement == NULL) { + return; + } + + // DELETE FROM "mappingTableName"; + + YDBLogVerbose(@"Deleting all rows from mapping table..."); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_reset(statement); +} + +/** + * Uses the index on the 'recordTable_hash' column to find associated rowids. + * And also takes into account pending changes to the mapping table via dirtyMappingTableInfoDict. +**/ +- (NSSet *)mappingTableRowidsForRecordTableHash:(NSString *)hash +{ + sqlite3_stmt *statement = [parentConnection mappingTable_enumerateForHashStatement]; + if (statement == NULL) { + return nil; + } + + __block NSMutableSet *rowids = nil; + + // SELECT "rowid" FROM "mappingTableName" WHERE "recordTable_hash" = ?; + + int col_rowid = SQLITE_COL_START + 0; + int bind_hash = SQLITE_BIND_START + 0; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + int status; + while ((status = sqlite3_step(statement)) == SQLITE_ROW) + { + int64_t rowid = sqlite3_column_int64(statement, col_rowid); + + if (rowids == nil) { + rowids = [NSMutableSet setWithCapacity:1]; + } + [rowids addObject:@(rowid)]; + } + + if (status != SQLITE_DONE) + { + YDBLogError(@"Error executing 'getKeyCountForCollectionStatement': %d %s", + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + [parentConnection->dirtyMappingTableInfoDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + __unsafe_unretained NSNumber *rowidNumber = (NSNumber *)key; + __unsafe_unretained YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo = (YDBCKDirtyMappingTableInfo *)obj; + + if ([hash isEqualToString:dirtyMappingTableInfo.clean_recordTable_hash]) + { + if (![hash isEqualToString:dirtyMappingTableInfo.dirty_recordTable_hash]) + { + // Mapping is scheduled to be removed + [rowids removeObject:rowidNumber]; + } + } + else if ([hash isEqualToString:dirtyMappingTableInfo.dirty_recordTable_hash]) + { + // Mapping is scheduled to be added + + if (rowids == nil) { + rowids = [NSMutableSet setWithCapacity:1]; + } + [rowids addObject:rowidNumber]; + } + }]; + + return rowids; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Utilities - RecordTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This method returns one of the following instance types: + * + * - YDBCKCleanRecordTableInfo + * - YDBCKDirtyRecordTableInfo + * - nil + * + * The caller must inspect the class type of the returned object. +**/ +- (id )recordTableInfoForHash:(NSString *)hash cacheResult:(BOOL)cacheResult +{ + YDBLogAutoTrace(); + + if (hash == nil) return nil; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = nil; + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = nil; + + // Check dirtyRecordTableInfo (modified records) + + dirtyRecordTableInfo = [parentConnection->dirtyRecordTableInfoDict objectForKey:hash]; + if (dirtyRecordTableInfo) { + return dirtyRecordTableInfo; + } + + // Check cleanRecordTableInfo (cache) + + cleanRecordTableInfo = [parentConnection->cleanRecordTableInfoCache objectForKey:hash]; + if (cleanRecordTableInfo) + { + if (cleanRecordTableInfo == (id)[NSNull null]) + return nil; + else + return cleanRecordTableInfo; + } + + // Fetch from disk + + sqlite3_stmt *statement = [parentConnection recordTable_getInfoForHashStatement]; + if (statement == NULL) { + return nil; + } + + // SELECT "databaseIdentifier", "ownerCount", "record" FROM "recordTableName" WHERE "hash" = ?; + + int col_databaseIdentifier = SQLITE_COL_START + 0; + int col_ownerCount = SQLITE_COL_START + 1; + int col_record = SQLITE_COL_START + 2; + + int bind_hash = SQLITE_BIND_START + 0; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + NSString *databaseIdentifier = nil; + int64_t ownerCount = 0; + CKRecord *record = nil; + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + int textSize; + + textSize = sqlite3_column_bytes(statement, col_databaseIdentifier); + if (textSize > 0) + { + const unsigned char *text = sqlite3_column_text(statement, col_databaseIdentifier); + databaseIdentifier = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding]; + } + + ownerCount = sqlite3_column_int64(statement, col_ownerCount); + + const void *blob = sqlite3_column_blob(statement, col_record); + int blobSize = sqlite3_column_bytes(statement, col_record); + + // Performance tuning: + // Use dataWithBytesNoCopy to avoid an extra allocation and memcpy. + + NSData *data = [NSData dataWithBytesNoCopy:(void *)blob length:blobSize freeWhenDone:NO]; + + record = [YDBCKRecord deserializeRecord:data]; + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'recordTable_getInfoForHashStatement': %d %s", + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + if (record) + { + cleanRecordTableInfo = + [[YDBCKCleanRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + ownerCount:ownerCount + record:record]; + + if (cacheResult){ + [parentConnection->cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:hash]; + } + return cleanRecordTableInfo; + } + else + { + if (cacheResult) { + [parentConnection->cleanRecordTableInfoCache setObject:[NSNull null] forKey:hash]; + } + return nil; + } +} + +/** + * This method is called from handleRemoveObjectsForKeys:inCollection:withRowids:. + * + * It's used to fetch all the recordInfo items for all the given rowids. + * This information is used in order to determine which rowids have associated CKRecords, + * and should be deleted (locally and possibly from the cloud too). +**/ +- (NSDictionary *)recordTableInfoForHashes:(NSArray *)hashes +{ + NSUInteger hashesCount = hashes.count; + + if (hashesCount == 0) return nil; + if (hashesCount == 1) { + + NSString *hash = [hashes firstObject]; + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:NO]; + + if (recordTableInfo) + return @{ hash : recordTableInfo }; + else + return nil; + } + + NSMutableDictionary *foundHashes = [NSMutableDictionary dictionaryWithCapacity:[hashes count]]; + NSMutableArray *remainingHashes = [NSMutableArray arrayWithCapacity:[hashes count]]; + + for (NSString *hash in hashes) + { + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = nil; + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = nil; + + // Check dirtyRecordTableInfo (modified records) + + dirtyRecordTableInfo = [parentConnection->dirtyRecordTableInfoDict objectForKey:hash]; + if (dirtyRecordTableInfo) + { + [foundHashes setObject:dirtyRecordTableInfo forKey:hash]; + continue; + } + + // Check cleanRecordTableInfo (cache) + + cleanRecordTableInfo = [parentConnection->cleanRecordTableInfoCache objectForKey:hash]; + if (cleanRecordTableInfo) + { + if (cleanRecordTableInfo != (id)[NSNull null]) + { + [foundHashes setObject:cleanRecordTableInfo forKey:hash]; + } + + continue; + } + + // Need to fetch from disk + + [remainingHashes addObject:hash]; + } + + NSUInteger count = [remainingHashes count]; + if (count > 0) + { + sqlite3 *db = databaseTransaction->connection->db; + + // Note: + // The handleRemoveObjectsForKeys:inCollection:withRowids: has the following guarantee: + // count <= (SQLITE_LIMIT_VARIABLE_NUMBER - 1) + // + // So we don't have to worry about sqlite's upper bound on host parameters. + + // SELECT "hash", "databaseIdentifier", "ownerCount", "record" FROM "recordTableName" + // WHERE "hash" IN (?, ?, ...); + + NSUInteger capacity = 100 + (count * 3); + NSMutableString *query = [NSMutableString stringWithCapacity:capacity]; + + [query appendString: + @"SELECT \"hash\", \"databaseIdentifier\", \"ownerCount\", \"record\""]; + [query appendFormat:@" FROM \"%@\" WHERE \"hash\" IN (", [self recordTableName]]; + + int col_hash = SQLITE_COL_START + 0; + int col_databaseIdentifier = SQLITE_COL_START + 1; + int col_ownerCount = SQLITE_COL_START + 2; + int col_record = SQLITE_COL_START + 3; + + for (NSUInteger i = 0; i < count; i++) + { + if (i == 0) + [query appendFormat:@"?"]; + else + [query appendFormat:@", ?"]; + } + + [query appendString:@");"]; + + sqlite3_stmt *statement; + int status; + + status = sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ (%@): Error creating statement\n" + @" - status(%d), errmsg: %s\n" + @" - query: %@", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db), query); + + return foundHashes; + } + + for (NSUInteger i = 0; i < count; i++) + { + NSString *hash = [remainingHashes objectAtIndex:i]; + + sqlite3_bind_text(statement, (int)(SQLITE_BIND_START + i), [hash UTF8String], -1, SQLITE_TRANSIENT); + } + + while ((status = sqlite3_step(statement)) == SQLITE_ROW) + { + NSString *hash = nil; + NSString *databaseIdentifier = nil; + int64_t ownerCount = 0; + CKRecord *record = nil; + + int textLen; + const unsigned char *text; + + textLen = sqlite3_column_bytes(statement, col_hash); + text = sqlite3_column_text(statement, col_hash); + + hash = [[NSString alloc] initWithBytes:text length:textLen encoding:NSUTF8StringEncoding]; + + textLen = sqlite3_column_bytes(statement, col_databaseIdentifier); + if (textLen > 0) + { + text = sqlite3_column_text(statement, col_databaseIdentifier); + databaseIdentifier = [[NSString alloc] initWithBytes:text length:textLen encoding:NSUTF8StringEncoding]; + } + + ownerCount = sqlite3_column_int64(statement, col_ownerCount); + + const void *blob = sqlite3_column_blob(statement, col_record); + int blobSize = sqlite3_column_bytes(statement, col_record); + + // Performance tuning: + // Use dataWithBytesNoCopy to avoid an extra allocation and memcpy. + + NSData *data = [NSData dataWithBytesNoCopy:(void *)blob length:blobSize freeWhenDone:NO]; + record = [YDBCKRecord deserializeRecord:data]; + + if (record) + { + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + [[YDBCKCleanRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + ownerCount:ownerCount + record:record]; + + [foundHashes setObject:cleanRecordTableInfo forKey:hash]; + } + } + + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ (%@): Error executing statement: %d %s", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db)); + } + + sqlite3_finalize(statement); + } + + return foundHashes; +} + +/** + * Inserts the given dirtyRecordTableInfo into the recordTable. + * + * Returns a corresponding row that needs to be inserted into the recordKeysTable. + * The caller is responsible for inserting the recordKeysRow. +**/ +- (void)insertRecordTableRowWithHash:(NSString *)hash + info:(YDBCKDirtyRecordTableInfo *)dirtyRecordTableInfo + outSanitizedRecord:(CKRecord **)outSanitizedRecord +{ + YDBLogAutoTrace(); + + NSParameterAssert(hash != nil); + NSParameterAssert(dirtyRecordTableInfo != nil); + + NSAssert(dirtyRecordTableInfo.dirty_record != nil, @"Logic error"); + NSAssert(dirtyRecordTableInfo.dirty_ownerCount > 0, @"Logic error"); + + // Update recordKeys table + + sqlite3_stmt *statement = [parentConnection recordTable_insertStatement]; + if (statement == NULL) + { + if (outSanitizedRecord) *outSanitizedRecord = nil; + return; + } + + // INSERT OR REPLACE INTO "recordTableName" + // ("hash", "databaseIdentifier", "ownerCount", "record") VALUES (?, ?, ?, ?, ?); + + int bind_hash = SQLITE_BIND_START + 0; + int bind_databaseIdentifier = SQLITE_BIND_START + 1; + int bind_ownerCount = SQLITE_BIND_START + 2; + int bind_record = SQLITE_BIND_START + 3; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + YapDatabaseString _dbID; MakeYapDatabaseString(&_dbID, dirtyRecordTableInfo.databaseIdentifier); + if (dirtyRecordTableInfo.databaseIdentifier) + sqlite3_bind_text(statement, bind_databaseIdentifier, _dbID.str, _dbID.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_databaseIdentifier); + + sqlite3_bind_int64(statement, bind_ownerCount, dirtyRecordTableInfo.dirty_ownerCount); + + __attribute__((objc_precise_lifetime)) NSData *recordBlob = + [YDBCKRecord serializeRecord:dirtyRecordTableInfo.dirty_record]; + sqlite3_bind_blob(statement, bind_record, recordBlob.bytes, (int)recordBlob.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + FreeYapDatabaseString(&_dbID); + + if (outSanitizedRecord) { + CKRecord *sanitizedRecord = [YDBCKRecord deserializeRecord:recordBlob]; + *outSanitizedRecord = sanitizedRecord; + } +} + +/** + * Updates the metadata column(s) (ownerCount) for the record IF NEEDED. + * + * Returns a corresponding row that needs to be inserted into the recordKeysTable. + * The caller is responsible for inserting the recordKeysRow. +**/ +- (void)maybeUpdateRecordTableRowWithHash:(NSString *)hash + info:(YDBCKDirtyRecordTableInfo *)dirtyRecordTableInfo +{ + YDBLogAutoTrace(); + + NSParameterAssert(hash != nil); + NSParameterAssert(dirtyRecordTableInfo != nil); + + NSAssert(dirtyRecordTableInfo.dirty_record != nil, @"Logic error"); + NSAssert(dirtyRecordTableInfo.dirty_ownerCount > 0, @"Logic error"); + + BOOL ownerCountChanged = dirtyRecordTableInfo.ownerCountChanged; + + if (ownerCountChanged) + { + sqlite3_stmt *statement = [parentConnection recordTable_updateOwnerCountStatement]; + if (statement == NULL) { + return; + } + + // UPDATE "recordTableName" SET "ownerCount" = ? WHERE "hash" = ?; + + int bind_ownerCount = SQLITE_BIND_START + 0; + int bind_hash = SQLITE_BIND_START + 1; + + sqlite3_bind_int64(statement, bind_ownerCount, dirtyRecordTableInfo.dirty_ownerCount); + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement (A): %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + } +} + +- (void)updateRecordTableRowWithHash:(NSString *)hash + record:(CKRecord *)record + outSanitizedRecord:(CKRecord **)outSanitizedRecord +{ + YDBLogAutoTrace(); + + NSParameterAssert(hash != nil); + NSParameterAssert(record != nil); + + // Update record table + + sqlite3_stmt *statement = [parentConnection recordTable_updateRecordStatement]; + if (statement == NULL) + { + if (outSanitizedRecord) *outSanitizedRecord = nil; + return; + } + + // UPDATE "recordTableName" SET "record" = ? WHERE "hash" = ?; + + int bind_record = SQLITE_BIND_START + 0; + int bind_hash = SQLITE_BIND_START + 1; + + __attribute__((objc_precise_lifetime)) NSData *recordBlob = [YDBCKRecord serializeRecord:record]; + sqlite3_bind_blob(statement, bind_record, recordBlob.bytes, (int)recordBlob.length, SQLITE_STATIC); + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement (A): %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + if (outSanitizedRecord) { + CKRecord *sanitizedRecord = [YDBCKRecord deserializeRecord:recordBlob]; + *outSanitizedRecord = sanitizedRecord; + } +} + +- (void)removeRecordTableRowWithHash:(NSString *)hash +{ + YDBLogAutoTrace(); + + if (hash == nil) { + YDBLogWarn(@"%@ - Invalid parameter: hash == nil", THIS_METHOD); + return; + } + + sqlite3_stmt *statement = [parentConnection recordTable_removeForHashStatement]; + if (statement == NULL) { + return; + } + + // DELETE FROM "recordTableName" WHERE "hash" = ?; + + int bind_hash = SQLITE_BIND_START + 0; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + YDBLogVerbose(@"Deleting 1 row from record table with hash(%@)...", hash); + + int status = sqlite3_step(statement); + if (status == SQLITE_ERROR) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); +} + +/** + * This method is invoked from flushPendingChangesToExtensionTables. + * The given hashes are an summation of all the rows that have been deleted throughout this tranaction. +**/ +/* +- (void)removeRecordTableRowsWithHashes:(NSArray *)hashes +{ + YDBLogAutoTrace(); + + NSUInteger hashesCount = [hashes count]; + + if (hashesCount == 0) return; + if (hashesCount == 1) + { + [self removeRecordTableRowWithHash:[hashes firstObject]]; + return; + } + + sqlite3 *db = databaseTransaction->connection->db; + + NSUInteger maxHostParams = (NSUInteger) sqlite3_limit(db, SQLITE_LIMIT_VARIABLE_NUMBER, -1); + + NSUInteger offset = 0; + do + { + NSUInteger left = hashesCount - offset; + NSUInteger numParams = MIN(left, maxHostParams); + + // DELETE FROM "recordTableName" WHERE "hash" IN (?, ?, ...); + + NSUInteger capacity = 60 + (numParams * 3); + NSMutableString *query = [NSMutableString stringWithCapacity:capacity]; + + [query appendFormat:@"DELETE FROM \"%@\" WHERE \"rowid\" IN (", [self recordTableName]]; + + for (NSUInteger i = 0; i < numParams; i++) + { + if (i == 0) + [query appendFormat:@"?"]; + else + [query appendFormat:@", ?"]; + } + + [query appendString:@");"]; + + sqlite3_stmt *statement; + int status; + + status = sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ (%@): Error creating statement\n" + @" - status(%d), errmsg: %s\n" + @" - query: %@", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db), query); + + return; + } + + for (NSUInteger i = 0; i < numParams; i++) + { + NSString *hash = [hashes objectAtIndex:i]; + + sqlite3_bind_text(statement, (int)(i + 1), [hash UTF8String], -1, SQLITE_TRANSIENT); + } + + YDBLogVerbose(@"Deleting %lu rows from records table...", (unsigned long)numParams); + + status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ (%@): Error executing statement: %d %s", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db)); + } + + sqlite3_finalize(statement); + statement = NULL; + + offset += numParams; + + } while (offset < hashesCount); + +} +*/ + +- (void)removeAllRecordTableRows +{ + YDBLogAutoTrace(); + + sqlite3_stmt *statement = [parentConnection recordTable_removeAllStatement]; + if (statement == NULL) { + return; + } + + // DELETE FROM "recordTableName"; + + YDBLogVerbose(@"Deleting all rows from records table..."); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_reset(statement); +} + +- (BOOL)getOwnerCount:(int64_t *)ownerCountPtr fromDiskForHash:(NSString *)hash +{ + if (hash == nil) { + if (ownerCountPtr) *ownerCountPtr = 0; + return NO; + } + + sqlite3_stmt *statement = [parentConnection recordTable_getOwnerCountForHashStatement]; + if (statement == NULL) { + if (ownerCountPtr) *ownerCountPtr = 0; + return NO; + } + + // SELECT "ownerCount" FROM "recordTableName" WHERE "hash" = ?; + + int col_ownerCount = SQLITE_COL_START + 0; + int bind_hash = SQLITE_BIND_START + 0; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + BOOL found = NO; + int64_t ownerCount = 0; + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + found = YES; + ownerCount = sqlite3_column_int64(statement, col_ownerCount); + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'recordTable_getInfoForHashStatement': %d %s", + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + if (ownerCountPtr) *ownerCountPtr = ownerCount; + return found; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Utilities - QueueTable +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Invoke this method with the NEW changeSets from the pendingQueue (pendingQueue.newChangeSets). +**/ +- (void)insertQueueTableRowWithChangeSet:(YDBCKChangeSet *)changeSet +{ + YDBLogAutoTrace(); + + sqlite3_stmt *statement = [parentConnection queueTable_insertStatement]; + if (statement == NULL) { + return; + } + + // INSERT INTO "queueTableName" + // ("uuid", "prev", "databaseIdentifier", "deletedRecordIDs", "modifiedRecords") VALUES (?, ?, ?, ?, ?); + + int bind_uuid = SQLITE_BIND_START + 0; + int bind_prev = SQLITE_BIND_START + 1; + int bind_dbid = SQLITE_BIND_START + 2; + int bind_deletedRecordIDs = SQLITE_BIND_START + 3; + int bind_modifiedRecords = SQLITE_BIND_START + 4; + + YapDatabaseString _uuid; MakeYapDatabaseString(&_uuid, changeSet.uuid); + sqlite3_bind_text(statement, bind_uuid, _uuid.str, _uuid.length, SQLITE_STATIC); + + YapDatabaseString _prev; MakeYapDatabaseString(&_prev, changeSet.prev); + sqlite3_bind_text(statement, bind_prev, _prev.str, _prev.length, SQLITE_STATIC); + + YapDatabaseString _dbid; MakeYapDatabaseString(&_dbid, changeSet.databaseIdentifier); + if (changeSet.databaseIdentifier) + sqlite3_bind_text(statement, bind_dbid, _dbid.str, _dbid.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_dbid); + + __attribute__((objc_precise_lifetime)) NSData *blob1 = [changeSet serializeDeletedRecordIDs]; + if (blob1) + sqlite3_bind_blob(statement, bind_deletedRecordIDs, blob1.bytes, (int)blob1.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_deletedRecordIDs); + + __attribute__((objc_precise_lifetime)) NSData *blob2 = [changeSet serializeModifiedRecords]; + if (blob2) + sqlite3_bind_blob(statement, bind_modifiedRecords, blob2.bytes, (int)blob2.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_modifiedRecords); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_uuid); + FreeYapDatabaseString(&_prev); + FreeYapDatabaseString(&_dbid); +} + +/** + * Invoke this method with OLDER changeSets from the pendingQueue that have changes we need to write to the DB. +**/ +- (void)updateQueueTableRowWithChangeSet:(YDBCKChangeSet *)changeSet +{ + YDBLogAutoTrace(); + + NSAssert(changeSet.hasChangesToDeletedRecordIDs || changeSet.hasChangesToModifiedRecords, + @"Method expected modified changeSet !"); + + if (changeSet.hasChangesToDeletedRecordIDs && !changeSet.hasChangesToModifiedRecords) + { + // Update column(s): + // - deletedRecordIDs + + sqlite3_stmt *statement = [parentConnection queueTable_updateDeletedRecordIDsStatement]; + if (statement == NULL) { + return; + } + + // UPDATE "queueTableName" SET "deletedRecordIDs" = ? WHERE "uuid" = ?; + + int bind_deletedRecordIDs = SQLITE_BIND_START + 0; + int bind_uuid = SQLITE_BIND_START + 1; + + __attribute__((objc_precise_lifetime)) NSData *blob = [changeSet serializeDeletedRecordIDs]; + if (blob) + sqlite3_bind_blob(statement, bind_deletedRecordIDs, blob.bytes, (int)blob.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_deletedRecordIDs); + + YapDatabaseString _uuid; MakeYapDatabaseString(&_uuid, changeSet.uuid); + sqlite3_bind_text(statement, bind_uuid, _uuid.str, _uuid.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_uuid); + } + else if (!changeSet.hasChangesToDeletedRecordIDs && changeSet.hasChangesToModifiedRecords) + { + // Update column(s): + // - modifiedRecords + + sqlite3_stmt *statement = [parentConnection queueTable_updateModifiedRecordsStatement]; + if (statement == NULL) { + return; + } + + // UPDATE "queueTableName" SET "modifiedRecords" = ? WHERE "uuid" = ?; + + int bind_modifiedRecords = SQLITE_BIND_START + 0; + int bind_uuid = SQLITE_BIND_START + 1; + + __attribute__((objc_precise_lifetime)) NSData *blob = [changeSet serializeModifiedRecords]; + if (blob) + sqlite3_bind_blob(statement, bind_modifiedRecords, blob.bytes, (int)blob.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_modifiedRecords); + + YapDatabaseString _uuid; MakeYapDatabaseString(&_uuid, changeSet.uuid); + sqlite3_bind_text(statement, bind_uuid, _uuid.str, _uuid.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_uuid); + } + else if (changeSet.hasChangesToDeletedRecordIDs && changeSet.hasChangesToModifiedRecords) + { + // Update column(s): + // - deletedRecordIDs + // - modifiedRecords + + sqlite3_stmt *statement = [parentConnection queueTable_updateBothStatement]; + if (statement == NULL) { + return; + } + + // UPDATE "queueTableName" SET "deletedRecordIDs" = ?, "modifiedRecords" = ? WHERE "uuid" = ?; + + int bind_deletedRecordIDs = SQLITE_BIND_START + 0; + int bind_modifiedRecods = SQLITE_BIND_START + 1; + int bind_uuid = SQLITE_BIND_START + 2; + + __attribute__((objc_precise_lifetime)) NSData *drBlob = [changeSet serializeDeletedRecordIDs]; + if (drBlob) + sqlite3_bind_blob(statement, bind_deletedRecordIDs, drBlob.bytes, (int)drBlob.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_deletedRecordIDs); + + __attribute__((objc_precise_lifetime)) NSData *mrBlob = [changeSet serializeModifiedRecords]; + if (mrBlob) + sqlite3_bind_blob(statement, bind_modifiedRecods, mrBlob.bytes, (int)mrBlob.length, SQLITE_STATIC); + else + sqlite3_bind_null(statement, bind_modifiedRecods); + + YapDatabaseString _uuid; MakeYapDatabaseString(&_uuid, changeSet.uuid); + sqlite3_bind_text(statement, bind_uuid, _uuid.str, _uuid.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_uuid); + } +} + +/** + * This method is invoked by [YapDatabaseCloudKit handleCompletedOperation:withSavedRecords:]. +**/ +- (void)removeQueueTableRowWithUUID:(NSString *)uuid +{ + YDBLogAutoTrace(); + + // Execute that sqlite statement. + + sqlite3_stmt *statement = [parentConnection queueTable_removeForUuidStatement]; + if (statement == NULL) { + return; + } + + // DELETE FROM "queueTableName" WHERE "uuid" = ?; + + int bind_uuid = SQLITE_BIND_START + 0; + + YapDatabaseString _uuid; MakeYapDatabaseString(&_uuid, uuid); + sqlite3_bind_text(statement, bind_uuid, _uuid.str, _uuid.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_uuid); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Completion +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)handlePartiallyCompletedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)savedRecords + deletedRecordIDs:(NSArray *)deletedRecordIDs +{ + YDBLogAutoTrace(); + + // Proper API usage check + if (!databaseTransaction->isReadWriteTransaction) + { + @throw [self requiresReadWriteTransactionException:NSStringFromSelector(_cmd)]; + return; + } + + // Step 1 of 6: + // + // Mark this transaction as an operationPartialCompletionTransaction. + // This is handled a little differently from a regular (user-initiated) transaction. + + parentConnection->isOperationPartialCompletionTransaction = YES; + + // Step 2 of 6: + // + // Update recordsTable & recordsCache for any records that were saved. + // We need to store the new system fields of the CKRecord. + + for (CKRecord *record in savedRecords) + { + NSString *hash = [self hashRecordID:record.recordID databaseIdentifier:changeSet.databaseIdentifier]; + + CKRecord *sanitizedRecord = nil; + [self updateRecordTableRowWithHash:hash + record:record + outSanitizedRecord:&sanitizedRecord]; + + if (sanitizedRecord) + { + YDBCKCleanRecordTableInfo *cleanRecordTableInfo; + + cleanRecordTableInfo = [parentConnection->cleanRecordTableInfoCache objectForKey:hash]; + if (cleanRecordTableInfo) + { + cleanRecordTableInfo = [cleanRecordTableInfo cleanCopyWithSanitizedRecord:sanitizedRecord]; + + [parentConnection->cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:hash]; + } + else + { + int64_t ownerCount = 0; + [self getOwnerCount:&ownerCount fromDiskForHash:hash]; + + cleanRecordTableInfo = + [[YDBCKCleanRecordTableInfo alloc] initWithDatabaseIdentifier:changeSet.databaseIdentifier + ownerCount:ownerCount + record:sanitizedRecord]; + } + + if (parentConnection->changeset_recordTableInfo == nil) { + parentConnection->changeset_recordTableInfo = [NSMutableDictionary dictionary]; + } + [parentConnection->changeset_recordTableInfo setObject:cleanRecordTableInfo forKey:hash]; + } + else + { + if (parentConnection->changeset_deletedHashes == nil) { + parentConnection->changeset_deletedHashes = [NSMutableSet set]; + } + [parentConnection->changeset_deletedHashes addObject:hash]; + } + } + + // Step 3 of 6: + // + // Create a pendingQueue, + // and lock the masterQueue so we can make changes to it. + // + // Note: Creating a pendingQueue automatically locks the masterQueue. + + YDBCKChangeQueue *masterQueue = parentConnection->parent->masterQueue; + YDBCKChangeQueue *pendingQueue = [masterQueue newPendingQueue]; + + // Step 4 of 6: + // + // Update previous changeSets (if needed), including the inFlightChangeSet. + + for (CKRecord *savedRecord in savedRecords) + { + [masterQueue updatePendingQueue:pendingQueue + withSavedRecord:savedRecord + databaseIdentifier:changeSet.databaseIdentifier + isOpPartialCompletion:YES]; + } + + for (CKRecordID *deletedRecordID in deletedRecordIDs) + { + [masterQueue updatePendingQueue:pendingQueue + withSavedDeletedRecordID:deletedRecordID + databaseIdentifier:changeSet.databaseIdentifier]; + } + + // Step 5 of 6: + // + // Update queue table. + // This is the list of changes the pendingQueue gives us. + + for (YDBCKChangeSet *oldChangeSet in pendingQueue.changeSetsFromPreviousCommits) + { + if (oldChangeSet.hasChangesToDeletedRecordIDs || oldChangeSet.hasChangesToModifiedRecords) + { + [self updateQueueTableRowWithChangeSet:oldChangeSet]; + } + } + + // Step 6 of 6: + // + // Update the masterQueue, + // and unlock it so the next operation can be dispatched. + + [masterQueue mergePendingQueue:pendingQueue]; +} + +- (void)handleCompletedOperationWithChangeSet:(YDBCKChangeSet *)changeSet + savedRecords:(NSArray *)savedRecords + deletedRecordIDs:(NSArray *)deletedRecordIDs +{ + YDBLogAutoTrace(); + + // Proper API usage check + if (!databaseTransaction->isReadWriteTransaction) + { + @throw [self requiresReadWriteTransactionException:NSStringFromSelector(_cmd)]; + return; + } + + // Step 1 of 6: + // + // Mark this transaction as an operationCompletionTransaction. + // This is handled a little differently from a regular (user-initiated) transaction. + + parentConnection->isOperationCompletionTransaction = YES; + + // Step 2 of 6: + // + // Update recordsTable & recordsCache for any records that were saved. + // We need to store the new system fields of the CKRecord. + + for (CKRecord *record in savedRecords) + { + NSString *hash = [self hashRecordID:record.recordID databaseIdentifier:changeSet.databaseIdentifier]; + + CKRecord *sanitizedRecord = nil; + [self updateRecordTableRowWithHash:hash + record:record + outSanitizedRecord:&sanitizedRecord]; + + if (sanitizedRecord) + { + YDBCKCleanRecordTableInfo *cleanRecordTableInfo; + + cleanRecordTableInfo = [parentConnection->cleanRecordTableInfoCache objectForKey:hash]; + if (cleanRecordTableInfo) + { + cleanRecordTableInfo = [cleanRecordTableInfo cleanCopyWithSanitizedRecord:sanitizedRecord]; + + [parentConnection->cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:hash]; + } + else + { + int64_t ownerCount = 0; + [self getOwnerCount:&ownerCount fromDiskForHash:hash]; + + cleanRecordTableInfo = + [[YDBCKCleanRecordTableInfo alloc] initWithDatabaseIdentifier:changeSet.databaseIdentifier + ownerCount:ownerCount + record:sanitizedRecord]; + + [parentConnection->cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:hash]; + } + + if (parentConnection->changeset_recordTableInfo == nil) { + parentConnection->changeset_recordTableInfo = [NSMutableDictionary dictionary]; + } + [parentConnection->changeset_recordTableInfo setObject:cleanRecordTableInfo forKey:hash]; + } + else + { + if (parentConnection->changeset_deletedHashes == nil) { + parentConnection->changeset_deletedHashes = [NSMutableSet set]; + } + [parentConnection->changeset_deletedHashes addObject:hash]; + } + + } + + // Step 3 of 6: + // + // Create a pendingQueue, + // and lock the masterQueue so we can make changes to it. + // + // Note: Creating a pendingQueue automatically locks the masterQueue. + + YDBCKChangeQueue *masterQueue = parentConnection->parent->masterQueue; + YDBCKChangeQueue *pendingQueue = [masterQueue newPendingQueue]; + + // Step 4 of 6: + // + // Update previous changeSets (if needed). + // + // Note: There's no need to update the inFlightChangeSet. + // Since this operation completed successfully, we're just going to delete the inFlightChangeSet anyway. + + for (CKRecord *savedRecord in savedRecords) + { + [masterQueue updatePendingQueue:pendingQueue + withSavedRecord:savedRecord + databaseIdentifier:changeSet.databaseIdentifier + isOpPartialCompletion:NO]; + } + + // Step 5 of 6: + // + // Update queue table. + // This is the list of changes the pendingQueue gives us. + + for (YDBCKChangeSet *queuedChangeSet in pendingQueue.changeSetsFromPreviousCommits) + { + if (queuedChangeSet.hasChangesToDeletedRecordIDs || queuedChangeSet.hasChangesToModifiedRecords) + { + NSAssert(![queuedChangeSet.uuid isEqualToString:changeSet.uuid], @"Logic error"); + + [self updateQueueTableRowWithChangeSet:queuedChangeSet]; + } + } + + [self removeQueueTableRowWithUUID:changeSet.uuid]; + + // Step 6 of 6: + // + // Update the masterQueue, + // and unlock it so the next operation can be dispatched. + + [masterQueue mergePendingQueue:pendingQueue]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Cleanup & Commit +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Subclasses MUST implement this method. + * This method is only called if within a readwrite transaction. + * + * Subclasses should write any last changes to their database table(s) if needed, + * and should perform any needed cleanup before the changeset is requested. + * + * Remember, the changeset is requested immediately after this method is invoked. +**/ +- (void)flushPendingChangesToExtensionTables +{ + YDBLogAutoTrace(); + + if (parentConnection->isOperationCompletionTransaction) + { + // Nothing to do here. + // We already handled everything in + // 'handleCompletedOperationWithChangeSet:savedRecords:deletedRecordIDs:'. + return; + } + if (parentConnection->isOperationPartialCompletionTransaction) + { + // Nothing to do here. + // We already handled everything in + // 'handlePartiallyCompletedOperationWithChangeSet:savedRecords:deletedRecordIDs:' + return; + } + + if ((parentConnection->dirtyMappingTableInfoDict.count == 0) && + (parentConnection->dirtyRecordTableInfoDict.count == 0)) + { + // Nothing affecting YapDatabaseCloudKit was changed in this transaction. + return; + } + + // Step 1 of 6: + // + // Update mapping table. + + [parentConnection->dirtyMappingTableInfoDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + __unsafe_unretained NSNumber *rowidNumber = (NSNumber *)key; + __unsafe_unretained YDBCKDirtyMappingTableInfo *dirtyMappingTableInfo = (YDBCKDirtyMappingTableInfo *)obj; + + if (dirtyMappingTableInfo.dirty_recordTable_hash == nil) + { + [self removeMappingTableRowWithRowid:[rowidNumber longLongValue]]; + + if (parentConnection->changeset_deletedRowids == nil) + parentConnection->changeset_deletedRowids = [[NSMutableSet alloc] init]; + + [parentConnection->changeset_deletedRowids addObject:rowidNumber]; + } + else + { + [self insertOrUpdateMappingTableRowWithRowid:[rowidNumber longLongValue] info:dirtyMappingTableInfo]; + + YDBCKCleanMappingTableInfo *cleanMappingTableInfo = [dirtyMappingTableInfo cleanCopy]; + + if (parentConnection->changeset_mappingTableInfo == nil) + parentConnection->changeset_mappingTableInfo = [[NSMutableDictionary alloc] init]; + + [parentConnection->changeset_mappingTableInfo setObject:cleanMappingTableInfo forKey:rowidNumber]; + [parentConnection->cleanMappingTableInfoCache setObject:cleanMappingTableInfo forKey:rowidNumber]; + } + }]; + + // Step 2 of 6: + // + // Update record table. + + [parentConnection->dirtyRecordTableInfoDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + __unsafe_unretained NSString *hash = (NSString *)key; + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = (YDBCKDirtyRecordTableInfo *)obj; + + if ([dirtyRecordTableInfo hasNilRecordOrZeroOwnerCount]) + { + if (dirtyRecordTableInfo.clean_ownerCount <= 0) + { + // We were just updating CKRecords in the queue. + // We've already deleted/detached the CKRecord, so it's not in the record table. + } + else + { + [self removeRecordTableRowWithHash:hash]; + + if (parentConnection->changeset_deletedHashes == nil) + parentConnection->changeset_deletedHashes = [[NSMutableSet alloc] init]; + + [parentConnection->changeset_deletedHashes addObject:hash]; + } + } + else + { + CKRecord *sanitizedRecord = nil; + + if (dirtyRecordTableInfo.clean_ownerCount <= 0) + { + [self insertRecordTableRowWithHash:hash + info:dirtyRecordTableInfo + outSanitizedRecord:&sanitizedRecord]; + } + else + { + // There's no use in us writing the record to the database right now. + // We only write the system fields anyway, and they have not changed yet. + // They won't be changed until the corresponding CKModifyRecordsOperation completes. + // And it's at that point that we'll write the updated record to the database. + + sanitizedRecord = [dirtyRecordTableInfo.dirty_record sanitizedCopy]; + + // We may, however, need to update the metadata about the record. + // That is, the ownerCount value. + + [self maybeUpdateRecordTableRowWithHash:hash info:dirtyRecordTableInfo]; + } + + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + [dirtyRecordTableInfo cleanCopyWithSanitizedRecord:sanitizedRecord]; + + if (parentConnection->changeset_recordTableInfo == nil) + parentConnection->changeset_recordTableInfo = [[NSMutableDictionary alloc] init]; + + [parentConnection->changeset_recordTableInfo setObject:cleanRecordTableInfo forKey:hash]; + [parentConnection->cleanRecordTableInfoCache setObject:cleanRecordTableInfo forKey:hash]; + } + }]; + + // Step 3 of 6: + // + // Create a pendingQueue, + // and lock the masterQueue so we can make changes to it. + + YDBCKChangeQueue *masterQueue = parentConnection->parent->masterQueue; + YDBCKChangeQueue *pendingQueue = [masterQueue newPendingQueue]; + + // Step 4 of 6: + // + // Use YDBCKChangeQueue tools to generate a list of updates for the queue table. + + [parentConnection->dirtyRecordTableInfoDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + // __unsafe_unretained NSString *hash = (NSString *)key; + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = (YDBCKDirtyRecordTableInfo *)obj; + + if ([dirtyRecordTableInfo hasNilRecordOrZeroOwnerCount]) + { + // The CKRecord has been deleted via one of the following: + // + // - [transaction removeObjectForKey:inCollection:] + // - [[transaction ext:ck] deleteRecordForKey:inCollection] + // - [[transaction ext:ck] detachKey:inCollection] + // + // Note: In the detached scenario, the user wants us to "detach" the local row + // from its associated CKRecord, but not to actually delete the CKRecord from the cloud. + + if (dirtyRecordTableInfo.clean_ownerCount <= 0 && + dirtyRecordTableInfo.dirty_record && + dirtyRecordTableInfo.remoteMerge) + { + // We were just updating CKRecords in the queue. + // We've already deleted/detached the CKRecord, so it's not in the record table. + + [masterQueue updatePendingQueue:pendingQueue + withMergedRecord:dirtyRecordTableInfo.dirty_record + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + else if (dirtyRecordTableInfo.remoteDeletion) + { + [masterQueue updatePendingQueue:pendingQueue + withRemoteDeletedRecordID:dirtyRecordTableInfo.recordID + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + else if (dirtyRecordTableInfo.skipUploadDeletion) + { + [masterQueue updatePendingQueue:pendingQueue + withDetachedRecordID:dirtyRecordTableInfo.recordID + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + else + { + [masterQueue updatePendingQueue:pendingQueue + withDeletedRecordID:dirtyRecordTableInfo.recordID + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + } + else + { + // The CKRecord has been modified via one or more of the following: + // + // - [transaction setObject:forKey:inCollection:] + // - [[transaction ext:ck] detachKey:inCollection:] + // - [[transaction ext:ck] attachRecord:forKey:inCollection:] + + if (dirtyRecordTableInfo.clean_ownerCount <= 0) + { + // Newly inserted record + + if (dirtyRecordTableInfo.remoteMerge) + { + [masterQueue updatePendingQueue:pendingQueue + withMergedRecord:dirtyRecordTableInfo.dirty_record + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + else if (dirtyRecordTableInfo.skipUploadRecord == NO) + { + [masterQueue updatePendingQueue:pendingQueue + withInsertedRecord:dirtyRecordTableInfo.dirty_record + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + } + else + { + // Modified record + + if (dirtyRecordTableInfo.remoteMerge) + { + [masterQueue updatePendingQueue:pendingQueue + withMergedRecord:dirtyRecordTableInfo.dirty_record + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier]; + } + else if (dirtyRecordTableInfo.skipUploadRecord == NO) + { + [masterQueue updatePendingQueue:pendingQueue + withModifiedRecord:dirtyRecordTableInfo.dirty_record + databaseIdentifier:dirtyRecordTableInfo.databaseIdentifier + originalValues:dirtyRecordTableInfo.originalValues]; + } + } + } + }]; + + // Step 5 of 6: + // + // Update queue table. + // This is the list of changes the pendingQueue gives us. + + for (YDBCKChangeSet *oldChangeSet in pendingQueue.changeSetsFromPreviousCommits) + { + if (oldChangeSet.hasChangesToDeletedRecordIDs || oldChangeSet.hasChangesToModifiedRecords) + { + [self updateQueueTableRowWithChangeSet:oldChangeSet]; + } + } + + for (YDBCKChangeSet *newChangeSet in pendingQueue.changeSetsFromCurrentCommit) + { + [self insertQueueTableRowWithChangeSet:newChangeSet]; + } + + // Step 6 of 6: + // + // Update the masterQueue, + // and unlock it so the next operation can be dispatched. + + [masterQueue mergePendingQueue:pendingQueue]; +} + +/** + * Required override method from YapDatabaseExtensionTransaction. +**/ +- (void)didCommitTransaction +{ + YDBLogAutoTrace(); + + // Forward to connection for further cleanup. + + [parentConnection postCommitCleanup]; + + // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. + // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, + // and then use it outside the context of the database transaction block. + // Thus, this code is here as a safety net to ensure that such accidental misuse doesn't do any damage. + + parentConnection = nil; // Do not remove ! + databaseTransaction = nil; // Do not remove ! +} + +/** + * Required override method from YapDatabaseExtensionTransaction. +**/ +- (void)didRollbackTransaction +{ + YDBLogAutoTrace(); + + // Forward to connection for further cleanup. + + [parentConnection postRollbackCleanup]; + + // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. + // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, + // and then use it outside the context of the database transaction block. + // Thus, this code is here as a safety net to ensure that such accidental misuse doesn't do any damage. + + parentConnection = nil; // Do not remove ! + databaseTransaction = nil; // Do not remove ! +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Transaction Hooks +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleInsertObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata + rowid:(int64_t)rowid +{ + YDBLogAutoTrace(); + + __unsafe_unretained NSString *collection = collectionKey.collection; + __unsafe_unretained NSString *key = collectionKey.key; + + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (allowedCollections && ![allowedCollections isAllowed:collection]) + { + return; + } + + // Check for pending attach request + + YDBCKAttachRequest *attachRequest = [parentConnection->pendingAttachRequests objectForKey:collectionKey]; + if (attachRequest) + { + CKRecord *record = attachRequest.record; + NSString *databaseIdentifier = attachRequest.databaseIdentifier; + + YDBCKProcessRecordBitMask flags = 0; + if (!attachRequest.shouldUploadRecord) + flags |= YDBCK_skipUploadRecord; + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.databaseIdentifier = databaseIdentifier; + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:nil + prevRecordTableInfo:nil + flags:flags]; + + [parentConnection->pendingAttachRequests removeObjectForKey:collectionKey]; + return; + } + + // Invoke the recordBlock. + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + CKRecord *record = nil; + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithKeyBlock recordBlock = + (YapDatabaseCloudKitRecordWithKeyBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key); + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, object); + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, metadata); + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, object, metadata); + } + + // Figure if anything changed, and schedule updates to the table(s) accordingly + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:nil + prevRecordTableInfo:nil + flags:0]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleUpdateObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata + rowid:(int64_t)rowid +{ + YDBLogAutoTrace(); + + __unsafe_unretained NSString *collection = collectionKey.collection; + __unsafe_unretained NSString *key = collectionKey.key; + + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (allowedCollections && ![allowedCollections isAllowed:collection]) + { + return; + } + + if (rowidsInMidMerge && [rowidsInMidMerge containsObject:@(rowid)]) + { + // Ignore - we're in the middle of a merge block + return; + } + + // Fetch current mappings & record information for the given rowid. + + id mappingTableInfo = nil; + id recordTableInfo = nil; + + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) { + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:YES]; + } + + CKRecord *record = nil; + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordTableInfo; + + record = [cleanRecordTableInfo.record safeCopy]; + } + else if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + record = dirtyRecordTableInfo.dirty_record; + } + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.databaseIdentifier = recordTableInfo.databaseIdentifier; + + // Invoke the recordBlock. + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithKeyBlock recordBlock = + (YapDatabaseCloudKitRecordWithKeyBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key); + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, object); + } + else if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, metadata); + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, object, metadata); + } + + // Figure if anything changed, and schedule updates to the table(s) accordingly + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleReplaceObject:(id)object forCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ + YDBLogAutoTrace(); + + __unsafe_unretained NSString *collection = collectionKey.collection; + __unsafe_unretained NSString *key = collectionKey.key; + + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (allowedCollections && ![allowedCollections isAllowed:collection]) + { + return; + } + + if (rowidsInMidMerge && [rowidsInMidMerge containsObject:@(rowid)]) + { + // Ignore - we're in the middle of a merge block + return; + } + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey || + recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata ) + { + // Nothing to do. + // The collection/key/metadata hasn't changed, so the CKRecord hasn't changed. + + return; + } + + // Fetch current mappings & record information for the given rowid. + + id mappingTableInfo = nil; + id recordTableInfo = nil; + + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) { + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:YES]; + } + + CKRecord *record = nil; + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordTableInfo; + + record = [cleanRecordTableInfo.record safeCopy]; + } + else if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + record = dirtyRecordTableInfo.dirty_record; + } + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.databaseIdentifier = recordTableInfo.databaseIdentifier; + + // Invoke the recordBlock. + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithObject) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithObjectBlock recordBlock = + (YapDatabaseCloudKitRecordWithObjectBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, object); + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + id metadata = [databaseTransaction metadataForCollectionKey:collectionKey withRowid:rowid]; + + recordBlock(&record, recordInfo, collection, key, object, metadata); + } + + // Figure if anything changed, and schedule updates to the table(s) accordingly + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleReplaceMetadata:(id)metadata forCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ + YDBLogAutoTrace(); + + __unsafe_unretained NSString *collection = collectionKey.collection; + __unsafe_unretained NSString *key = collectionKey.key; + + YapWhitelistBlacklist *allowedCollections = parentConnection->parent->options.allowedCollections; + + if (allowedCollections && ![allowedCollections isAllowed:collection]) + { + return; + } + + if (rowidsInMidMerge && [rowidsInMidMerge containsObject:@(rowid)]) + { + // Ignore - we're in the middle of a merge block + return; + } + + YapDatabaseCloudKitBlockType recordBlockType = parentConnection->parent->recordBlockType; + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithKey || + recordBlockType == YapDatabaseCloudKitBlockTypeWithObject ) + { + // Nothing to do. + // The collection/key/object hasn't changed, so the CKRecord hasn't changed. + + return; + } + + // Fetch current mappings & record information for the given rowid. + + id mappingTableInfo = nil; + id recordTableInfo = nil; + + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) { + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:YES]; + } + + CKRecord *record = nil; + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordTableInfo; + + record = [cleanRecordTableInfo.record safeCopy]; + } + else if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + record = dirtyRecordTableInfo.dirty_record; + } + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.databaseIdentifier = recordTableInfo.databaseIdentifier; + + // Invoke the recordBlock. + + if (recordBlockType == YapDatabaseCloudKitBlockTypeWithMetadata) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithMetadataBlock recordBlock = + (YapDatabaseCloudKitRecordWithMetadataBlock)parentConnection->parent->recordBlock; + + recordBlock(&record, recordInfo, collection, key, metadata); + } + else // if (recordBlockType == YapDatabaseCloudKitBlockTypeWithRow) + { + __unsafe_unretained YapDatabaseCloudKitRecordWithRowBlock recordBlock = + (YapDatabaseCloudKitRecordWithRowBlock)parentConnection->parent->recordBlock; + + id object = [databaseTransaction objectForCollectionKey:collectionKey withRowid:rowid]; + + recordBlock(&record, recordInfo, collection, key, object, metadata); + } + + // Figure if anything changed, and schedule updates to the table(s) accordingly + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleTouchObjectForCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ + // Nothing to do here. + // "Touch" is generally meant for local operations. + // + // We may add an explicit "remote" touch (declared in YapDatabaseCloudKitTransaction.h) + // in the future if there seems to be a need for it. +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleTouchMetadataForCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ + // Nothing to do here. + // "Touch" is generally meant for local operations. + // + // We may add an explicit "remote" touch (declared in YapDatabaseCloudKitTransaction.h) + // in the future if there seems to be a need for it. +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleRemoveObjectForCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ + YDBLogAutoTrace(); + + // Fetch current mappings & record information for the given rowid. + + id mappingTableInfo = nil; + id recordTableInfo = nil; + + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) { + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:YES]; + } + + [self processRecord:nil recordInfo:nil + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleRemoveObjectsForKeys:(NSArray *)keys inCollection:(NSString *)collection withRowids:(NSArray *)rowids +{ + YDBLogAutoTrace(); + + // Fetch a dictionary of valid rowids with the format: + // + // key = rowid (NSNumber) + // value = id (YDBCKCleanMappingTableInfo || YDBCKDirtyMappingTableInfo) + + NSDictionary *mappingTableInfoDict = [self mappingTableInfoForRowids:rowids]; + + NSMutableSet *hashes = [NSMutableSet setWithCapacity:[mappingTableInfoDict count]]; + for (id mappingTableInfo in [mappingTableInfoDict objectEnumerator]) + { + [hashes addObject:mappingTableInfo.current_recordTable_hash]; + } + + NSDictionary *recordTableInfoDict = [self recordTableInfoForHashes:[hashes allObjects]]; + + [mappingTableInfoDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + + __unsafe_unretained NSNumber *rowidNumber = (NSNumber *)key; + __unsafe_unretained id mappingTableInfo = (id )obj; + + int64_t rowid = [rowidNumber longLongValue]; + + id recordTableInfo = + [recordTableInfoDict objectForKey:mappingTableInfo.current_recordTable_hash]; + + [self processRecord:nil recordInfo:nil + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:0]; + }]; +} + +/** + * YapDatabase extension hook. + * This method is invoked by a YapDatabaseReadWriteTransaction as a post-operation-hook. +**/ +- (void)handleRemoveAllObjectsInAllCollections +{ + YDBLogAutoTrace(); + + [self removeAllMappingTableRows]; + [self removeAllRecordTableRows]; + + [parentConnection->cleanMappingTableInfoCache removeAllObjects]; + [parentConnection->cleanRecordTableInfoCache removeAllObjects]; + + [parentConnection->dirtyMappingTableInfoDict removeAllObjects]; + [parentConnection->dirtyRecordTableInfoDict removeAllObjects]; + + parentConnection->reset = YES; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Public API +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * This method is used to associate an existing CKRecord with a row in the database. + * There are two primary use cases for this method. + * + * 1. To associate a discovered/pulled CKRecord with a row in the database before you insert it the row. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a record that was inserted by another device. + * - You need to add a corresponding row to the database, + * but you also need to inform the YapDatabaseCloudKit extension about the existing record, + * so it won't bother invoking the recordHandler, or attempting to upload the existing record. + * - So you invoke this method FIRST. + * - And THEN you insert the corresponding object into the database via the + * normal setObject:forKey:inCollection: method (or similar methods). + * + * 2. To assist in the migration process when switching to YapDatabaseCloudKit. + * In particular, for the following situation: + * + * - You've been handling CloudKit manually (not via YapDatabaseCloudKit). + * - And you now want YapDatabaseCloudKit to manage the CKRecord for you. + * - So you can invoke this method for an object that already exists in the database, + * OR you can invoke this method FIRST, and then insert the new object that you want linked to the record. + * + * Thus, this method works as a simple "hand-off" of the CKRecord to the YapDatabaseCloudKit extension. + * + * In other words, YapDatbaseCloudKit will write the system fields of the given CKRecord to its internal table, + * and associate it with the given collection/key tuple. + * + * @param record + * The CKRecord to associate with the collection/key tuple. + * + * @param databaseIdentifer + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * @param key + * The key of the row to associate the record with. + * + * @param collection + * The collection of the row to associate the record with. + * + * @param shouldUpload + * If NO, then the record is simply associated with the collection/key, + * and YapDatabaseCloudKit doesn't attempt to push the record to the cloud. + * If YES, then the record is associated with the collection/key, + * and YapDatabaseCloutKit assumes the given record is dirty and will push the record to the cloud. + * + * @return + * YES if the record was associated with the given collection/key. + * NO if one of the following errors occurred. + * + * The following errors will prevent this method from succeeding: + * - The given record is nil. + * - The given collection/key is already associated with a different record (so must detach it first). + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (BOOL)attachRecord:(CKRecord *)inRecord + databaseIdentifier:(NSString *)databaseIdentifier + forKey:(NSString *)key + inCollection:(NSString *)collection + shouldUploadRecord:(BOOL)shouldUploadRecord +{ + YDBLogAutoTrace(); + + // Proper API usage check + if (!databaseTransaction->isReadWriteTransaction) + { + @throw [self requiresReadWriteTransactionException:NSStringFromSelector(_cmd)]; + return NO; + } + + // Sanity checks + + if (inRecord == nil) { + return NO; + } + if (key == nil) { + return NO; + } + + CKRecord *record = nil; + if (shouldUploadRecord) + record = inRecord; + else + record = [inRecord sanitizedCopy]; + + // Check for attachedRecord that hasn't been inserted into the database yet. + + int64_t rowid = 0; + if (![databaseTransaction getRowid:&rowid forKey:key inCollection:collection]) + { + YapCollectionKey *collectionKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; + + YDBCKAttachRequest *attachRequest; + + attachRequest = [[YDBCKAttachRequest alloc] init]; + attachRequest.record = record; + attachRequest.databaseIdentifier = databaseIdentifier; + attachRequest.shouldUploadRecord = shouldUploadRecord; + + if (parentConnection->pendingAttachRequests == nil) + parentConnection->pendingAttachRequests = [[NSMutableDictionary alloc] initWithCapacity:1]; + + [parentConnection->pendingAttachRequests setObject:attachRequest forKey:collectionKey]; + + return YES; + } + + // Handle attach (but make sure we're not overwriting an existing association) + + NSString *hash = [self hashRecordID:record.recordID databaseIdentifier:databaseIdentifier]; + + id mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) + { + NSString *currentHash = mappingTableInfo.current_recordTable_hash; + + if (currentHash && ![currentHash isEqualToString:hash]) + { + // The collection/key is already associated with an existing record. + // You must detach it first. + // + // @see detachRecordForKey:inCollection:wasRemoteDeletion:shouldUploadDeletion: + + return NO; + } + } + + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + YDBCKProcessRecordBitMask flags = 0; + if (!shouldUploadRecord) flags |= YDBCK_skipUploadRecord; + + YDBCKRecordInfo *recordInfo = [[YDBCKRecordInfo alloc] init]; + recordInfo.databaseIdentifier = databaseIdentifier; + + [self processRecord:record recordInfo:recordInfo + preCalculatedHash:hash + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:flags]; + + return YES; +} + +/** + * This method is used to unassociate an existing CKRecord with a row in the database. + * There are three primary use cases for this method. + * + * 1. To properly handle CKRecordID's that are reported as deleted from the server. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a recordID that was deleted by another device. + * - You need to remove the associated record from the database, + * but you also need to inform the YapDatabaseCloudKit extension that it was remotely deleted, + * so it won't bother attempting to upload the already deleted recordID. + * - So you invoke this method FIRST. + * - And THEN you can remove the corresponding object from the database via the + * normal removeObjectForKey:inCollection: method (or similar methods) (if needed). + * + * 2. To assist in various migrations, such as version migrations. + * For example: + * + * - In version 2 of your app, you need to move a few CKRecords into a new zone. + * - But you don't want to delete the items from the old zone, + * because you need to continue supporting v1.X for awhile. + * - So you invoke this method first in order to drop the previous record association(s). + * - And then you can attach the new CKRecord(s), + * and have YapDatabaseCloudKit upload the new records (to their new zone). + * + * 3. To "move" an object from the cloud to "local-only". + * For example: + * + * - You're making a Notes app that allows user to stores notes locally, or in the cloud. + * - The user moves an existing note from the cloud, to local-only storage. + * - This method can be used to delete the item from the cloud without deleting it locally. + * + * @param key + * The key of the row associated with the record to detach. + * + * @param collection + * The collection of the row associated with the record to detach. + * + * @param wasRemoteDeletion + * Did the server notify you of a deleted CKRecordID? + * Then make sure you set this parameter to YES. + * This allows the extension to properly modify any changeSets that are still queued for upload + * so that it can remove potential modifications for this recordID. + * + * Note: If a record was deleted remotely, and the record was associated with MULTIPLE items in the database, + * then you should be sure to invoke this method for each attached collection/key. + * + * @param shouldUpload + * Whether or not the extension should push a deleted CKRecordID to the cloud. + * In use case #2 (from the above discussion, concerning migration), you'd pass NO. + * In use case #3 (from the above discussion, concerning moving), you'd pass YES. + * This parameter is ignored if wasRemoteDeletion is YES (in which it will force shouldUpload to be NO). + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. + * + * @see getKey:collection:forRecordID:databaseIdentifier: +**/ +- (void)detachRecordForKey:(NSString *)key + inCollection:(NSString *)collection + wasRemoteDeletion:(BOOL)wasRemoteDeletion + shouldUploadDeletion:(BOOL)shouldUploadDeletion +{ + YDBLogAutoTrace(); + + // Proper API usage check + if (!databaseTransaction->isReadWriteTransaction) + { + @throw [self requiresReadWriteTransactionException:NSStringFromSelector(_cmd)]; + return; + } + + int64_t rowid; + if (![databaseTransaction getRowid:&rowid forKey:key inCollection:collection]) + { + YDBLogWarn(@"%@ - No row in database with given collection/key: %@, %@", THIS_METHOD, collection, key); + return; + } + + id mappingTableInfo = nil; + id recordTableInfo = nil; + + mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:NO]; + recordTableInfo = [self recordTableInfoForHash:mappingTableInfo.current_recordTable_hash cacheResult:NO]; + + YDBCKProcessRecordBitMask flags = 0; + if (wasRemoteDeletion) flags |= YDBCK_remoteDeletion; + if (!shouldUploadDeletion) flags |= YDBCK_skipUploadDeletion; + + [self processRecord:nil recordInfo:nil + preCalculatedHash:nil + forRowid:rowid + withPrevMappingTableInfo:mappingTableInfo + prevRecordTableInfo:recordTableInfo + flags:flags]; +} + +/** + * This method is used to merge a pulled record from the server with what's in the database. + * In particular, for the following situation: + * + * - You're pulling record changes from the server via CKFetchRecordChangesOperation (or similar). + * - You discover a record that was modified by another device. + * - You need to properly merge the changes with your own version of the object in the database, + * and you also need to inform YapDatabaseCloud extension about the merger + * so it can properly handle any changes that were pending a push to the cloud. + * + * Thus, you should use this method, which will invoke your mergeBlock with the appropriate parameters. + * + * @param remoteRecord + * A record that was modified remotely, and discovered via CKFetchRecordChangesOperation (or similar). + * This value will be passed as the remoteRecord parameter to the mergeBlock. + * + * @param databaseIdentifier + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (void)mergeRecord:(CKRecord *)remoteRecord databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + // Proper API usage check + if (!databaseTransaction->isReadWriteTransaction) + { + @throw [self requiresReadWriteTransactionException:NSStringFromSelector(_cmd)]; + return; + } + + if (remoteRecord == nil) + { + YDBLogWarn(@"%@ - Unable to merge a nil record! Did you mean to detach the recordID?", THIS_METHOD); + return; + } + + CKRecordID *recordID = remoteRecord.recordID; + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + BOOL isInRecordTable = YES; + + if (recordTableInfo == nil) + { + // The given record is not managed by YapDatabseCloudKit. + isInRecordTable = NO; + } + else if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + if ([dirtyRecordTableInfo hasNilRecordOrZeroOwnerCount]) + { + // The given record is no longer managed by YapDatabaseCloudKit. + // (scheduled for removal during commit processing) + isInRecordTable = NO; + } + } + + if (!isInRecordTable) + { + // The given record is not currently managed by YapDatabaseCloudKit. + // However ... it's possible we still have this record in the queue. + // For example: + // - User modified record + // - Then user deleted/detached record + // - Then the modification didn't upload to the server due to partial error. + // - And the user is merging the latest version of the record now. + // + // So if the record exists in our queue, we have to update it (one way or another), + // or we'll be stuck on this changeSet forever. + + BOOL hasPendingModification = NO; + [parentConnection->parent->masterQueue getHasPendingModification:&hasPendingModification + hasPendingDelete:NULL + forRecordID:recordID + databaseIdentifier:databaseIdentifier]; + + if (!hasPendingModification) + { + return; + } + } + + // Make sanitized copy of the remoteRecord. + // Sanitized == copy of the system fields only, without any values. + + YDBCKMergeInfo *mergeInfo = [[YDBCKMergeInfo alloc] init]; + mergeInfo.pendingLocalRecord = [remoteRecord sanitizedCopy]; + + // And then infuse the pendingLocalRecord with any key/value pairs that are pending upload. + // + // First we start with any previous commits (records that are sitting in the queue, awaiting upload to server) + + BOOL hasPendingChanges = + [parentConnection->parent->masterQueue mergeChangesForRecordID:recordID + databaseIdentifier:databaseIdentifier + into:mergeInfo]; + + // And then we check changes from this readWriteTransaction, just in case. + + if (isInRecordTable) + { + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + [parentConnection->dirtyRecordTableInfoDict objectForKey:hash]; + + if (dirtyRecordTableInfo) + { + [mergeInfo mergeNewerRecord:dirtyRecordTableInfo.dirty_record + newerOriginalValues:dirtyRecordTableInfo.originalValues]; + + hasPendingChanges = YES; + } + } + + // Invoke the mergeBlock on any associated collection/key + + __unsafe_unretained YapDatabaseCloudKitMergeBlock mergeBlock = parentConnection->parent->mergeBlock; + __unsafe_unretained YapDatabaseReadWriteTransaction *rwTransaction = + (YapDatabaseReadWriteTransaction *)databaseTransaction; + + mergeInfo.updatedPendingLocalRecord = [remoteRecord sanitizedCopy]; + if (!hasPendingChanges) { + mergeInfo.pendingLocalRecord = nil; + } + + if (isInRecordTable) + { + rowidsInMidMerge = [self mappingTableRowidsForRecordTableHash:hash]; + for (NSNumber *rowidNumber in rowidsInMidMerge) + { + int64_t rowid = [rowidNumber longLongValue]; + YapCollectionKey *ck = [databaseTransaction collectionKeyForRowid:rowid]; + + mergeBlock(rwTransaction, ck.collection, ck.key, remoteRecord, mergeInfo); + } + + rowidsInMidMerge = nil; + } + else if (hasPendingChanges) + { + mergeBlock(rwTransaction, nil, nil, remoteRecord, mergeInfo); + } + + // Store the results + + if (recordTableInfo) + { + // Note: We need to use directly set dirty_record here. + // Because the updatedPendingLocalRecord has [baseRecord sanitizedRecord] as its base. + // And it also has any/all values from a previous dirty_record (that we want to keep). + + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordTableInfo; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = [cleanRecordTableInfo dirtyCopy]; + + dirtyRecordTableInfo.dirty_record = mergeInfo.updatedPendingLocalRecord; // see above note + dirtyRecordTableInfo.remoteMerge = YES; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:hash]; + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:hash]; + } + else // if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + dirtyRecordTableInfo.dirty_record = mergeInfo.updatedPendingLocalRecord; // see above note + dirtyRecordTableInfo.remoteMerge = YES; + } + } + else if (hasPendingChanges) + { + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + [[YDBCKDirtyRecordTableInfo alloc] initWithDatabaseIdentifier:databaseIdentifier + recordID:recordID + ownerCount:0]; + + dirtyRecordTableInfo.dirty_record = mergeInfo.updatedPendingLocalRecord; + dirtyRecordTableInfo.remoteMerge = YES; + + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:hash]; + } +} + +/** + * This method allows you to manually modify a CKRecord. + * + * This is useful for tasks such as migrations, debugging, and various one-off tasks during the development lifecycle. + * For example, you added a property to some on of your model classes in the database, + * but you forgot to add the code that creates the corresponding property in the CKRecord. + * So you might whip up some code that uses this method, and forces that property to get uploaded to the server + * for all the corresponding model objects that you already updated. + * + * Returns NO if the given recordID/databaseIdentifier is unknown. + * That is, such a record has not been given to YapDatabaseCloudKit (via the recordHandler), + * or has not previously been associated with a collection/key, + * or the record was deleted earlier in this transaction. + * + * Important: This method only works if within a readWriteTrasaction. + * Invoking this method from within a read-only transaction will throw an exception. +**/ +- (BOOL)saveRecord:(CKRecord *)record databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + if (record == nil) return NO; + + NSString *hash = [self hashRecordID:record.recordID databaseIdentifier:databaseIdentifier]; + + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + if (recordTableInfo == nil) + { + // The given record is not managed by YapDatabseCloudKit. + return NO; + } + + if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + if ([dirtyRecordTableInfo hasNilRecordOrZeroOwnerCount]) + { + // The given record is no longer managed by YapDatabaseCloudKit. + // (scheduled for removal during commit processing) + return NO; + } + } + + // Store the results (if needed) + + if ([record.changedKeys count] > 0) + { + if ([recordTableInfo isKindOfClass:[YDBCKCleanRecordTableInfo class]]) + { + __unsafe_unretained YDBCKCleanRecordTableInfo *cleanRecordTableInfo = + (YDBCKCleanRecordTableInfo *)recordTableInfo; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = [cleanRecordTableInfo dirtyCopy]; + + [self mergeChangedValuesFromRecord:record intoRecord:dirtyRecordTableInfo.dirty_record]; + + [parentConnection->cleanRecordTableInfoCache removeObjectForKey:hash]; + [parentConnection->dirtyRecordTableInfoDict setObject:dirtyRecordTableInfo forKey:hash]; + } + else // if ([recordTableInfo isKindOfClass:[YDBCKDirtyRecordTableInfo class]]) + { + __unsafe_unretained YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = + (YDBCKDirtyRecordTableInfo *)recordTableInfo; + + [self mergeChangedValuesFromRecord:record intoRecord:dirtyRecordTableInfo.dirty_record]; + } + } + + return YES; +} + +/** + * If the given recordID & databaseIdentifier are associated with a row in the database, + * then this method will return YES, and set the collectionPtr/keyPtr with the collection/key of the associated row. + * + * @param keyPtr (optional) + * If non-null, and this method returns YES, then the keyPtr will be set to the associated row's key. + * + * @param collectionPtr (optional) + * If non-null, and this method returns YES, then the collectionPtr will be set to the associated row's collection. + * + * @param recordID + * The CKRecordID to look for. + * + * @param databaseIdentifier + * The identifying string for the CKDatabase. + * @see YapDatabaseCloudKitDatabaseIdentifierBlock. + * + * @return + * YES if the given recordID & databaseIdentifier are associated with a row in the database. + * NO otherwise. + * + * + * Note: + * It's possible to associate multiple items in the database with a single CKRecord/databaseIdentifier. + * This is completely legal, and supported by YapDatabaseCloudKit extension. + * However, if you do this keep in mind that this method will only return 1 of the associated items. + * Further, which item it returns is not guaranteed, and may change between method invocations. + * So, in this particular case, you likely should be using 'collectionKeysForRecordID:databaseIdentifier:'. +**/ +- (BOOL)getKey:(NSString **)keyPtr collection:(NSString **)collectionPtr + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + if (recordID == nil) + { + if (keyPtr) *keyPtr = nil; + if (collectionPtr) *collectionPtr = nil; + return NO; + } + + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + NSSet *rowids = [self mappingTableRowidsForRecordTableHash:hash]; + + YapCollectionKey *ck = nil; + if (rowids.count > 0) + { + int64_t rowid = [[rowids anyObject] longLongValue]; + ck = [databaseTransaction collectionKeyForRowid:rowid]; + } + + if (keyPtr) *keyPtr = ck.key; + if (collectionPtr) *collectionPtr = ck.collection; + + return (ck != nil); +} + +/** + * It's possible to associate multiple items in the database with a single CKRecord/databaseIdentifier. + * This is completely legal, and supported by YapDatabaseCloudKit extension. + * + * This method returns an array of YapCollectionKey objects, + * each associated with the given recordID/databaseIdentifier. + * + * @see YapCollectionKey +**/ +- (NSArray *)collectionKeysForRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + if (recordID == nil) { + return nil; + } + + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + NSSet *rowids = [self mappingTableRowidsForRecordTableHash:hash]; + + NSUInteger count = rowids.count; + if (count == 0) { + return nil; + } + + NSMutableArray *collectionKeys = [NSMutableArray arrayWithCapacity:count]; + for (NSNumber *rowidNumber in rowids) + { + int64_t rowid = [rowidNumber longLongValue]; + + YapCollectionKey *ck = [databaseTransaction collectionKeyForRowid:rowid]; + if (ck) { + [collectionKeys addObject:ck]; + } + } + + return collectionKeys; +} + +/** + * If the given key/collection tuple is associated with a record, + * then this method returns YES, and sets the recordIDPtr & databaseIdentifierPtr accordingly. + * + * @param recordIDPtr (optional) + * If non-null, and this method returns YES, then the recordIDPtr will be set to the associated recordID. + * + * @param databaseIdentifierPtr (optional) + * If non-null, and this method returns YES, then the databaseIdentifierPtr will be set to the associated value. + * Keep in mind that nil is a valid databaseIdentifier, + * and is generally used to signify the defaultContainer/privateCloudDatabase. + * + * @param key + * The key of the row in the database. + * + * @param collection + * The collection of the row in the database. + * + * @return + * YES if the given collection/key is associated with a CKRecord. + * NO otherwise. +**/ +- (BOOL)getRecordID:(CKRecordID **)recordIDPtr + databaseIdentifier:(NSString **)databaseIdentifierPtr + forKey:(NSString *)key + inCollection:(NSString *)collection +{ + CKRecordID *recordID = nil; + NSString *databaseIdentifier = nil; + + int64_t rowid = 0; + if ([databaseTransaction getRowid:&rowid forKey:key inCollection:collection]) + { + id mappingTableInfo = [self mappingTableInfoForRowid:rowid cacheResult:YES]; + if (mappingTableInfo) + { + NSString *hash = mappingTableInfo.current_recordTable_hash; + + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + if (recordTableInfo) + { + recordID = recordTableInfo.current_record.recordID; + databaseIdentifier = recordTableInfo.databaseIdentifier; + } + } + } + + if (recordIDPtr) *recordIDPtr = recordID; + if (databaseIdentifierPtr) *databaseIdentifierPtr = databaseIdentifier; + + return (recordID != nil); +} + +/** + * Returns a copy of the CKRcord for the given recordID/databaseIdentifier. + * + * Keep in mind that YapDatabaseCloudKit stores ONLY the system fields of a CKRecord. + * That is, it does NOT store any key/value pairs. + * It only stores "system fields", which is the internal metadata that CloudKit uses to handle sync state. + * + * So if you invoke this method from within a read-only transaction, + * then you will receive a "base" CKRecord, which is really only useful for extracting "system field" metadata, + * such as the 'recordChangeTag'. + * + * If you invoke this method from within a read-write transaction, + * then you will receive the "base" CKRecord, along with any modifications that have been made to the CKRecord + * during the current read-write transaction. + * + * Also keep in mind that you are receiving a copy of the record which YapDatabaseCloudKit is using internally. + * If you intend to manually modify the CKRecord directly, + * then you need to save those changes back into YapDatabaseCloudKit via 'saveRecord:databaseIdentifier'. + * + * @see saveRecord:databaseIdentifier: +**/ +- (CKRecord *)recordForRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + if (recordID == nil) return nil; + + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + CKRecord *record = [recordTableInfo.current_record safeCopy]; + return record; +} + +/** + * Convenience method. + * Combines the following two methods into a single call: + * + * - getRecordID:databaseIdentifier:forKey:inCollection: + * - recordForRecordID:databaseIdentifier: + * + * @see recordForRecordID:databaseIdentifier: +**/ +- (CKRecord *)recordForKey:(NSString *)key inCollection:(NSString *)collection +{ + YDBLogAutoTrace(); + + CKRecordID *recordID = nil; + NSString *databaseIdentifier = nil; + + if ([self getRecordID:&recordID databaseIdentifier:&databaseIdentifier forKey:key inCollection:collection]) + { + return [self recordForRecordID:recordID databaseIdentifier:databaseIdentifier]; + } + + return nil; +} + +/** + * High performance lookup method, if you only need to know if YapDatabaseCloudKit has a + * record for the given recordID/databaseIdentifier. + * + * This method is much faster than invoking recordForRecordID:databaseIdentifier:, + * if you don't actually need the record. + * + * @return + * Whether or not YapDatabaseCloudKit is currently managing a record for the given recordID/databaseIdentifer. + * That is, whether or not there is currently one or more rows in the database attached to the CKRecord. +**/ +- (BOOL)containsRecordID:(CKRecordID *)recordID databaseIdentifier:(NSString *)databaseIdentifier +{ + YDBLogAutoTrace(); + + if (recordID == nil) + { + return NO; + } + + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + + YDBCKDirtyRecordTableInfo *dirtyRecordTableInfo = nil; + YDBCKCleanRecordTableInfo *cleanRecordTableInfo = nil; + + // Check dirtyRecordTableInfo (modified records) + + dirtyRecordTableInfo = [parentConnection->dirtyRecordTableInfoDict objectForKey:hash]; + if (dirtyRecordTableInfo) + { + if ([dirtyRecordTableInfo hasNilRecordOrZeroOwnerCount]) + return NO; + else + return YES; + } + + // Check cleanRecordTableInfo (cache) + + cleanRecordTableInfo = [parentConnection->cleanRecordTableInfoCache objectForKey:hash]; + if (cleanRecordTableInfo) + { + if (cleanRecordTableInfo == (id)[NSNull null]) + return NO; + else + return YES; + } + + // Fetch from disk + + sqlite3_stmt *statement = [parentConnection recordTable_getCountForHashStatement]; + if (statement == NULL) { + return NO; + } + + // SELECT COUNT(*) AS NumberOfRows FROM "recordTableName" WHERE "hash" = ?; + + int col_count = SQLITE_COL_START + 0; + int bind_hash = SQLITE_BIND_START + 0; + + YapDatabaseString _hash; MakeYapDatabaseString(&_hash, hash); + sqlite3_bind_text(statement, bind_hash, _hash.str, _hash.length, SQLITE_STATIC); + + int64_t count = 0; + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + count = sqlite3_column_int64(statement, col_count); + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"%@ - Error executing statement: %d %s", THIS_METHOD, + status, sqlite3_errmsg(databaseTransaction->connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_hash); + + return (count > 0); +} + +/** + * Use this method during CKFetchRecordChangesOperation.fetchRecordChangesCompletionBlock. + * The values returned by this method will help you determine how to process each reported changedRecord. + * + * @param outRecordChangeTag + * If YapDatabaseRecord is managing a record for the given recordID/databaseIdentifier, + * this this will be set to the local record.recordChangeTag value. + * Remember that CloudKit tells us about changes that we made. + * It doesn't do so via push notification, but it still does when we use a CKFetchRecordChangesOperation. + * Thus its advantageous for us to ignore our own changes. + * This can be done by comparing the changedRecord.recordChangeTag vs outRecordChangeTag. + * If they're the same, then we already have this CKRecord (this change) in our system, and we can ignore it. + * + * Note: Sometimes during development, we may screw up some merge operations. + * This may happen when we're changing our data model(s) and record. + * If this happens, you can ignore the recordChangeTag, + * and force another merge by invoking mergeRecord:databaseIdentifier: again. + * + * @param outPendingModifications + * Tells you if there are changes in the queue for the given recordID/databaseIdentifier. + * That is, whether or not this record has been modified, and we have modifications that are still + * pending upload to the CloudKit servers. + * If this value is YES, then you MUST invoke mergeRecord:databaseIdentifier:. + * + * Note: It's possible for this value to be YES, and for outRecordChangeTag to be nil. + * This may happen if the user modified a record, deleted it, and neither of these changes have hit the server yet. + * Thus YDBCK no longer actively manages the record, but it does have changes for it sitting in the queue. + * Failure to observe this value could result in an infinite loop: + * attempt upload, partial error, fetch changes, failure to invoke merge properly, attempt upload, partial error... + * + * @param outPendingDelete + * Tells you if there is a pending delete of the record in the queue. + * That is, if we deleted the item locally, and the delete operation is pending upload to the cloudKit server. + * If this value is YES, then you may not want to create a new database item for the record. +**/ +- (void)getRecordChangeTag:(NSString **)outRecordChangeTag + hasPendingModifications:(BOOL *)outPendingModifications + hasPendingDelete:(BOOL *)outPendingDelete + forRecordID:(CKRecordID *)recordID + databaseIdentifier:(NSString *)databaseIdentifier +{ + if (outRecordChangeTag) + { + NSString *hash = [self hashRecordID:recordID databaseIdentifier:databaseIdentifier]; + id recordTableInfo = [self recordTableInfoForHash:hash cacheResult:YES]; + + // Note: Record is internal, must remain immutable here. + // But since we're just extracting the recordChangeTag, we don't have to make a copy. + CKRecord *record = recordTableInfo.current_record; + *outRecordChangeTag = record.recordChangeTag; + } + + if (outPendingModifications || outPendingDelete) + { + BOOL pendingModifications = NO; + BOOL pendingDelete = NO; + + [parentConnection->parent->masterQueue getHasPendingModification:&pendingModifications + hasPendingDelete:&pendingDelete + forRecordID:recordID + databaseIdentifier:databaseIdentifier]; + + if (outPendingModifications) *outPendingModifications = pendingModifications; + if (outPendingDelete) *outPendingDelete = pendingDelete; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Exceptions +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (NSException *)requiresReadWriteTransactionException:(NSString *)methodName +{ + NSString *reason = [NSString stringWithFormat: + @"The method [YapDatabaseCloudKitTransaction %@] can only be used within a readWriteTransaction.", methodName]; + + return [NSException exceptionWithName:@"YapDatabaseCloudKit" reason:reason userInfo:nil]; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h new file mode 100644 index 0000000..66f744d --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.h @@ -0,0 +1,100 @@ +#import +#import + +#import "YDBCKRecordInfo.h" +#import "YDBCKMergeInfo.h" +#import "YapDatabaseTransaction.h" + + +/** + * Corresponds to the different type of blocks supported by the various extension subclasses. +**/ +typedef NS_ENUM(NSInteger, YapDatabaseCloudKitBlockType) { + YapDatabaseCloudKitBlockTypeWithKey = 1, + YapDatabaseCloudKitBlockTypeWithObject = 2, + YapDatabaseCloudKitBlockTypeWithMetadata = 3, + YapDatabaseCloudKitBlockTypeWithRow = 4 +}; + + +@interface YapDatabaseCloudKitRecordHandler : NSObject + +typedef id YapDatabaseCloudKitRecordBlock; // One of the YapDatabaseCloutKitGetRecordX types below. + +/** + * @param inOutRecordPtr + * + * @param recordInfo + * +**/ + +typedef void (^YapDatabaseCloudKitRecordWithKeyBlock) + (CKRecord **inOutRecordPtr, YDBCKRecordInfo *recordInfo, NSString *collection, NSString *key); +typedef void (^YapDatabaseCloudKitRecordWithObjectBlock) + (CKRecord **inOutRecordPtr, YDBCKRecordInfo *recordInfo, NSString *collection, NSString *key, id object); +typedef void (^YapDatabaseCloudKitRecordWithMetadataBlock) + (CKRecord **inOutRecordPtr, YDBCKRecordInfo *recordInfo, NSString *collection, NSString *key, id metadata); +typedef void (^YapDatabaseCloudKitRecordWithRowBlock) + (CKRecord **inOutRecordPtr, YDBCKRecordInfo *recordInfo, NSString *collection, NSString *key, id object, id metadata); + ++ (instancetype)withKeyBlock:(YapDatabaseCloudKitRecordWithKeyBlock)recordBlock; ++ (instancetype)withObjectBlock:(YapDatabaseCloudKitRecordWithObjectBlock)recordBlock; ++ (instancetype)withMetadataBlock:(YapDatabaseCloudKitRecordWithMetadataBlock)recordBlock; ++ (instancetype)withRowBlock:(YapDatabaseCloudKitRecordWithRowBlock)recordBlock; + +@property (nonatomic, strong, readonly) YapDatabaseCloudKitRecordBlock recordBlock; +@property (nonatomic, assign, readonly) YapDatabaseCloudKitBlockType recordBlockType; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Merge Block. +**/ +typedef void (^YapDatabaseCloudKitMergeBlock) + (YapDatabaseReadWriteTransaction *transaction, NSString *collection, NSString *key, + CKRecord *remoteRecord, YDBCKMergeInfo *mergeInfo); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * OperationError Block. + * + * ... +**/ +typedef void (^YapDatabaseCloudKitOperationErrorBlock) + (NSString *databaseIdentifier, NSError *operationError); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * DatabaseIdentifier Block. + * + * CloudKit supports multiple databases. + * There is the privateCloudDatabase & publicCloudDatabase of the defaultContainer. + * In addition to this, apps may be configured with access to other (non-default) containers. + * + * In order to properly support multiple databases, the DatabaseIdentifier block is used. + * Here's how it works: + * + * The recordHandler block is used to provide a CKRecord for a given row in the database. + * In addition to the CKRecord, you may also specify a 'databaseIdentifier' via the YDBCKRecordInfo parameter. + * If you specify a databaseIdentifier, then this method will be used in order to get an appropriate + * CKDatabase instance for the databaseIdentifier you specified. + * + * If you ONLY use [[CKContainer defaultContainer] privateCloudDatabase], + * then you do NOT need to specify a DatabaseIdentifierBlock. + * + * That is, if you never specify a databaseIdentifier for any records (you leave recordInfo.databaseIdentifier nil), + * then YapDatabaseCloudKit will assume & use [[CKContainer defaultContainer] privateCloudDatabase] for every CKRecord. + * + * However, if you intend to use any other CKDatabase, the you MUST provide a DatabaseIdentifierBlock. +**/ +typedef CKDatabase* (^YapDatabaseCloudKitDatabaseIdentifierBlock)(NSString *databaseIdentifier); diff --git a/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.m b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.m new file mode 100644 index 0000000..aae9e10 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/CloudKit/YapDatabaseCloudKitTypes.m @@ -0,0 +1,54 @@ +#import "YapDatabaseCloudKitTypes.h" +#import "YapDatabaseCloudKitPrivate.h" + + +@implementation YapDatabaseCloudKitRecordHandler + +@synthesize recordBlock = recordBlock; +@synthesize recordBlockType = recordBlockType; + ++ (instancetype)withKeyBlock:(YapDatabaseCloudKitRecordWithKeyBlock)recordBlock +{ + if (recordBlock == nil) return nil; + + YapDatabaseCloudKitRecordHandler *handler = [[YapDatabaseCloudKitRecordHandler alloc] init]; + handler->recordBlock = recordBlock; + handler->recordBlockType = YapDatabaseCloudKitBlockTypeWithKey; + + return handler; +} + ++ (instancetype)withObjectBlock:(YapDatabaseCloudKitRecordWithObjectBlock)recordBlock +{ + if (recordBlock == nil) return nil; + + YapDatabaseCloudKitRecordHandler *handler = [[YapDatabaseCloudKitRecordHandler alloc] init]; + handler->recordBlock = recordBlock; + handler->recordBlockType = YapDatabaseCloudKitBlockTypeWithObject; + + return handler; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseCloudKitRecordWithMetadataBlock)recordBlock +{ + if (recordBlock == nil) return nil; + + YapDatabaseCloudKitRecordHandler *handler = [[YapDatabaseCloudKitRecordHandler alloc] init]; + handler->recordBlock = recordBlock; + handler->recordBlockType = YapDatabaseCloudKitBlockTypeWithMetadata; + + return handler; +} + ++ (instancetype)withRowBlock:(YapDatabaseCloudKitRecordWithRowBlock)recordBlock +{ + if (recordBlock == nil) return nil; + + YapDatabaseCloudKitRecordHandler *handler = [[YapDatabaseCloudKitRecordHandler alloc] init]; + handler->recordBlock = recordBlock; + handler->recordBlockType = YapDatabaseCloudKitBlockTypeWithRow; + + return handler; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h index 989ffc9..8c6c4b0 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h @@ -10,6 +10,19 @@ static NSString *const changeset_key_filteringBlock = @"filteringBlock"; static NSString *const changeset_key_filteringBlockType = @"filteringBlockType"; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseViewFiltering () + ++ (instancetype)withBlock:(YapDatabaseViewFilteringBlock)block blockType:(YapDatabaseViewBlockType)blockType; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @interface YapDatabaseFilteredView () { @private diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h index ca5fb94..81d8b6d 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h @@ -16,34 +16,18 @@ * YapDatabaseFilteredView extension. * That is, you must first register the parentView, and then use that registered name here. * - * @param filteringBlock + * @param filtering * - * The filteringBlock type is one of the following typedefs: - * - YapDatabaseViewFilteringWithKeyBlock - * - YapDatabaseViewFilteringWithObjectBlock - * - YapDatabaseViewFilteringWithMetadataBlock - * - YapDatabaseViewFilteringWithRowBlock - * It allows you to filter items from this view that exist in the parent view. - * You should pick a block type that requires the minimum number of parameters that you need. + * The filteringBlock allows you to filter items from this view that exist in the parent view. + * There are multiple filteringBlock types that are supported. * - * @see YapDatabaseViewTypes.h for block type definition(s). + * @see YapDatabaseViewTypes.h for block type definitions. * - * @param filteringBlockType - * - * This parameter identifies the type of filtering block being used. - * It must be one of the following (and must match the filteringBlock being passed): - * - YapDatabaseViewBlockTypeWithKey - * - YapDatabaseViewBlockTypeWithObject - * - YapDatabaseViewBlockTypeWithMetadata - * - YapDatabaseViewBlockTypeWithRow - * - * @see YapDatabaseViewTypes.h for block type definition(s). - * - * @param tag + * @param versionTag * * The filteringBlock may be changed after the filteredView is created (see YapDatabaseFilteredViewTransaction). * This is often in association with user events. - * The tag helps to identify the filteringBlock being used. + * The versionTag helps to identify the filteringBlock being used. * During initialization of the view, the view will compare the passed tag to what it has stored from a previous * app session. If the tag matches, then the filteredView is already setup. Otherwise the view will automatically * flush its tables, and re-populate itself. @@ -54,28 +38,39 @@ **/ - (id)initWithParentViewName:(NSString *)viewName - filteringBlock:(YapDatabaseViewFilteringBlock)filteringBlock - filteringBlockType:(YapDatabaseViewBlockType)filteringBlockType; + filtering:(YapDatabaseViewFiltering *)filtering; + +- (id)initWithParentViewName:(NSString *)viewName + filtering:(YapDatabaseViewFiltering *)filtering + versionTag:(NSString *)versionTag; + +- (id)initWithParentViewName:(NSString *)viewName + filtering:(YapDatabaseViewFiltering *)filtering + versionTag:(NSString *)versionTag + options:(YapDatabaseViewOptions *)options; + - (id)initWithParentViewName:(NSString *)viewName filteringBlock:(YapDatabaseViewFilteringBlock)filteringBlock filteringBlockType:(YapDatabaseViewBlockType)filteringBlockType - versionTag:(NSString *)versionTag; +__attribute((deprecated("Use method initWithParentViewName:filtering: instead"))); - (id)initWithParentViewName:(NSString *)viewName filteringBlock:(YapDatabaseViewFilteringBlock)filteringBlock filteringBlockType:(YapDatabaseViewBlockType)filteringBlockType versionTag:(NSString *)versionTag - options:(YapDatabaseViewOptions *)options; +__attribute((deprecated("Use method initWithParentViewName:filtering:versionTag: instead"))); + +- (id)initWithParentViewName:(NSString *)viewName + filteringBlock:(YapDatabaseViewFilteringBlock)filteringBlock + filteringBlockType:(YapDatabaseViewBlockType)filteringBlockType + versionTag:(NSString *)versionTag + options:(YapDatabaseViewOptions *)options +__attribute((deprecated("Use method initWithParentViewName:filtering:versionTag:options: instead"))); @property (nonatomic, strong, readonly) NSString *parentViewName; @property (nonatomic, strong, readonly) YapDatabaseViewFilteringBlock filteringBlock; @property (nonatomic, assign, readonly) YapDatabaseViewBlockType filteringBlockType; -/** - * The options allow you to specify things like creating an IN-MEMORY-ONLY VIEW (non persistent). -**/ -@property (nonatomic, copy, readonly) YapDatabaseViewOptions *options; - @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m index 25ae623..6173356 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m @@ -28,12 +28,10 @@ #pragma mark Invalid -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType - versionTag:(NSString *)inVersionTag - options:(YapDatabaseViewOptions *)inOptions +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)inVersionTag + options:(YapDatabaseViewOptions *)inOptions { NSString *reason = @"You must use the init method(s) specific to YapDatabaseFilteredView."; @@ -52,49 +50,32 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (id)initWithParentViewName:(NSString *)inParentViewName - filteringBlock:(YapDatabaseViewFilteringBlock)inFilteringBlock - filteringBlockType:(YapDatabaseViewBlockType)inFilteringBlockType + filtering:(YapDatabaseViewFiltering *)filtering { - return [self initWithParentViewName:inParentViewName - filteringBlock:inFilteringBlock - filteringBlockType:inFilteringBlockType - versionTag:nil - options:nil]; + return [self initWithParentViewName:inParentViewName filtering:filtering versionTag:nil options:nil]; } - (id)initWithParentViewName:(NSString *)inParentViewName - filteringBlock:(YapDatabaseViewFilteringBlock)inFilteringBlock - filteringBlockType:(YapDatabaseViewBlockType)inFilteringBlockType + filtering:(YapDatabaseViewFiltering *)filtering versionTag:(NSString *)inVersionTag { - return [self initWithParentViewName:inParentViewName - filteringBlock:inFilteringBlock - filteringBlockType:inFilteringBlockType - versionTag:inVersionTag - options:nil]; + return [self initWithParentViewName:inParentViewName filtering:filtering versionTag:inVersionTag options:nil]; } - (id)initWithParentViewName:(NSString *)inParentViewName - filteringBlock:(YapDatabaseViewFilteringBlock)inFilteringBlock - filteringBlockType:(YapDatabaseViewBlockType)inFilteringBlockType + filtering:(YapDatabaseViewFiltering *)filtering versionTag:(NSString *)inVersionTag options:(YapDatabaseViewOptions *)inOptions { - NSAssert(inParentViewName != nil, @"Invalid parentViewName"); - NSAssert(inFilteringBlock != NULL, @"Invalid filteringBlock"); - - NSAssert(inFilteringBlockType == YapDatabaseViewBlockTypeWithKey || - inFilteringBlockType == YapDatabaseViewBlockTypeWithObject || - inFilteringBlockType == YapDatabaseViewBlockTypeWithMetadata || - inFilteringBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid filteringBlockType"); + NSAssert(inParentViewName != nil, @"Invalid parameter: parentViewName == nil"); + NSAssert(filtering != nil, @"Invalid parameter: filtering == nil"); if ((self = [super init])) { parentViewName = [inParentViewName copy]; - filteringBlock = inFilteringBlock; - filteringBlockType = inFilteringBlockType; + filteringBlock = filtering.filteringBlock; + filteringBlockType = filtering.filteringBlockType; versionTag = inVersionTag ? [inVersionTag copy] : @""; @@ -103,6 +84,57 @@ return self; } +/** + * DEPRECATED + * Use method initWithParentViewName:filtering: instead. +**/ +- (id)initWithParentViewName:(NSString *)inParentViewName + filteringBlock:(YapDatabaseViewFilteringBlock)inBlock + filteringBlockType:(YapDatabaseViewBlockType)inBlockType +{ + YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withBlock:inBlock blockType:inBlockType]; + + return [self initWithParentViewName:inParentViewName + filtering:filtering + versionTag:nil + options:nil]; +} + +/** + * DEPRECATED + * Use method initWithParentViewName:filtering:versionTag: instead. +**/ +- (id)initWithParentViewName:(NSString *)inParentViewName + filteringBlock:(YapDatabaseViewFilteringBlock)inBlock + filteringBlockType:(YapDatabaseViewBlockType)inBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withBlock:inBlock blockType:inBlockType]; + + return [self initWithParentViewName:inParentViewName + filtering:filtering + versionTag:inVersionTag + options:nil]; +} + +/** + * DEPRECATED + * Use method initWithParentViewName:filtering:versionTag:options: instead. +**/ +- (id)initWithParentViewName:(NSString *)inParentViewName + filteringBlock:(YapDatabaseViewFilteringBlock)inBlock + filteringBlockType:(YapDatabaseViewBlockType)inBlockType + versionTag:(NSString *)inVersionTag + options:(YapDatabaseViewOptions *)inOptions +{ + YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withBlock:inBlock blockType:inBlockType]; + + return [self initWithParentViewName:inParentViewName + filtering:filtering + versionTag:inVersionTag + options:inOptions]; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Custom Getters //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h index cd9e53f..7e6e48e 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h @@ -32,8 +32,12 @@ * * Note: You must pass a different versionTag, or this method does nothing. **/ +- (void)setFiltering:(YapDatabaseViewFiltering *)filtering + versionTag:(NSString *)tag; + - (void)setFilteringBlock:(YapDatabaseViewFilteringBlock)filteringBlock filteringBlockType:(YapDatabaseViewBlockType)filteringBlockType - versionTag:(NSString *)tag; + versionTag:(NSString *)tag +__attribute((deprecated("Use method setFiltering:versionTag: instead"))); @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m index e217c2d..5e2aae1 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m @@ -47,7 +47,11 @@ static NSString *const ExtKey_versionTag = @"versionTag"; // So we can skip all the checks because we know we need to create the memory tables. if (![self createTables]) return NO; - if (![self populateView]) return NO; + + if (!viewConnection->view->options.skipInitialViewPopulation) + { + if (![self populateView]) return NO; + } // Store initial versionTag in prefs table @@ -96,7 +100,7 @@ static NSString *const ExtKey_versionTag = @"versionTag"; // First time registration needsCreateTables = YES; - needsPopulateView = YES; + needsPopulateView = !viewConnection->view->options.skipInitialViewPopulation; } else if (oldClassVersion != classVersion) { @@ -104,7 +108,7 @@ static NSString *const ExtKey_versionTag = @"versionTag"; [self dropTablesForOldClassVersion:oldClassVersion]; needsCreateTables = YES; - needsPopulateView = YES; + needsPopulateView = YES; // Not initialViewPopulation, but rather codebase upgrade. } // Create the database tables (if needed) @@ -134,7 +138,7 @@ static NSString *const ExtKey_versionTag = @"versionTag"; if (![oldParentViewName isEqualToString:parentViewName]) { - needsPopulateView = YES; + needsPopulateView = YES; // Not initialViewPopulation, but rather config change. } // Check user-supplied tag. @@ -153,7 +157,7 @@ static NSString *const ExtKey_versionTag = @"versionTag"; if (![oldVersionTag isEqualToString:versionTag]) { - needsPopulateView = YES; + needsPopulateView = YES; // Not initialViewPopulation, but rather versionTag upgrade. } } @@ -1363,11 +1367,9 @@ static NSString *const ExtKey_versionTag = @"versionTag"; @implementation YapDatabaseFilteredViewTransaction (ReadWrite) -- (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock - groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock - sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType - versionTag:(NSString *)versionTag +- (void)setGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)versionTag { NSString *reason = @"This method is not available for YapDatabaseFilteredView."; @@ -1378,20 +1380,13 @@ static NSString *const ExtKey_versionTag = @"versionTag"; @throw [NSException exceptionWithName:@"YapDatabaseException" reason:reason userInfo:userInfo]; } -- (void)setFilteringBlock:(YapDatabaseViewFilteringBlock)newFilteringBlock - filteringBlockType:(YapDatabaseViewBlockType)newFilteringBlockType - versionTag:(NSString *)inVersionTag +- (void)setFiltering:(YapDatabaseViewFiltering *)filtering + versionTag:(NSString *)inVersionTag { YDBLogAutoTrace(); - NSAssert(newFilteringBlock != NULL, @"Invalid filteringBlock"); - - NSAssert(newFilteringBlockType == YapDatabaseViewBlockTypeWithKey || - newFilteringBlockType == YapDatabaseViewBlockTypeWithObject || - newFilteringBlockType == YapDatabaseViewBlockTypeWithMetadata || - newFilteringBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid filteringBlockType"); + NSAssert(filtering != nil, @"Invalid parameter: filtering == nil"); if (!databaseTransaction->isReadWriteTransaction) { @@ -1410,8 +1405,8 @@ static NSString *const ExtKey_versionTag = @"versionTag"; __unsafe_unretained YapDatabaseFilteredViewConnection *filteredViewConnection = (YapDatabaseFilteredViewConnection *)viewConnection; - [filteredViewConnection setFilteringBlock:newFilteringBlock - filteringBlockType:newFilteringBlockType + [filteredViewConnection setFilteringBlock:filtering.filteringBlock + filteringBlockType:filtering.filteringBlockType versionTag:newVersionTag]; [self repopulateViewDueToFilteringBlockChange]; @@ -1443,4 +1438,17 @@ static NSString *const ExtKey_versionTag = @"versionTag"; }]; } +/** + * DEPRECATED + * Use method setFiltering:versionTag: instead. +**/ +- (void)setFilteringBlock:(YapDatabaseViewFilteringBlock)inBlock + filteringBlockType:(YapDatabaseViewBlockType)inBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withBlock:inBlock blockType:inBlockType]; + + [self setFiltering:filtering versionTag:inVersionTag]; +} + @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h index 67fc0cc..13e776d 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h @@ -1,5 +1,5 @@ #import - +#import "YapDatabaseViewTypes.h" /** * The filtering block removes items from this view that are in the parent view. @@ -19,6 +19,8 @@ * You should choose a block type that takes the minimum number of required parameters. * The filterView can make various optimizations based on required parameters of the block. **/ +@interface YapDatabaseViewFiltering : NSObject + typedef id YapDatabaseViewFilteringBlock; // One of the YapDatabaseViewGroupingX types below. typedef BOOL (^YapDatabaseViewFilteringWithKeyBlock) \ @@ -30,3 +32,12 @@ typedef BOOL (^YapDatabaseViewFilteringWithMetadataBlock)\ typedef BOOL (^YapDatabaseViewFilteringWithRowBlock) \ (NSString *group, NSString *collection, NSString *key, id object, id metadata); ++ (instancetype)withKeyBlock:(YapDatabaseViewFilteringWithKeyBlock)filteringBlock; ++ (instancetype)withObjectBlock:(YapDatabaseViewFilteringWithObjectBlock)filteringBlock; ++ (instancetype)withMetadataBlock:(YapDatabaseViewFilteringWithMetadataBlock)filteringBlock; ++ (instancetype)withRowBlock:(YapDatabaseViewFilteringWithRowBlock)filteringBlock; + +@property (nonatomic, strong, readonly) YapDatabaseViewFilteringBlock filteringBlock; +@property (nonatomic, assign, readonly) YapDatabaseViewBlockType filteringBlockType; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.m b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.m new file mode 100644 index 0000000..a611df6 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.m @@ -0,0 +1,67 @@ +#import "YapDatabaseFilteredViewTypes.h" + +@implementation YapDatabaseViewFiltering + +@synthesize filteringBlock = filteringBlock; +@synthesize filteringBlockType = filteringBlockType; + ++ (instancetype)withKeyBlock:(YapDatabaseViewFilteringWithKeyBlock)filteringBlock +{ + if (filteringBlock == NULL) return nil; + + YapDatabaseViewFiltering *filtering = [[YapDatabaseViewFiltering alloc] init]; + filtering->filteringBlock = filteringBlock; + filtering->filteringBlockType = YapDatabaseViewBlockTypeWithKey; + + return filtering; +} + ++ (instancetype)withObjectBlock:(YapDatabaseViewFilteringWithObjectBlock)filteringBlock +{ + if (filteringBlock == NULL) return nil; + + YapDatabaseViewFiltering *filtering = [[YapDatabaseViewFiltering alloc] init]; + filtering->filteringBlock = filteringBlock; + filtering->filteringBlockType = YapDatabaseViewBlockTypeWithObject; + + return filtering; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseViewFilteringWithMetadataBlock)filteringBlock +{ + if (filteringBlock == NULL) return nil; + + YapDatabaseViewFiltering *filtering = [[YapDatabaseViewFiltering alloc] init]; + filtering->filteringBlock = filteringBlock; + filtering->filteringBlockType = YapDatabaseViewBlockTypeWithMetadata; + + return filtering; +} + ++ (instancetype)withRowBlock:(YapDatabaseViewFilteringWithRowBlock)filteringBlock +{ + if (filteringBlock == NULL) return nil; + + YapDatabaseViewFiltering *filtering = [[YapDatabaseViewFiltering alloc] init]; + filtering->filteringBlock = filteringBlock; + filtering->filteringBlockType = YapDatabaseViewBlockTypeWithRow; + + return filtering; +} + +/** + * Helper method for supporting deprecated methods. + * This method will disappear in the future. +**/ ++ (instancetype)withBlock:(YapDatabaseViewFilteringBlock)block blockType:(YapDatabaseViewBlockType)blockType +{ + if (block == NULL) return nil; + + YapDatabaseViewFiltering *filtering = [[YapDatabaseViewFiltering alloc] init]; + filtering->filteringBlock = block; + filtering->filteringBlockType = blockType; + + return filtering; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h index a34990c..7890e89 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h @@ -1,4 +1,5 @@ #import "YapDatabaseFullTextSearch.h" +#import "YapDatabaseFullTextSearchHandler.h" #import "YapDatabaseFullTextSearchConnection.h" #import "YapDatabaseFullTextSearchTransaction.h" @@ -15,6 +16,19 @@ **/ #define YAP_DATABASE_FTS_CLASS_VERSION 1 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseFullTextSearchHandler () + ++ (instancetype)withBlock:(YapDatabaseFullTextSearchBlock)block blockType:(YapDatabaseFullTextSearchBlockType)blockType; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @interface YapDatabaseFullTextSearch () { @public diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h index ee3045b..eb3f2db 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h @@ -1,78 +1,60 @@ #import #import "YapDatabaseExtension.h" +#import "YapDatabaseFullTextSearchHandler.h" #import "YapDatabaseFullTextSearchConnection.h" #import "YapDatabaseFullTextSearchTransaction.h" /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseFullTextSearch is an extension for performing text based search. * Internally it uses sqlite's FTS module which was contributed by Google. **/ - -/** - * The block handles extracting the column values for indexing by the FTS module. - * - * When you add or update rows in the databse the FTS block is invoked. - * Your block can inspect the row and determine if it contains any text columns that should be indexed. - * If not, the block can simply return. - * Otherwise the block should extract any text values, add them to the given dictionary. - * - * After the block returns, the dictionary parameter will be inspected, - * and any set values will be automatically passed to sqlite's FTS module for indexing. - * - * You should choose a block type that takes the minimum number of required parameters. - * The view can make various optimizations based on required parameters of the block. -**/ -typedef id YapDatabaseFullTextSearchBlock; // One of YapDatabaseFullTextSearchXBlock types - -typedef void (^YapDatabaseFullTextSearchWithKeyBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key); -typedef void (^YapDatabaseFullTextSearchWithObjectBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id object); -typedef void (^YapDatabaseFullTextSearchWithMetadataBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id metadata); -typedef void (^YapDatabaseFullTextSearchWithRowBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id object, id metadata); - -/** - * Use this enum to specify what kind of block you're passing. -**/ -typedef NS_ENUM(NSInteger, YapDatabaseFullTextSearchBlockType) { - YapDatabaseFullTextSearchBlockTypeWithKey = 201, - YapDatabaseFullTextSearchBlockTypeWithObject = 202, - YapDatabaseFullTextSearchBlockTypeWithMetadata = 203, - YapDatabaseFullTextSearchBlockTypeWithRow = 204 -}; - @interface YapDatabaseFullTextSearch : YapDatabaseExtension -/* Inherited from YapDatabaseExtension - -@property (nonatomic, strong, readonly) NSString *registeredName; - -*/ +- (id)initWithColumnNames:(NSArray *)columnNames + handler:(YapDatabaseFullTextSearchHandler *)handler; - (id)initWithColumnNames:(NSArray *)columnNames - block:(YapDatabaseFullTextSearchBlock)block - blockType:(YapDatabaseFullTextSearchBlockType)blockType; - -- (id)initWithColumnNames:(NSArray *)columnNames - block:(YapDatabaseFullTextSearchBlock)block - blockType:(YapDatabaseFullTextSearchBlockType)blockType + handler:(YapDatabaseFullTextSearchHandler *)handler versionTag:(NSString *)versionTag; - (id)initWithColumnNames:(NSArray *)columnNames options:(NSDictionary *)options + handler:(YapDatabaseFullTextSearchHandler *)handler + versionTag:(NSString *)versionTag; + + +- (id)initWithColumnNames:(NSArray *)columnNames block:(YapDatabaseFullTextSearchBlock)block blockType:(YapDatabaseFullTextSearchBlockType)blockType - versionTag:(NSString *)versionTag; +__attribute((deprecated("Use method initWithColumnNames:handler: instead"))); + +- (id)initWithColumnNames:(NSArray *)columnNames + block:(YapDatabaseFullTextSearchBlock)block + blockType:(YapDatabaseFullTextSearchBlockType)blockType + versionTag:(NSString *)versionTag +__attribute((deprecated("Use method initWithColumnNames:handler:versionTag: instead"))); + +- (id)initWithColumnNames:(NSArray *)columnNames + options:(NSDictionary *)options + block:(YapDatabaseFullTextSearchBlock)block + blockType:(YapDatabaseFullTextSearchBlockType)blockType + versionTag:(NSString *)versionTag +__attribute((deprecated("Use method initWithColumnNames:options:handler:versionTag: instead"))); + + +/* Inherited from YapDatabaseExtension + +@property (nonatomic, strong, readonly) NSString *registeredName; + +*/ @property (nonatomic, strong, readonly) YapDatabaseFullTextSearchBlock block; @property (nonatomic, assign, readonly) YapDatabaseFullTextSearchBlockType blockType; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m index 4be29a1..54c7ff5 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m @@ -60,28 +60,24 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; @synthesize versionTag = versionTag; - (id)initWithColumnNames:(NSArray *)inColumnNames - block:(YapDatabaseFullTextSearchBlock)inBlock - blockType:(YapDatabaseFullTextSearchBlockType)inBlockType + handler:(YapDatabaseFullTextSearchHandler *)inHandler { - return [self initWithColumnNames:inColumnNames options:nil block:inBlock blockType:inBlockType versionTag:nil]; + return [self initWithColumnNames:inColumnNames options:nil handler:inHandler versionTag:nil]; } - (id)initWithColumnNames:(NSArray *)inColumnNames - block:(YapDatabaseFullTextSearchBlock)inBlock - blockType:(YapDatabaseFullTextSearchBlockType)inBlockType + handler:(YapDatabaseFullTextSearchHandler *)inHandler versionTag:(NSString *)inVersionTag { return [self initWithColumnNames:inColumnNames options:nil - block:inBlock - blockType:inBlockType + handler:inHandler versionTag:inVersionTag]; } - (id)initWithColumnNames:(NSArray *)inColumnNames options:(NSDictionary *)inOptions - block:(YapDatabaseFullTextSearchBlock)inBlock - blockType:(YapDatabaseFullTextSearchBlockType)inBlockType + handler:(YapDatabaseFullTextSearchHandler *)inHandler versionTag:(NSString *)inVersionTag { if ([inColumnNames count] == 0) @@ -106,13 +102,7 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; } } - NSAssert(inBlock != NULL, @"Null block"); - - NSAssert(inBlockType == YapDatabaseFullTextSearchBlockTypeWithKey || - inBlockType == YapDatabaseFullTextSearchBlockTypeWithObject || - inBlockType == YapDatabaseFullTextSearchBlockTypeWithMetadata || - inBlockType == YapDatabaseFullTextSearchBlockTypeWithRow, - @"Invalid block type"); + NSAssert(inHandler != NULL, @"Null handler"); if ((self = [super init])) { @@ -121,8 +111,8 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; options = [inOptions copy]; - block = inBlock; - blockType = inBlockType; + block = inHandler.block; + blockType = inHandler.blockType; versionTag = inVersionTag ? [inVersionTag copy] : @""; } @@ -130,14 +120,51 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; } /** - * Subclasses must implement this method. - * This method is called during the view registration process to enusre the extension supports the database config. + * DEPRECATED + * Use method initWithColumnNames:handler: instead. **/ -- (BOOL)supportsDatabase:(YapDatabase *)database withRegisteredExtensions:(NSDictionary *)registeredExtensions +- (id)initWithColumnNames:(NSArray *)inColumnNames + block:(YapDatabaseFullTextSearchBlock)inBlock + blockType:(YapDatabaseFullTextSearchBlockType)inBlockType { - return YES; + YapDatabaseFullTextSearchHandler *handler = + [YapDatabaseFullTextSearchHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithColumnNames:inColumnNames handler:handler]; } +/** + * DEPRECATED + * Use method initWithColumnNames:handler:versionTag: instead. +**/ +- (id)initWithColumnNames:(NSArray *)inColumnNames + block:(YapDatabaseFullTextSearchBlock)inBlock + blockType:(YapDatabaseFullTextSearchBlockType)inBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseFullTextSearchHandler *handler = + [YapDatabaseFullTextSearchHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithColumnNames:inColumnNames handler:handler versionTag:inVersionTag]; +} + +/** + * DEPRECATED + * Use method initWithColumnNames:options:handler:versionTag: instead. +**/ +- (id)initWithColumnNames:(NSArray *)inColumnNames + options:(NSDictionary *)inOptions + block:(YapDatabaseFullTextSearchBlock)inBlock + blockType:(YapDatabaseFullTextSearchBlockType)inBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseFullTextSearchHandler *handler = + [YapDatabaseFullTextSearchHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithColumnNames:inColumnNames options:inOptions handler:handler versionTag:inVersionTag]; +} + + - (YapDatabaseExtensionConnection *)newConnection:(YapDatabaseConnection *)databaseConnection { return [[YapDatabaseFullTextSearchConnection alloc] initWithFTS:self databaseConnection:databaseConnection]; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h index 9578620..741f19a 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h @@ -6,10 +6,10 @@ /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseFullTextSearch is an extension for performing text based search. * Internally it uses sqlite's FTS module which was contributed by Google. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m index a5fd803..506d9af 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m @@ -266,10 +266,8 @@ sqlite3_stmt **statement = &queryStatement; if (*statement == NULL) { - NSString *tableName = [fts tableName]; - NSString *string = [NSString stringWithFormat: - @"SELECT \"rowid\" FROM \"%1$@\" WHERE \"%1$@\" MATCH ?;", tableName]; + @"SELECT \"rowid\" FROM \"%1$@\" WHERE \"%1$@\" MATCH ?;", [fts tableName]]; sqlite3 *db = databaseConnection->db; @@ -288,10 +286,9 @@ sqlite3_stmt **statement = &querySnippetStatement; if (*statement == NULL) { - NSString *tableName = [fts tableName]; - NSString *string = [NSString stringWithFormat: - @"SELECT \"rowid\", snippet(\"%1$@\", ?, ?, ?, ?, ?) FROM \"%1$@\" WHERE \"%1$@\" MATCH ?;", tableName]; + @"SELECT \"rowid\", snippet(\"%1$@\", ?, ?, ?, ?, ?) FROM \"%1$@\" WHERE \"%1$@\" MATCH ?;", + [fts tableName]]; sqlite3 *db = databaseConnection->db; @@ -310,10 +307,8 @@ sqlite3_stmt **statement = &rowidQueryStatement; if (*statement == NULL) { - NSString *tableName = [fts tableName]; - NSString *string = [NSString stringWithFormat: - @"SELECT \"rowid\" FROM \"%1$@\" WHERE \"rowid\" = ? AND \"%1$@\" MATCH ?;", tableName]; + @"SELECT \"rowid\" FROM \"%1$@\" WHERE \"rowid\" = ? AND \"%1$@\" MATCH ?;", [fts tableName]]; sqlite3 *db = databaseConnection->db; @@ -332,11 +327,9 @@ sqlite3_stmt **statement = &rowidQuerySnippetStatement; if (*statement == NULL) { - NSString *tableName = [fts tableName]; - NSString *string = [NSString stringWithFormat: @"SELECT \"rowid\", snippet(\"%1$@\", ?, ?, ?, ?, ?) FROM \"%1$@\" WHERE \"rowid\" = ? AND \"%1$@\" MATCH ?;", - tableName]; + [fts tableName]]; sqlite3 *db = databaseConnection->db; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h new file mode 100644 index 0000000..e71034d --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.h @@ -0,0 +1,49 @@ +#import + + +/** + * Specifies the kind of block being used. +**/ +typedef NS_ENUM(NSInteger, YapDatabaseFullTextSearchBlockType) { + YapDatabaseFullTextSearchBlockTypeWithKey = 201, + YapDatabaseFullTextSearchBlockTypeWithObject = 202, + YapDatabaseFullTextSearchBlockTypeWithMetadata = 203, + YapDatabaseFullTextSearchBlockTypeWithRow = 204 +}; + +/** + * The handler block handles extracting the column values for indexing by the FTS module. + * + * When you add or update rows in the databse the FTS block is invoked. + * Your block can inspect the row and determine if it contains any text columns that should be indexed. + * If not, the block can simply return. + * Otherwise the block should extract any text values, and add them to the given dictionary. + * + * After the block returns, the dictionary parameter will be inspected, + * and any set values will be automatically passed to sqlite's FTS module for indexing. + * + * You should choose a block type that takes the minimum number of required parameters. + * The extension can make various optimizations based on the required parameters of the block. +**/ +@interface YapDatabaseFullTextSearchHandler : NSObject + +typedef id YapDatabaseFullTextSearchBlock; // One of YapDatabaseFullTextSearchXBlock types + +typedef void (^YapDatabaseFullTextSearchWithKeyBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key); +typedef void (^YapDatabaseFullTextSearchWithObjectBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id object); +typedef void (^YapDatabaseFullTextSearchWithMetadataBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id metadata); +typedef void (^YapDatabaseFullTextSearchWithRowBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id object, id metadata); + ++ (instancetype)withKeyBlock:(YapDatabaseFullTextSearchWithKeyBlock)block; ++ (instancetype)withObjectBlock:(YapDatabaseFullTextSearchWithObjectBlock)block; ++ (instancetype)withMetadataBlock:(YapDatabaseFullTextSearchWithMetadataBlock)block; ++ (instancetype)withRowBlock:(YapDatabaseFullTextSearchWithRowBlock)block; + +@property (nonatomic, strong, readonly) YapDatabaseFullTextSearchBlock block; +@property (nonatomic, assign, readonly) YapDatabaseFullTextSearchBlockType blockType; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.m b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.m new file mode 100644 index 0000000..6518ac8 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchHandler.m @@ -0,0 +1,68 @@ +#import "YapDatabaseFullTextSearchHandler.h" + + +@implementation YapDatabaseFullTextSearchHandler + +@synthesize block = block; +@synthesize blockType = blockType; + ++ (instancetype)withKeyBlock:(YapDatabaseFullTextSearchWithKeyBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseFullTextSearchHandler *handler = [[YapDatabaseFullTextSearchHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseFullTextSearchBlockTypeWithKey; + + return handler; +} + ++ (instancetype)withObjectBlock:(YapDatabaseFullTextSearchWithObjectBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseFullTextSearchHandler *handler = [[YapDatabaseFullTextSearchHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseFullTextSearchBlockTypeWithObject; + + return handler; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseFullTextSearchWithMetadataBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseFullTextSearchHandler *handler = [[YapDatabaseFullTextSearchHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseFullTextSearchBlockTypeWithMetadata; + + return handler; +} + ++ (instancetype)withRowBlock:(YapDatabaseFullTextSearchWithRowBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseFullTextSearchHandler *handler = [[YapDatabaseFullTextSearchHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseFullTextSearchBlockTypeWithRow; + + return handler; +} + +/** + * Helper method for supporting deprecated methods. + * This method will disappear in the future. +**/ ++ (instancetype)withBlock:(YapDatabaseFullTextSearchBlock)block blockType:(YapDatabaseFullTextSearchBlockType)blockType +{ + if (block == NULL) return nil; + + YapDatabaseFullTextSearchHandler *handler = [[YapDatabaseFullTextSearchHandler alloc] init]; + handler->block = block; + handler->blockType = blockType; + + return handler; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h index 6b65591..a5b9cb0 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h @@ -8,10 +8,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to check out the wiki - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseFullTextSearch is an extension for performing text based search. * Internally it uses sqlite's FTS module which was contributed by Google. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m index 764c89f..4cc517c 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m @@ -505,7 +505,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; /** * Required override method from YapDatabaseExtension **/ -- (void)commitTransaction +- (void)didCommitTransaction { // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, @@ -519,7 +519,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; /** * Required override method from YapDatabaseExtension **/ -- (void)rollbackTransaction +- (void)didRollbackTransaction { // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h index f616011..9fd4fb7 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h @@ -92,13 +92,13 @@ - (BOOL)flushPendingChangesToMainDatabaseTable; // See YapDatabaseExtensionTransaction.m for discussion of this method -- (void)prepareChangeset; +- (void)flushPendingChangesToExtensionTables; // See YapDatabaseExtensionTransaction.m for discussion of this method -- (void)commitTransaction; +- (void)didCommitTransaction; // See YapDatabaseExtensionTransaction.m for discussion of this method -- (void)rollbackTransaction; +- (void)didRollbackTransaction; #pragma mark Hooks @@ -133,6 +133,32 @@ - (void)handleRemoveAllObjectsInAllCollections; +// Pre-op versions + +- (void)handleWillInsertObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata; + +- (void)handleWillUpdateObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata + rowid:(int64_t)rowid; + +- (void)handleWillReplaceObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withRowid:(int64_t)rowid; + +- (void)handleWillReplaceMetadata:(id)metadata + forCollectionKey:(YapCollectionKey *)collectionKey + withRowid:(int64_t)rowid; + +- (void)handleWillRemoveObjectForCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid; + +- (void)handleWillRemoveObjectsForKeys:(NSArray *)keys inCollection:(NSString *)collection withRowids:(NSArray *)rowids; + +- (void)handleWillRemoveAllObjectsInAllCollections; + + #pragma mark Configuration Values /** diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m index 4496d83..56a2159 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m @@ -63,15 +63,20 @@ @synthesize registeredDatabase; /** - * Subclasses MUST implement this method. - * This method is called during the view registration process to enusre the extension supports the database type. + * Subclasses may OPTIONALLY implement this method. + * This method is called during the extension registration process to enusre the extension (as configured) + * will support the given database configuration. This is primarily for extensions with dependecies. + * + * For example, the YapDatabaseFilteredView is configured with the registered name of a parent View instance. + * So that class should implement this method to ensure: + * - The parentView actually exists + * - The parentView is actually a YapDatabaseView class/subclass * * Return YES if the class/instance supports the database configuration. **/ - (BOOL)supportsDatabase:(YapDatabase *)database withRegisteredExtensions:(NSDictionary *)registeredExtensions { - NSAssert(NO, @"Missing required method(%@) in class(%@)", NSStringFromSelector(_cmd), [self class]); - return NO; + return YES; } /** diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h index 7a40a01..6e79ef4 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h @@ -5,7 +5,7 @@ /** * This class is abstract and has no public API. - * See concrete implementations such as YapDatabaseViewConnection. + * See concrete implementations such as YapDatabaseViewConnection, YapDatabaseSecondaryIndexConnection, etc. **/ @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h index 2a3ccb1..b0ce1e0 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h @@ -5,7 +5,7 @@ /** * This class is abstract and has no public API. - * See concrete implementations such as YapDatabaseViewTransaction. + * See concrete implementations such as YapDatabaseViewTransaction, YapDatabaseSecondaryIndexTransaction, etc. **/ @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m index ba1ce23..4edb899 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m @@ -56,6 +56,8 @@ */ } +#pragma mark Creation + /** * Subclasses MUST implement this method. * @@ -118,6 +120,10 @@ return NO; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Commit & Rollback +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** * Subclasses may OPTIONALLY implement this method. * This method is only called if within a readwrite transaction. @@ -133,6 +139,7 @@ **/ - (BOOL)flushPendingChangesToMainDatabaseTable { + // Override me if needed return NO; } @@ -140,40 +147,49 @@ * Subclasses may OPTIONALLY implement this method. * This method is only called if within a readwrite transaction. * - * Subclasses may implement it to perform any "cleanup" before the changeset is requested. - * Remember, the changeset is requested before the commitTransaction method is invoked. + * Subclasses should write any last changes to their database table(s) if needed, + * and should perform any needed cleanup before the changeset is requested. + * + * Remember, the changeset is requested immediately after this method is invoked. **/ -- (void)prepareChangeset +- (void)flushPendingChangesToExtensionTables { - // Subclasses may optionally override this method to perform any "cleanup" before the changesets are requested. - // Remember, the changesets are requested before the commitTransaction method is invoked. + // Override me if needed } /** * Subclasses MUST implement this method. * This method is only called if within a readwrite transaction. + * + * Remember, the transaction cannot make any changes to the database at this point, + * as this method is called after the transaction has completed. + * This method is primarily for cleanup & related tasks. **/ -- (void)commitTransaction +- (void)didCommitTransaction { NSAssert(NO, @"Missing required override method(%@) in class(%@)", NSStringFromSelector(_cmd), [self class]); - // Subclasses should include the code similar to the following at the end of their implementation: + // Subclasses MUST include the code similar to the following at the end of their implementation: // - // viewConnection = nil; + // extConnection = nil; // databaseTransaction = nil; } /** * Subclasses MUST implement this method. * This method is only called if within a readwrite transaction. + * + * Remember, the transaction cannot make any changes to the database at this point, + * as this method is called after the transaction has aborted. + * This method is primarily for cleanup & related tasks. **/ -- (void)rollbackTransaction +- (void)didRollbackTransaction { NSAssert(NO, @"Missing required override method(%@) in class(%@)", NSStringFromSelector(_cmd), [self class]); - // Subclasses should include the code similar to the following at the end of their implementation: + // Subclasses MUST include the code similar to the following at the end of their implementation: // - // viewConnection = nil; + // extConnection = nil; // databaseTransaction = nil; } @@ -309,6 +325,95 @@ NSAssert(NO, @"Missing required override method(%@) in class(%@)", NSStringFromSelector(_cmd), [self class]); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Pre-Hooks +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction setObject:object forKey:key inCollection:collection] & + * [transaction setObject:object forKey:key inCollection:collection withMetadata:metadata] + * where the object is being inserted (value for collection/key does NOT exist at the moment this method is called). + **/ +- (void)handleWillInsertObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction setObject:object forKey:key inCollection:collection] & + * [transaction setObject:object forKey:key inCollection:collection withMetadata:metadata] + * where the object is being updated (value for collection/key DOES exist, and is being updated/changed). + **/ +- (void)handleWillUpdateObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withMetadata:(id)metadata + rowid:(int64_t)rowid +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction replaceObject:object forKey:key inCollection:collection]. + **/ +- (void)handleWillReplaceObject:(id)object + forCollectionKey:(YapCollectionKey *)collectionKey + withRowid:(int64_t)rowid +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction replaceMetadata:metadata forKey:key inCollection:collection]. + **/ +- (void)handleWillReplaceMetadata:(id)metadata + forCollectionKey:(YapCollectionKey *)collectionKey + withRowid:(int64_t)rowid +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction removeObjectForKey:key inCollection:collection]. + **/ +- (void)handleWillRemoveObjectForCollectionKey:(YapCollectionKey *)collectionKey withRowid:(int64_t)rowid +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * + * Corresponds to [transaction removeObjectsForKeys:keys inCollection:collection] & + * [transaction removeAllObjectsInCollection:collection]. + * + * IMPORTANT: + * The number of items passed to this method has the following guarantee: + * count <= (SQLITE_LIMIT_VARIABLE_NUMBER - 1) + * + * The YapDatabaseReadWriteTransaction will inspect the list of keys that are to be removed, + * and then loop over them in "chunks" which are readily processable for extensions. + **/ +- (void)handleWillRemoveObjectsForKeys:(NSArray *)keys inCollection:(NSString *)collection withRowids:(NSArray *)rowids +{ +} + +/** + * Subclasses may OPTIONALLY implement this method. + * YapDatabaseReadWriteTransaction Hook, invoked pre-op. + * Corresponds to [transaction removeAllObjectsInAllCollections]. + **/ +- (void)handleWillRemoveAllObjectsInAllCollections +{ +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Configuration Values //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h index 4ad4b6d..33ca486 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h @@ -48,7 +48,7 @@ @public BOOL disableYapDatabaseRelationshipNodeProtocol; - NSSet *allowedCollections; + YapWhitelistBlacklist *allowedCollections; } @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h index a6eb4fd..b1f7524 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h @@ -12,16 +12,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ @interface YapDatabaseRelationship : YapDatabaseExtension diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h index 09417ed..b661c33 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h @@ -7,16 +7,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ @interface YapDatabaseRelationshipConnection : YapDatabaseExtensionConnection diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m index 31cdf57..ed9e5c0 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m @@ -230,28 +230,32 @@ #pragma mark Statements //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)prepareStatement:(sqlite3_stmt **)statement withString:(NSString *)stmtString caller:(SEL)caller_cmd +{ + sqlite3 *db = databaseConnection->db; + YapDatabaseString stmt; MakeYapDatabaseString(&stmt, stmtString); + + int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@: Error creating prepared statement: %d %s", + NSStringFromSelector(caller_cmd), status, sqlite3_errmsg(db)); + } + + FreeYapDatabaseString(&stmt); +} + - (sqlite3_stmt *)findManualEdgeStatement { sqlite3_stmt **statement = &findManualEdgeStatement; if (*statement == NULL) { - NSString *tableName = [relationship tableName]; - NSString *string = [NSString stringWithFormat: @"SELECT \"rowid\", \"rules\" FROM \"%@\" " @" WHERE \"src\" = ? AND \"dst\" = ? AND \"name\" = ? AND \"manual\" = 1 LIMIT 1;", - tableName]; + [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -266,16 +270,7 @@ @"INSERT INTO \"%@\" (\"name\", \"src\", \"dst\", \"rules\", \"manual\") VALUES (?, ?, ?, ?, ?);", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -289,16 +284,7 @@ NSString *string = [NSString stringWithFormat: @"UPDATE \"%@\" SET \"rules\" = ? WHERE \"rowid\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -312,16 +298,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\" WHERE \"rowid\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -335,16 +312,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\" WHERE \"src\" = ? OR \"dst\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -371,16 +339,7 @@ @"SELECT \"dst\" FROM \"%@\" WHERE \"dst\" > ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } if (*statement) @@ -403,16 +362,7 @@ @"SELECT \"rowid\", \"name\", \"dst\", \"rules\", \"manual\" FROM \"%@\" WHERE \"src\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -427,16 +377,7 @@ @"SELECT \"rowid\", \"name\", \"src\", \"rules\", \"manual\" FROM \"%@\" WHERE \"dst\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -451,16 +392,7 @@ @"SELECT \"rowid\", \"dst\", \"rules\", \"manual\" FROM \"%@\" WHERE \"src\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -475,16 +407,7 @@ @"SELECT \"rowid\", \"src\", \"rules\", \"manual\" FROM \"%@\" WHERE \"dst\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -499,16 +422,7 @@ @"SELECT \"rowid\", \"src\", \"dst\", \"rules\", \"manual\" FROM \"%@\" WHERE \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -523,16 +437,7 @@ @"SELECT \"rowid\", \"name\", \"rules\", \"manual\" FROM \"%@\" WHERE \"src\" = ? AND \"dst\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -547,16 +452,7 @@ @"SELECT \"rowid\", \"rules\", \"manual\" FROM \"%@\" WHERE \"src\" = ? AND \"dst\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -571,16 +467,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"src\" = ? AND \"dst\" != ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -595,16 +482,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"dst\" = ? AND \"src\" != ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -619,16 +497,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -643,16 +512,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"src\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -667,16 +527,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"src\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -691,16 +542,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"dst\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -715,16 +557,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"dst\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -739,16 +572,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"src\" = ? AND \"dst\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -763,16 +587,7 @@ @"SELECT COUNT(*) AS NumberOfRows FROM \"%@\" WHERE \"src\" = ? AND \"dst\" = ? AND \"name\" = ?;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -785,16 +600,7 @@ { NSString *string = [NSString stringWithFormat:@"DELETE FROM \"%@\";", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -808,16 +614,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\" WHERE \"manual\" = 0;", [relationship tableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h index bf9dddb..ecb58fd 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h @@ -4,16 +4,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ enum { diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h index 3e22d68..0ddf40d 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h @@ -5,16 +5,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ typedef NS_ENUM(NSInteger, YDB_NotifyReason) { diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h index 3fbc60e..ff8178e 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h @@ -1,17 +1,18 @@ #import +#import "YapWhitelistBlacklist.h" /** * Welcome to YapDatabase! - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ typedef NSData* (^YapDatabaseRelationshipFilePathEncryptor)(NSString *dstFilePath); @@ -56,7 +57,7 @@ typedef id (^YapDatabaseRelationshipFilePathDecryptor)(NSData *data); * * The default value is nil. **/ -@property (nonatomic, copy, readwrite) NSSet *allowedCollections; +@property (nonatomic, strong, readwrite) YapWhitelistBlacklist *allowedCollections; /** * The relationship extension allows you to create relationships between objects in the database & files on disk. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h index ed792b6..6030610 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h @@ -8,16 +8,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabaseRelationship extension allow you to create relationships between objects, * and configure automatic deletion rules. * * For tons of information about this extension, see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Relationships + * https://github.com/yapstudios/YapDatabase/wiki/Relationships **/ @interface YapDatabaseRelationshipTransaction : YapDatabaseExtensionTransaction @@ -352,7 +352,7 @@ * * For more information, see the wiki section "Edge Creation": * - * https://github.com/yaptv/YapDatabase/wiki/Relationships#wiki-edge_creation + * https://github.com/yapstudios/YapDatabase/wiki/Relationships#wiki-edge_creation **/ /** diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m index 27ab8bb..d8c3d82 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m @@ -312,18 +312,22 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t } }; - __unsafe_unretained NSSet *allowedCollections = relationshipConnection->relationship->options->allowedCollections; + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = + relationshipConnection->relationship->options->allowedCollections; if (allowedCollections) { - for (NSString *collection in allowedCollections) - { - [databaseTransaction _enumerateKeysAndObjectsInCollection:collection usingBlock: - ^(int64_t rowid, NSString *key, id object, BOOL *stop) + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *outerStop) { + + if ([allowedCollections isAllowed:collection]) { - ProcessRow(rowid, collection, key, object); - }]; - } + [databaseTransaction _enumerateKeysAndObjectsInCollection:collection usingBlock: + ^(int64_t rowid, NSString *key, id object, BOOL *innerStop) + { + ProcessRow(rowid, collection, key, object); + }]; + } + }]; } else { @@ -2374,7 +2378,8 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t [databaseRwTransaction replaceObject:updatedDestinationNode forKey:edge->destinationKey inCollection:edge->destinationCollection - withRowid:edge->destinationRowid]; + withRowid:edge->destinationRowid + serializedObject:nil]; } } } @@ -2433,7 +2438,8 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t [databaseRwTransaction replaceObject:updatedSourceNode forKey:edge->sourceKey inCollection:edge->sourceCollection - withRowid:edge->sourceRowid]; + withRowid:edge->sourceRowid + serializedObject:nil]; } } } @@ -2749,7 +2755,8 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t [databaseRwTransaction replaceObject:updatedDstNode forKey:edge->destinationKey inCollection:edge->destinationCollection - withRowid:edge->destinationRowid]; + withRowid:edge->destinationRowid + serializedObject:nil]; } } } @@ -2835,7 +2842,8 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t [databaseRwTransaction replaceObject:updatedSrcNode forKey:edge->sourceKey inCollection:edge->sourceCollection - withRowid:edge->sourceRowid]; + withRowid:edge->sourceRowid + serializedObject:nil]; } } } @@ -2895,7 +2903,7 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t /** * This method is only called if within a readwrite transaction. **/ -- (void)commitTransaction +- (void)didCommitTransaction { YDBLogAutoTrace(); @@ -2943,7 +2951,7 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t /** * This method is only called if within a readwrite transaction. **/ -- (void)rollbackTransaction +- (void)didRollbackTransaction { YDBLogAutoTrace(); @@ -2983,7 +2991,7 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t if (options->disableYapDatabaseRelationshipNodeProtocol) { return; } - if (options->allowedCollections && ![options->allowedCollections containsObject:collectionKey.collection]) { + if (options->allowedCollections && ![options->allowedCollections isAllowed:collectionKey.collection]) { return; } @@ -3086,7 +3094,7 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t if (options->disableYapDatabaseRelationshipNodeProtocol) { return; } - if (options->allowedCollections && ![options->allowedCollections containsObject:collectionKey.collection]) { + if (options->allowedCollections && ![options->allowedCollections isAllowed:collectionKey.collection]) { return; } @@ -3144,7 +3152,7 @@ NS_INLINE BOOL EdgeMatchesDestination(YapDatabaseRelationshipEdge *edge, int64_t if (options->disableYapDatabaseRelationshipNodeProtocol) { return; } - if (options->allowedCollections && ![options->allowedCollections containsObject:collectionKey.collection]) { + if (options->allowedCollections && ![options->allowedCollections isAllowed:collectionKey.collection]) { return; } diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h index f9f59c9..cc49750 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.h @@ -8,10 +8,10 @@ /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseSearchResults allows you to pipe search results from YapDatabaseFullTextSearch into a YapDatabaseView. * This makes it easy to display search results in a tableView or collectionView. @@ -50,8 +50,8 @@ **/ - (id)initWithFullTextSearchName:(NSString *)fullTextSearchName parentViewName:(NSString *)parentViewName - versionTag:(NSString *)versionTag - options:(YapDatabaseSearchResultsViewOptions *)options; + versionTag:(NSString *)versionTag + options:(YapDatabaseSearchResultsViewOptions *)options; /** * In this configuration, you want to pipe search results directly into a new YapDatabaseView. @@ -69,18 +69,10 @@ * The groupingBlock is used to place search results into proper sections. * The block may also be used to perform secondary filtering. * - * @param groupingBlockType - * - * Must match the groupingBlock. - * * @param sortingBlock * * The sortingBlock is used to sort search results within their respective sections. * - * @param sortingBlockType - * - * Must match the sortingBlock. - * * @param versionTag * * The standard versionTag mechanism. @@ -93,13 +85,21 @@ * For more information on the groupingBlock & sortingBlock parmaters, * please see the documentation in YapDatabaseView.h. **/ +- (id)initWithFullTextSearchName:(NSString *)fullTextSearchName + grouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)versionTag + options:(YapDatabaseSearchResultsViewOptions *)options; + + - (id)initWithFullTextSearchName:(NSString *)fullTextSearchName groupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType versionTag:(NSString *)versionTag - options:(YapDatabaseSearchResultsViewOptions *)options; + options:(YapDatabaseSearchResultsViewOptions *)options +__attribute((deprecated("Use method initWithFullTextSearchName:grouping:sorting:versionTag:options: instead"))); @property (nonatomic, strong, readonly) NSString *fullTextSearchName; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m index e51d70a..5233e56 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsView.m @@ -2,6 +2,7 @@ #import "YapDatabaseSearchResultsViewPrivate.h" #import "YapDatabaseExtensionPrivate.h" #import "YapDatabaseFullTextSearch.h" +#import "YapDatabaseViewPrivate.h" #import "YapDatabasePrivate.h" #import "YapDatabaseLogging.h" @@ -60,12 +61,10 @@ #pragma mark Invalid //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType - versionTag:(NSString *)inVersionTag - options:(YapDatabaseViewOptions *)inOptions +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)inVersionTag + options:(YapDatabaseViewOptions *)inOptions { NSString *reason = @"You must use the init method(s) specific to YapDatabaseSearchResults."; @@ -107,39 +106,25 @@ } - (id)initWithFullTextSearchName:(NSString *)inFullTextSearchName - groupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType + grouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting versionTag:(NSString *)inVersionTag options:(YapDatabaseSearchResultsViewOptions *)inOptions { - NSAssert(inFullTextSearchName != nil, @"Invalid fullTextSearchName"); + NSAssert(inFullTextSearchName != nil, @"Invalid parameter: fullTextSearchName == nil"); - NSAssert(inGroupingBlock != NULL, @"Invalid grouping block"); - NSAssert(inSortingBlock != NULL, @"Invalid sorting block"); - - NSAssert(inGroupingBlockType == YapDatabaseViewBlockTypeWithKey || - inGroupingBlockType == YapDatabaseViewBlockTypeWithObject || - inGroupingBlockType == YapDatabaseViewBlockTypeWithMetadata || - inGroupingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid grouping block type"); - - NSAssert(inSortingBlockType == YapDatabaseViewBlockTypeWithKey || - inSortingBlockType == YapDatabaseViewBlockTypeWithObject || - inSortingBlockType == YapDatabaseViewBlockTypeWithMetadata || - inSortingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid sorting block type"); + NSAssert(grouping != NULL, @"Invalid parameter: grouping == nil"); + NSAssert(sorting != NULL, @"Invalid parameter: sorting == nil"); if ((self = [super init])) { fullTextSearchName = [inFullTextSearchName copy]; - groupingBlock = inGroupingBlock; - groupingBlockType = inGroupingBlockType; + groupingBlock = grouping.groupingBlock; + groupingBlockType = grouping.groupingBlockType; - sortingBlock = inSortingBlock; - sortingBlockType = inSortingBlockType; + sortingBlock = sorting.sortingBlock; + sortingBlockType = sorting.sortingBlockType; versionTag = inVersionTag ? [inVersionTag copy] : @""; @@ -148,6 +133,28 @@ return self; } +/** + * DEPRECATED + * Use method initWithFullTextSearchName:grouping:sorting:versionTag:options: instead. +**/ +- (id)initWithFullTextSearchName:(NSString *)inFullTextSearchName + groupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType + versionTag:(NSString *)inVersionTag + options:(YapDatabaseSearchResultsViewOptions *)inOptions +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + return [self initWithFullTextSearchName:inFullTextSearchName + grouping:grouping + sorting:sorting + versionTag:inVersionTag + options:inOptions]; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Registration //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m index 16aba24..d2ac460 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewConnection.m @@ -158,21 +158,11 @@ sqlite3_stmt **statement = &snippetTable_getForRowidStatement; if (*statement == NULL) { - NSString *snippetTableName = [(YapDatabaseSearchResultsView *)view snippetTableName]; - NSString *string = [NSString stringWithFormat: - @"SELECT \"snippet\" FROM \"%@\" WHERE \"rowid\" = ?;", snippetTableName]; + @"SELECT \"snippet\" FROM \"%@\" WHERE \"rowid\" = ?;", + [(YapDatabaseSearchResultsView *)view snippetTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -185,21 +175,11 @@ sqlite3_stmt **statement = &snippetTable_setForRowidStatement; if (*statement == NULL) { - NSString *snippetTableName = [(YapDatabaseSearchResultsView *)view snippetTableName]; - NSString *string = [NSString stringWithFormat: - @"INSERT OR REPLACE INTO \"%@\" (\"rowid\", \"snippet\") VALUES (?, ?);", snippetTableName]; + @"INSERT OR REPLACE INTO \"%@\" (\"rowid\", \"snippet\") VALUES (?, ?);", + [(YapDatabaseSearchResultsView *)view snippetTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -212,20 +192,10 @@ sqlite3_stmt **statement = &snippetTable_removeForRowidStatement; if (*statement == NULL) { - NSString *snippetTableName = [(YapDatabaseSearchResultsView *)view snippetTableName]; + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\" WHERE \"rowid\" = ? ;", [(YapDatabaseSearchResultsView *)view snippetTableName]]; - NSString *string = [NSString stringWithFormat:@"DELETE FROM \"%@\" WHERE \"rowid\" = ? ;", snippetTableName]; - - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -238,20 +208,10 @@ sqlite3_stmt **statement = &snippetTable_removeAllStatement; if (*statement == NULL) { - NSString *snippetTableName = [(YapDatabaseSearchResultsView *)view snippetTableName]; + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\";", [(YapDatabaseSearchResultsView *)view snippetTableName]]; - NSString *string = [NSString stringWithFormat:@"DELETE FROM \"%@\";", snippetTableName]; - - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h index 7fb3a1c..a1ccf5a 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewOptions.h @@ -1,6 +1,7 @@ #import #import "YapDatabaseViewOptions.h" +#import "YapWhitelistBlacklist.h" #import "YapDatabaseFullTextSearchSnippetOptions.h" @@ -28,7 +29,7 @@ * * The default value is nil. **/ -@property (nonatomic, copy, readwrite) NSSet *allowedGroups; +@property (nonatomic, strong, readwrite) YapWhitelistBlacklist *allowedGroups; /** * Set this option to include snippets with the search results. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m index 8834939..972f369 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SearchResults/YapDatabaseSearchResultsViewTransaction.m @@ -1,6 +1,7 @@ #import "YapDatabaseSearchResultsViewTransaction.h" #import "YapDatabaseSearchResultsViewPrivate.h" #import "YapDatabaseViewChangePrivate.h" +#import "YapDatabaseViewPrivate.h" #import "YapDatabaseFullTextSearchPrivate.h" #import "YapDatabaseExtensionPrivate.h" #import "YapDatabasePrivate.h" @@ -549,12 +550,20 @@ static NSString *const ExtKey_query = @"query"; NSMutableArray *groupsInSelf = [[self allGroups] mutableCopy]; id groupsInParent; - if (searchResultsOptions.allowedGroups) + __unsafe_unretained YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups) { - NSMutableSet *groupsInParentSet = [NSMutableSet setWithArray:[parentViewTransaction allGroups]]; - [groupsInParentSet intersectSet:searchResultsOptions.allowedGroups]; + NSArray *allGroups = [parentViewTransaction allGroups]; + NSMutableArray *groups = [NSMutableArray arrayWithCapacity:[allGroups count]]; - groupsInParent = groupsInParentSet; + for (NSString *group in allGroups) + { + if ([allowedGroups isAllowed:group]) { + [groups addObject:group]; + } + } + + groupsInParent = groups; } else { @@ -942,7 +951,7 @@ static NSString *const ExtKey_query = @"query"; #pragma mark Cleanup & Commit //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)commitTransaction +- (void)flushPendingChangesToExtensionTables { YDBLogAutoTrace(); @@ -966,10 +975,10 @@ static NSString *const ExtKey_query = @"query"; } // This must be done LAST. - [super commitTransaction]; + [super flushPendingChangesToExtensionTables]; } -- (void)rollbackTransaction +- (void)didRollbackTransaction { YDBLogAutoTrace(); @@ -979,7 +988,7 @@ static NSString *const ExtKey_query = @"query"; } // This must be done LAST. - [super rollbackTransaction]; + [super didRollbackTransaction]; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1018,8 +1027,8 @@ static NSString *const ExtKey_query = @"query"; if (group) { - NSSet *allowedGroups = searchResultsOptions.allowedGroups; - if (allowedGroups && ![allowedGroups containsObject:group]) + YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups && ![allowedGroups isAllowed:group]) { group = nil; } @@ -1032,9 +1041,9 @@ static NSString *const ExtKey_query = @"query"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = searchResultsOptions.allowedCollections; + YapWhitelistBlacklist *allowedCollections = searchResultsOptions.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { YapDatabaseViewGroupingBlock groupingBlock_generic; YapDatabaseViewBlockType groupingBlockType; @@ -1139,8 +1148,8 @@ static NSString *const ExtKey_query = @"query"; if (group) { - NSSet *allowedGroups = searchResultsOptions.allowedGroups; - if (allowedGroups && ![allowedGroups containsObject:group]) + YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups && ![allowedGroups isAllowed:group]) { group = nil; } @@ -1153,9 +1162,9 @@ static NSString *const ExtKey_query = @"query"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = searchResultsOptions.allowedCollections; + YapWhitelistBlacklist *allowedCollections = searchResultsOptions.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { YapDatabaseViewGroupingBlock groupingBlock_generic; YapDatabaseViewBlockType groupingBlockType; @@ -1277,8 +1286,8 @@ static NSString *const ExtKey_query = @"query"; if (group) { - NSSet *allowedGroups = searchResultsOptions.allowedGroups; - if (allowedGroups && ![allowedGroups containsObject:group]) + YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups && ![allowedGroups isAllowed:group]) { group = nil; } @@ -1438,9 +1447,9 @@ static NSString *const ExtKey_query = @"query"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = searchResultsOptions.allowedCollections; + YapWhitelistBlacklist *allowedCollections = searchResultsOptions.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { if (groupingBlockType == YapDatabaseViewBlockTypeWithObject) { @@ -1562,8 +1571,8 @@ static NSString *const ExtKey_query = @"query"; if (group) { - NSSet *allowedGroups = searchResultsOptions.allowedGroups; - if (allowedGroups && ![allowedGroups containsObject:group]) + YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups && ![allowedGroups isAllowed:group]) { group = nil; } @@ -1723,9 +1732,9 @@ static NSString *const ExtKey_query = @"query"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = searchResultsOptions.allowedCollections; + YapWhitelistBlacklist *allowedCollections = searchResultsOptions.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { if (groupingBlockType == YapDatabaseViewBlockTypeWithMetadata) { @@ -1882,11 +1891,9 @@ static NSString *const ExtKey_query = @"query"; #pragma mark ReadWrite //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType - versionTag:(NSString *)inVersionTag +- (void)setGrouping:(YapDatabaseViewGrouping *)inGrouping + sorting:(YapDatabaseViewSorting *)inSorting + versionTag:(NSString *)inVersionTag { YDBLogAutoTrace(); @@ -1907,14 +1914,28 @@ static NSString *const ExtKey_query = @"query"; } else { - [super setGroupingBlock:inGroupingBlock - groupingBlockType:inGroupingBlockType - sortingBlock:inSortingBlock - sortingBlockType:inSortingBlockType - versionTag:inVersionTag]; + [super setGrouping:inGrouping + sorting:inSorting + versionTag:inVersionTag]; } } +/** + * DEPRECATED + * Use method setGrouping:sorting:versionTag: instead. +**/ +- (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + [self setGrouping:grouping sorting:sorting versionTag:inVersionTag]; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Searching //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1957,10 +1978,23 @@ static NSString *const ExtKey_query = @"query"; id groupsToEnumerate = nil; - if (searchResultsOptions.allowedGroups) { - groupsToEnumerate = searchResultsOptions.allowedGroups; + __unsafe_unretained YapWhitelistBlacklist *allowedGroups = searchResultsOptions.allowedGroups; + if (allowedGroups) + { + NSArray *allGroups = [parentViewTransaction allGroups]; + NSMutableArray *groups = [NSMutableArray arrayWithCapacity:[allGroups count]]; + + for (NSString *group in allGroups) + { + if ([allowedGroups isAllowed:group]) { + [groups addObject:group]; + } + } + + groupsToEnumerate = groups; } - else { + else + { groupsToEnumerate = [parentViewTransaction allGroups]; } @@ -2149,9 +2183,9 @@ static NSString *const ExtKey_query = @"query"; // Invoke the grouping block to find out if the object should be included in the view. NSString *group = nil; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:ck.collection]) + if (!allowedCollections || [allowedCollections isAllowed:ck.collection]) { if (groupingBlockType == YapDatabaseViewBlockTypeWithKey) { diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h index 26ad86a..2a2432a 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h @@ -3,12 +3,11 @@ #import "YapDatabaseTransaction.h" #import "YapDatabaseSecondaryIndex.h" +#import "YapDatabaseSecondaryIndexSetup.h" +#import "YapDatabaseSecondaryIndexHandler.h" #import "YapDatabaseSecondaryIndexConnection.h" #import "YapDatabaseSecondaryIndexTransaction.h" -#import "YapDatabaseSecondaryIndexSetup.h" -#import "YapDatabaseSecondaryIndexSetupPrivate.h" - #import "YapCache.h" #import "sqlite3.h" @@ -21,6 +20,39 @@ #define YAP_DATABASE_SECONDARY_INDEX_CLASS_VERSION 1 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseSecondaryIndexSetup () + +/** + * This method compares its setup to a current table structure. + * + * @param columns + * + * Dictionary of column names and affinity. + * + * @see YapDatabase columnNamesAndAffinityForTable:using: +**/ +- (BOOL)matchesExistingColumnNamesAndAffinity:(NSDictionary *)columns; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface YapDatabaseSecondaryIndexHandler () + ++ (instancetype)withBlock:(YapDatabaseSecondaryIndexBlock)block blockType:(YapDatabaseSecondaryIndexBlockType)blockType; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @interface YapDatabaseSecondaryIndex () { @public diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h deleted file mode 100644 index bc85dc7..0000000 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h +++ /dev/null @@ -1,18 +0,0 @@ -#import -#import "YapDatabaseSecondaryIndexSetup.h" - - -@interface YapDatabaseSecondaryIndexSetup () - -/** - * This method compares its setup to a current table structure. - * - * @param columns - * - * Dictionary of column names and affinity. - * - * @see YapDatabase columnNamesAndAffinityForTable:using: -**/ -- (BOOL)matchesExistingColumnNamesAndAffinity:(NSDictionary *)columns; - -@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h index 3c3df92..579259c 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h @@ -2,16 +2,17 @@ #import "YapDatabaseExtension.h" #import "YapDatabaseSecondaryIndexSetup.h" +#import "YapDatabaseSecondaryIndexHandler.h" #import "YapDatabaseSecondaryIndexOptions.h" #import "YapDatabaseSecondaryIndexConnection.h" #import "YapDatabaseSecondaryIndexTransaction.h" /** * Welcome to YapDatabase! - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseSecondaryIndex is an extension which allows you to add additional indexes for fast searching. * @@ -23,54 +24,10 @@ * - find the contact where: email == "johndoe@domain.com" * * For more information, see the wiki article about secondary indexes: - * https://github.com/yaptv/YapDatabase/wiki/Secondary-Indexes + * https://github.com/yapstudios/YapDatabase/wiki/Secondary-Indexes **/ - -/** - * The block handles extracting the column values for the secondary indexes. - * - * When you add or update rows in the databse the block is invoked. - * Your block can inspect the row and determine if it contains any values that should be added to the secondary indexes. - * If not, the block can simply return. - * Otherwise the block should extract any values and add them to the given dictionary. - * - * After the block returns, the dictionary parameter will be inspected, - * and any set values will be automatically inserted/updated within the sqlite indexes. - * - * You should choose a block type that takes the minimum number of required parameters. - * The extension can make various optimizations based on required parameters of the block. - * For example, if metadata isn't required, then the extension can ignore metadata-only updates. -**/ -typedef id YapDatabaseSecondaryIndexBlock; // One of the YapDatabaseSecondaryIndexWith_X_Block types below. - -typedef void (^YapDatabaseSecondaryIndexWithKeyBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key); -typedef void (^YapDatabaseSecondaryIndexWithObjectBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id object); -typedef void (^YapDatabaseSecondaryIndexWithMetadataBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id metadata); -typedef void (^YapDatabaseSecondaryIndexWithRowBlock) \ - (NSMutableDictionary *dict, NSString *collection, NSString *key, id object, id metadata); - -/** - * Use this enum to specify what kind of block you're passing. -**/ -typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { - YapDatabaseSecondaryIndexBlockTypeWithKey = 1031, - YapDatabaseSecondaryIndexBlockTypeWithObject = 1032, - YapDatabaseSecondaryIndexBlockTypeWithMetadata = 1033, - YapDatabaseSecondaryIndexBlockTypeWithRow = 1034 -}; - - @interface YapDatabaseSecondaryIndex : YapDatabaseExtension -/* Inherited from YapDatabaseExtension - -@property (nonatomic, strong, readonly) NSString *registeredName; - -*/ - /** * Creates a new secondary index extension. * After creation, you'll need to register the extension with the database system. @@ -81,28 +38,18 @@ typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { * The column names can be whatever you want, with a few exceptions for reserved names such as "rowid". * The types can reflect numbers or text. * - * @param block + * @param handler * - * Pass a block that is one of the following types: - * - YapDatabaseSecondaryIndexWithKeyBlock - * - YapDatabaseSecondaryIndexWithObjectBlock - * - YapDatabaseSecondaryIndexWithMetadataBlock - * - YapDatabaseSecondaryIndexWithRowBlock - * - * @param blockType - * - * Pass the blockType enum that matches the passed block: - * - YapDatabaseSecondaryIndexBlockTypeWithKey - * - YapDatabaseSecondaryIndexBlockTypeWithObject - * - YapDatabaseSecondaryIndexBlockTypeWithMetadata - * - YapDatabaseSecondaryIndexBlockTypeWithRow + * The block (and blockType) that handles extracting secondary index information from a row in the database. + * * * @see YapDatabaseSecondaryIndexSetup + * @see YapDatabaseSecondaryIndexHandler + * * @see YapDatabase registerExtension:withName: **/ - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup - block:(YapDatabaseSecondaryIndexBlock)block - blockType:(YapDatabaseSecondaryIndexBlockType)blockType; + handler:(YapDatabaseSecondaryIndexHandler *)handler; /** * Creates a new secondary index extension. @@ -114,21 +61,9 @@ typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { * The column names can be whatever you want, with a few exceptions for reserved names such as "rowid". * The types can reflect numbers or text. * - * @param block + * @param handler * - * Pass a block that is one of the following types: - * - YapDatabaseSecondaryIndexWithKeyBlock - * - YapDatabaseSecondaryIndexWithObjectBlock - * - YapDatabaseSecondaryIndexWithMetadataBlock - * - YapDatabaseSecondaryIndexWithRowBlock - * - * @param blockType - * - * Pass the blockType enum that matches the passed block: - * - YapDatabaseSecondaryIndexBlockTypeWithKey - * - YapDatabaseSecondaryIndexBlockTypeWithObject - * - YapDatabaseSecondaryIndexBlockTypeWithMetadata - * - YapDatabaseSecondaryIndexBlockTypeWithRow + * The block (and blockType) that handles extracting secondary index information from a row in the database. * * @param version * @@ -137,11 +72,12 @@ typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { * initialization of the extension, then it will automatically re-create itself. * * @see YapDatabaseSecondaryIndexSetup + * @see YapDatabaseSecondaryIndexHandler + * * @see YapDatabase registerExtension:withName: **/ - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup - block:(YapDatabaseSecondaryIndexBlock)block - blockType:(YapDatabaseSecondaryIndexBlockType)blockType + handler:(YapDatabaseSecondaryIndexHandler *)handler versionTag:(NSString *)versionTag; /** @@ -154,21 +90,9 @@ typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { * The column names can be whatever you want, with a few exceptions for reserved names such as "rowid". * The types can reflect numbers or text. * - * @param block + * @param handler * - * Pass a block that is one of the following types: - * - YapDatabaseSecondaryIndexWithKeyBlock - * - YapDatabaseSecondaryIndexWithObjectBlock - * - YapDatabaseSecondaryIndexWithMetadataBlock - * - YapDatabaseSecondaryIndexWithRowBlock - * - * @param blockType - * - * Pass the blockType enum that matches the passed block: - * - YapDatabaseSecondaryIndexBlockTypeWithKey - * - YapDatabaseSecondaryIndexBlockTypeWithObject - * - YapDatabaseSecondaryIndexBlockTypeWithMetadata - * - YapDatabaseSecondaryIndexBlockTypeWithRow + * The block (and blockType) that handles extracting secondary index information from a row in the database. * * @param version * @@ -182,13 +106,41 @@ typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { * See the YapDatabaseSecondaryIndexOptions class for more information. * * @see YapDatabaseSecondaryIndexSetup + * @see YapDatabaseSecondaryIndexHandler + * * @see YapDatabase registerExtension:withName: **/ +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup + handler:(YapDatabaseSecondaryIndexHandler *)handler + versionTag:(NSString *)versionTag + options:(YapDatabaseSecondaryIndexOptions *)options; + +// +// Deprecated init methods : + +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup + block:(YapDatabaseSecondaryIndexBlock)block + blockType:(YapDatabaseSecondaryIndexBlockType)blockType +__attribute((deprecated("Use method initWithSetup:handler: instead"))); + - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup block:(YapDatabaseSecondaryIndexBlock)block blockType:(YapDatabaseSecondaryIndexBlockType)blockType versionTag:(NSString *)versionTag - options:(YapDatabaseSecondaryIndexOptions *)options; +__attribute((deprecated("Use method initWithSetup:handler:versionTag: instead"))); + +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)setup + block:(YapDatabaseSecondaryIndexBlock)block + blockType:(YapDatabaseSecondaryIndexBlockType)blockType + versionTag:(NSString *)versionTag + options:(YapDatabaseSecondaryIndexOptions *)options +__attribute((deprecated("Use method initWithSetup:handler:versionTag:options: instead"))); + +/* Inherited from YapDatabaseExtension + +@property (nonatomic, strong, readonly) NSString *registeredName; + +*/ /** * The versionTag assists in making changes to the extension. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m index a032e10..fc3ff92 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m @@ -63,23 +63,20 @@ } - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup - block:(YapDatabaseSecondaryIndexBlock)inBlock - blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType + handler:(YapDatabaseSecondaryIndexHandler *)inHandler { - return [self initWithSetup:inSetup block:inBlock blockType:inBlockType versionTag:nil options:nil]; + return [self initWithSetup:inSetup handler:inHandler versionTag:nil options:nil]; } - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup - block:(YapDatabaseSecondaryIndexBlock)inBlock - blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType + handler:(YapDatabaseSecondaryIndexHandler *)inHandler versionTag:(NSString *)inVersionTag { - return [self initWithSetup:inSetup block:inBlock blockType:inBlockType versionTag:inVersionTag options:nil]; + return [self initWithSetup:inSetup handler:inHandler versionTag:inVersionTag options:nil]; } - (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup - block:(YapDatabaseSecondaryIndexBlock)inBlock - blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType + handler:(YapDatabaseSecondaryIndexHandler *)inHandler versionTag:(NSString *)inVersionTag options:(YapDatabaseSecondaryIndexOptions *)inOptions { @@ -101,22 +98,11 @@ return nil; } - if (inBlock == NULL) + if (inHandler == NULL) { - NSAssert(NO, @"Invalid block: NULL"); + NSAssert(NO, @"Invalid handler: NULL"); - YDBLogError(@"%@: Invalid block: NULL", THIS_METHOD); - return nil; - } - - if (inBlockType != YapDatabaseSecondaryIndexBlockTypeWithKey && - inBlockType != YapDatabaseSecondaryIndexBlockTypeWithObject && - inBlockType != YapDatabaseSecondaryIndexBlockTypeWithMetadata && - inBlockType != YapDatabaseSecondaryIndexBlockTypeWithRow ) - { - NSAssert(NO, @"Invalid blockType"); - - YDBLogError(@"%@: Invalid blockType", THIS_METHOD); + YDBLogError(@"%@: Invalid handler: NULL", THIS_METHOD); return nil; } @@ -126,8 +112,8 @@ { setup = [inSetup copy]; - block = inBlock; - blockType = inBlockType; + block = inHandler.block; + blockType = inHandler.blockType; columnNamesSharedKeySet = [NSDictionary sharedKeySetForKeys:[setup columnNames]]; @@ -139,13 +125,48 @@ } /** - * Subclasses must implement this method. - * This method is called during the view registration process to enusre the extension supports - * the database configuration. + * DEPRECATED + * Use method initWithSetup:handler: instead. **/ -- (BOOL)supportsDatabase:(YapDatabase *)database withRegisteredExtensions:(NSDictionary *)registeredExtensions; +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup + block:(YapDatabaseSecondaryIndexBlock)inBlock + blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType { - return YES; + YapDatabaseSecondaryIndexHandler *handler = + [YapDatabaseSecondaryIndexHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithSetup:inSetup handler:handler]; +} + +/** + * DEPRECATED + * Use method initWithSetup:handler:versionTag: instead. +**/ +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup + block:(YapDatabaseSecondaryIndexBlock)inBlock + blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseSecondaryIndexHandler *handler = + [YapDatabaseSecondaryIndexHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithSetup:inSetup handler:handler versionTag:inVersionTag]; +} + +/** + * DEPRECATED + * Use method initWithSetup:handler:versionTag:options: instead. +**/ +- (id)initWithSetup:(YapDatabaseSecondaryIndexSetup *)inSetup + block:(YapDatabaseSecondaryIndexBlock)inBlock + blockType:(YapDatabaseSecondaryIndexBlockType)inBlockType + versionTag:(NSString *)inVersionTag + options:(YapDatabaseSecondaryIndexOptions *)inOptions +{ + YapDatabaseSecondaryIndexHandler *handler = + [YapDatabaseSecondaryIndexHandler withBlock:inBlock blockType:inBlockType]; + + return [self initWithSetup:inSetup handler:handler versionTag:inVersionTag options:inOptions]; } - (YapDatabaseExtensionConnection *)newConnection:(YapDatabaseConnection *)databaseConnection diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m index 3a0b1bc..75ea087 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m @@ -1,9 +1,11 @@ #import "YapDatabaseSecondaryIndexConnection.h" #import "YapDatabaseSecondaryIndexPrivate.h" +#import "YapDatabaseStatement.h" #import "YapDatabasePrivate.h" #import "YapDatabaseExtensionPrivate.h" +#import "YapDatabaseString.h" #import "YapDatabaseLogging.h" #if ! __has_feature(objc_arc) @@ -39,7 +41,9 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; databaseConnection = inDatabaseConnection; queryCacheLimit = 10; - queryCache = [[YapCache alloc] initWithKeyClass:[NSString class] countLimit:queryCacheLimit]; + queryCache = [[YapCache alloc] initWithCountLimit:queryCacheLimit]; + queryCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + queryCache.allowedObjectClasses = [NSSet setWithObject:[YapDatabaseStatement class]]; } return self; } @@ -114,7 +118,11 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; if (queryCacheEnabled) { if (queryCache == nil) - queryCache = [[YapCache alloc] initWithKeyClass:[NSString class] countLimit:queryCacheLimit]; + { + queryCache = [[YapCache alloc] initWithCountLimit:queryCacheLimit]; + queryCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + queryCache.allowedObjectClasses = [NSSet setWithObject:[YapDatabaseStatement class]]; + } } else { @@ -224,6 +232,21 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; #pragma mark Statements //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)prepareStatement:(sqlite3_stmt **)statement withString:(NSString *)stmtString caller:(SEL)caller_cmd +{ + sqlite3 *db = databaseConnection->db; + YapDatabaseString stmt; MakeYapDatabaseString(&stmt, stmtString); + + int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@: Error creating prepared statement: %d %s", + NSStringFromSelector(caller_cmd), status, sqlite3_errmsg(db)); + } + + FreeYapDatabaseString(&stmt); +} + - (sqlite3_stmt *)insertStatement { sqlite3_stmt **statement = &insertStatement; @@ -248,13 +271,7 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; [string appendString:@");"]; - sqlite3 *db = databaseConnection->db; - - int status = sqlite3_prepare_v2(db, [string UTF8String], -1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -284,13 +301,7 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; [string appendString:@");"]; - sqlite3 *db = databaseConnection->db; - - int status = sqlite3_prepare_v2(db, [string UTF8String], -1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -301,16 +312,10 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; sqlite3_stmt **statement = &removeStatement; if (*statement == NULL) { - NSString *string = - [NSString stringWithFormat:@"DELETE FROM \"%@\" WHERE \"rowid\" = ?;", [secondaryIndex tableName]]; + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\" WHERE \"rowid\" = ?;", [secondaryIndex tableName]]; - sqlite3 *db = databaseConnection->db; - - int status = sqlite3_prepare_v2(db, [string UTF8String], -1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -321,15 +326,10 @@ static const int ydbLogLevel = YDB_LOG_LEVEL_WARN; sqlite3_stmt **statement = &removeAllStatement; if (*statement == NULL) { - NSString *string = [NSString stringWithFormat:@"DELETE FROM \"%@\";", [secondaryIndex tableName]]; + NSString *string = [NSString stringWithFormat: + @"DELETE FROM \"%@\";", [secondaryIndex tableName]]; - sqlite3 *db = databaseConnection->db; - - int status = sqlite3_prepare_v2(db, [string UTF8String], -1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h new file mode 100644 index 0000000..0f50659 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.h @@ -0,0 +1,51 @@ +#import + + +/** + * Specifies the kind of block being used. +**/ +typedef NS_ENUM(NSInteger, YapDatabaseSecondaryIndexBlockType) { + YapDatabaseSecondaryIndexBlockTypeWithKey = 1031, + YapDatabaseSecondaryIndexBlockTypeWithObject = 1032, + YapDatabaseSecondaryIndexBlockTypeWithMetadata = 1033, + YapDatabaseSecondaryIndexBlockTypeWithRow = 1034 +}; + + +/** + * The handler block handles extracting the column values for the secondary indexes. + * + * When you add or update rows in the databse the block is invoked. + * Your block can inspect the row and determine if it contains any values that should be added to the secondary indexes. + * If not, the block can simply return. + * Otherwise the block should extract any values and add them to the given dictionary. + * + * After the block returns, the dictionary parameter will be inspected, + * and any set values will be automatically inserted/updated within the sqlite indexes. + * + * You should choose a block type that takes the minimum number of required parameters. + * The extension can make various optimizations based on required parameters of the block. + * For example, if metadata isn't required, then the extension can ignore metadata-only updates. +**/ +@interface YapDatabaseSecondaryIndexHandler : NSObject + +typedef id YapDatabaseSecondaryIndexBlock; // One of the YapDatabaseSecondaryIndexWith_X_Block types below. + +typedef void (^YapDatabaseSecondaryIndexWithKeyBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key); +typedef void (^YapDatabaseSecondaryIndexWithObjectBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id object); +typedef void (^YapDatabaseSecondaryIndexWithMetadataBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id metadata); +typedef void (^YapDatabaseSecondaryIndexWithRowBlock) \ + (NSMutableDictionary *dict, NSString *collection, NSString *key, id object, id metadata); + ++ (instancetype)withKeyBlock:(YapDatabaseSecondaryIndexWithKeyBlock)block; ++ (instancetype)withObjectBlock:(YapDatabaseSecondaryIndexWithObjectBlock)block; ++ (instancetype)withMetadataBlock:(YapDatabaseSecondaryIndexWithMetadataBlock)block; ++ (instancetype)withRowBlock:(YapDatabaseSecondaryIndexWithRowBlock)block; + +@property (nonatomic, strong, readonly) YapDatabaseSecondaryIndexBlock block; +@property (nonatomic, assign, readonly) YapDatabaseSecondaryIndexBlockType blockType; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.m b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.m new file mode 100644 index 0000000..ebf9223 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexHandler.m @@ -0,0 +1,68 @@ +#import "YapDatabaseSecondaryIndexHandler.h" + + +@implementation YapDatabaseSecondaryIndexHandler + +@synthesize block = block; +@synthesize blockType = blockType; + ++ (instancetype)withKeyBlock:(YapDatabaseSecondaryIndexWithKeyBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseSecondaryIndexHandler *handler = [[YapDatabaseSecondaryIndexHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseSecondaryIndexBlockTypeWithKey; + + return handler; +} + ++ (instancetype)withObjectBlock:(YapDatabaseSecondaryIndexWithObjectBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseSecondaryIndexHandler *handler = [[YapDatabaseSecondaryIndexHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseSecondaryIndexBlockTypeWithObject; + + return handler; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseSecondaryIndexWithMetadataBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseSecondaryIndexHandler *handler = [[YapDatabaseSecondaryIndexHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseSecondaryIndexBlockTypeWithMetadata; + + return handler; +} + ++ (instancetype)withRowBlock:(YapDatabaseSecondaryIndexWithRowBlock)block +{ + if (block == NULL) return nil; + + YapDatabaseSecondaryIndexHandler *handler = [[YapDatabaseSecondaryIndexHandler alloc] init]; + handler->block = block; + handler->blockType = YapDatabaseSecondaryIndexBlockTypeWithRow; + + return handler; +} + +/** + * Helper method for supporting deprecated methods. + * This method will disappear in the future. +**/ ++ (instancetype)withBlock:(YapDatabaseSecondaryIndexBlock)block blockType:(YapDatabaseSecondaryIndexBlockType)blockType +{ + if (block == NULL) return nil; + + YapDatabaseSecondaryIndexHandler *handler = [[YapDatabaseSecondaryIndexHandler alloc] init]; + handler->block = block; + handler->blockType = blockType; + + return handler; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h index 6688fa3..d277950 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.h @@ -1,16 +1,17 @@ #import +#import "YapWhitelistBlacklist.h" /** * Welcome to YapDatabase! - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * This class provides extra options when initializing YapDatabaseSecondaryIndex. * * For more information, see the wiki article about secondary indexes: - * https://github.com/yaptv/YapDatabase/wiki/Secondary-Indexes + * https://github.com/yapstudios/YapDatabase/wiki/Secondary-Indexes **/ @interface YapDatabaseSecondaryIndexOptions : NSObject @@ -35,6 +36,6 @@ * * The default value is nil. **/ -@property (nonatomic, copy, readwrite) NSSet *allowedCollections; +@property (nonatomic, strong, readwrite) YapWhitelistBlacklist *allowedCollections; @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m index 0e579be..c35b51d 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexOptions.m @@ -2,15 +2,15 @@ /** * Welcome to YapDatabase! - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * This class provides extra options when initializing YapDatabaseSecondaryIndex. * * For more information, see the wiki article about secondary indexes: - * https://github.com/yaptv/YapDatabase/wiki/Secondary-Indexes + * https://github.com/yapstudios/YapDatabase/wiki/Secondary-Indexes **/ @implementation YapDatabaseSecondaryIndexOptions diff --git a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m index 6de69fe..670a367 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m @@ -278,7 +278,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained YapDatabaseSecondaryIndex *secondaryIndex = secondaryIndexConnection->secondaryIndex; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; if (secondaryIndex->blockType == YapDatabaseSecondaryIndexBlockTypeWithKey) { @@ -297,10 +297,18 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - if (allowedCollections) { - [databaseTransaction _enumerateKeysInCollections:[allowedCollections allObjects] usingBlock:enumBlock]; + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; } - else { + else // if (!allowedCollections) + { [databaseTransaction _enumerateKeysInAllCollectionsUsingBlock:enumBlock]; } } @@ -321,11 +329,19 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - if (allowedCollections) { - [databaseTransaction _enumerateKeysAndObjectsInCollections:[allowedCollections allObjects] - usingBlock:enumBlock]; + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndObjectsInCollections:@[ collection ] + usingBlock:enumBlock]; + } + }]; } - else { + else // if (!allowedCollections) + { [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:enumBlock]; } } @@ -346,11 +362,19 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - if (allowedCollections) { - [databaseTransaction _enumerateKeysAndMetadataInCollections:[allowedCollections allObjects] - usingBlock:enumBlock]; + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndMetadataInCollections:@[ collection ] + usingBlock:enumBlock]; + } + }]; } - else { + else // if (!allowedCollections) + { [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:enumBlock]; } } @@ -371,10 +395,18 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - if (allowedCollections) { - [databaseTransaction _enumerateRowsInCollections:[allowedCollections allObjects] usingBlock:enumBlock]; + if (allowedCollections) + { + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateRowsInCollections:@[ collection ] usingBlock:enumBlock]; + } + }]; } - else { + else // if (!allowedCollections) + { [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:enumBlock]; } } @@ -641,7 +673,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; /** * Required override method from YapDatabaseExtension **/ -- (void)commitTransaction +- (void)didCommitTransaction { // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, @@ -655,7 +687,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; /** * Required override method from YapDatabaseExtension **/ -- (void)rollbackTransaction +- (void)didRollbackTransaction { // An extensionTransaction is only valid within the scope of its encompassing databaseTransaction. // I imagine this may occasionally be misunderstood, and developers may attempt to store the extension in an ivar, @@ -686,8 +718,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collection]) { return; } @@ -753,8 +785,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collection]) { return; } @@ -820,8 +852,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collection]) { return; } @@ -890,8 +922,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collection]) { return; } @@ -975,8 +1007,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained YapDatabaseSecondaryIndex *secondaryIndex = secondaryIndexConnection->secondaryIndex; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collectionKey.collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collectionKey.collection]) { return; } @@ -994,8 +1026,8 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained YapDatabaseSecondaryIndex *secondaryIndex = secondaryIndexConnection->secondaryIndex; - __unsafe_unretained NSSet *allowedCollections = secondaryIndex->options.allowedCollections; - if (allowedCollections && ![allowedCollections containsObject:collection]) + __unsafe_unretained YapWhitelistBlacklist *allowedCollections = secondaryIndex->options.allowedCollections; + if (allowedCollections && ![allowedCollections isAllowed:collection]) { return; } diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h index fe2f57c..70024c5 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h @@ -43,6 +43,22 @@ static NSString *const changeset_key_changes = @"changes"; #pragma mark - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +@interface YapDatabaseViewGrouping () + ++ (instancetype)withBlock:(YapDatabaseViewGroupingBlock)block blockType:(YapDatabaseViewBlockType)blockType; + +@end + +@interface YapDatabaseViewSorting () + ++ (instancetype)withBlock:(YapDatabaseViewSortingBlock)block blockType:(YapDatabaseViewBlockType)blockType; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @interface YapDatabaseView () { @protected @@ -126,6 +142,8 @@ static NSString *const changeset_key_changes = @"changes"; - (NSArray *)internalChangesetKeys; - (NSArray *)externalChangesetKeys; +- (void)prepareStatement:(sqlite3_stmt **)statement withString:(NSString *)stmtString caller:(SEL)caller_cmd; + - (sqlite3_stmt *)mapTable_getPageKeyForRowidStatement; - (sqlite3_stmt *)mapTable_setPageKeyForRowidStatement; - (sqlite3_stmt *)mapTable_removeForRowidStatement; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m index 8eff62b..a4deef0 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewState.m @@ -186,9 +186,14 @@ - (void)removeGroup:(NSString *)group { AssertIsMutable(); - NSAssert([[group_pagesMetadata_dict objectForKey:group] count] == 0, @"Attempting to remove non-empty group"); - [group_pagesMetadata_dict removeObjectForKey:group]; + NSUInteger count = [[group_pagesMetadata_dict objectForKey:group] count]; + NSAssert(count == 0, @"Attempting to remove non-empty group"); + + if (count == 0) + { + [group_pagesMetadata_dict removeObjectForKey:group]; + } } - (void)removeAllGroups diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h index 23654a4..d376b54 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h @@ -23,11 +23,11 @@ typedef NS_OPTIONS(NSUInteger, YapDatabaseViewChangesBitMask) { * which are designed to give you an overview of the various technologies available. * * General information about setting up and using Views: - * https://github.com/yaptv/YapDatabase/wiki/Views + * https://github.com/yapstudios/YapDatabase/wiki/Views * * General information about technologies which integrate with Views: - * https://github.com/yaptv/YapDatabase/wiki/LongLivedReadTransactions - * https://github.com/yaptv/YapDatabase/wiki/YapDatabaseModifiedNotification + * https://github.com/yapstudios/YapDatabase/wiki/LongLivedReadTransactions + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseModifiedNotification **/ @interface YapDatabaseViewSectionChange : NSObject @@ -181,7 +181,7 @@ typedef NS_OPTIONS(NSUInteger, YapDatabaseViewChangesBitMask) { * Once you have the sectionChanges & rowChanges, you can animate your tableView very simply like so: * * PS - For a FULL CODE EXAMPLE, see the wiki: - * https://github.com/yaptv/YapDatabase/wiki/Views#wiki-animating_updates_in_tableviews_collectionviews + * https://github.com/yapstudios/YapDatabase/wiki/Views#wiki-animating_updates_in_tableviews_collectionviews * * if ([sectionChanges count] == 0 & [rowChanges count] == 0) * { diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m index ca13897..1b0c133 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m @@ -3,6 +3,10 @@ #import "YapDatabaseViewMappingsPrivate.h" #import "YapDatabaseLogging.h" +#if TARGET_OS_IPHONE +#import +#endif + #if ! __has_feature(objc_arc) #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). #endif @@ -662,7 +666,7 @@ else if (rowChange->type == YapDatabaseViewChangeInsert) { // An INSERT operation may affect the ORIGINAL index value of operations that occurred AFTER it, - // IF the later operation occurs at a greater or equal index value. ( -1 ) + // IF the later operation occurs at a greater (but not equal) index value. ( -1 ) for (j = i; j < rowChangesCount; j++) { @@ -671,7 +675,7 @@ if (laterRowChange->type == YapDatabaseViewChangeDelete || laterRowChange->type == YapDatabaseViewChangeUpdate) { - if (laterRowChange->originalIndex >= rowChange->opFinalIndex && + if (laterRowChange->originalIndex > rowChange->opFinalIndex && [laterRowChange->originalGroup isEqualToString:rowChange->finalGroup]) { laterRowChange->originalIndex -= 1; @@ -713,7 +717,7 @@ else if (rowChange->type == YapDatabaseViewChangeInsert) { // An INSERT operation may affect the FINAL index value of operations that occurred BEFORE it, - // IF the earlier operation occurs at a greater index value ( +1 ) + // IF the earlier operation occurs at a greater or equal index value ( +1 ) for (j = i; j > 0; j--) { @@ -737,7 +741,7 @@ // The user may have various range options set for each group. // Here we update the range length & offset to match the basic changes made to the group. - __block BOOL rangeOptionsChanged = YES; + __block BOOL rangeOptionsChanged = NO; void (^UpdateRangeOptionsForGroup)(NSString *group); UpdateRangeOptionsForGroup = ^(NSString *group){ @@ -807,7 +811,7 @@ finalRangeLength = MIN(originalRangeOpts.maxLength, maxFinalRangeLength); } - else // if (rangeOpts.isFlexibleRange) + else // if (originalRangeOpts.isFlexibleRange) { // FLEXIBLE Range: // @@ -950,7 +954,9 @@ } // end else if (rangeOpts.isFlexibleRange) - if ((originalRangeLength != finalRangeLength) || (originalRangeOffset != finalRangeOffset)) + YapDatabaseViewRangeOptions *finalRangeOpts = [finalMappings _rangeOptionsForGroup:group]; + + if ((finalRangeLength != finalRangeOpts.length) || (finalRangeOffset != finalRangeOpts.offset)) { [finalMappings updateRangeOptionsForGroup:group withNewLength:finalRangeLength newOffset:finalRangeOffset]; rangeOptionsChanged = YES; @@ -1020,61 +1026,68 @@ __unsafe_unretained YapDatabaseViewRowChange *firstChangeForKey = _changes[i]; __unsafe_unretained YapDatabaseViewRowChange *mostRecentChangeForKey = firstChangeForKey; + NSUInteger mostRecentChangeForKey_OpIndex = 0; + + if (mostRecentChangeForKey->type == YapDatabaseViewChangeUpdate || + mostRecentChangeForKey->type == YapDatabaseViewChangeInsert) + mostRecentChangeForKey_OpIndex = mostRecentChangeForKey->opFinalIndex; + // Find later operations with the same key for (j = i+1; j < changesCount; j++) { - if ([indexesToRemove containsIndex:j]) continue; - __unsafe_unretained YapDatabaseViewRowChange *laterChange = _changes[j]; BOOL changesAreForSameKey = NO; - if (firstChangeForKey->collectionKey && laterChange->collectionKey) + if (![indexesToRemove containsIndex:j]) { - // Compare keys - - if (YapCollectionKeyEqual(laterChange->collectionKey, firstChangeForKey->collectionKey)) - changesAreForSameKey = YES; - } - else - { - // Compare indexes & groups - // - // This technique is used if one of the keys is nil, - // and applies to situations where one of the changes is an Update with a nil key, - // which was injected during pre-processing due to cell drawing dependencies. - - if (mostRecentChangeForKey->type == YapDatabaseViewChangeUpdate) + if (firstChangeForKey->collectionKey && laterChange->collectionKey) { - if (laterChange->type == YapDatabaseViewChangeUpdate || - laterChange->type == YapDatabaseViewChangeDelete) - { - if (mostRecentChangeForKey->originalIndex == laterChange->originalIndex && - [mostRecentChangeForKey->originalGroup isEqualToString:laterChange->originalGroup]) { - changesAreForSameKey = YES; - } - } - } - else if (mostRecentChangeForKey->type == YapDatabaseViewChangeInsert) - { - if (laterChange->type == YapDatabaseViewChangeUpdate) - { - if (mostRecentChangeForKey->originalIndex == laterChange->originalIndex && - [mostRecentChangeForKey->originalGroup isEqualToString:laterChange->originalGroup]) { - changesAreForSameKey = YES; - } - } - } - - if (changesAreForSameKey) - { - if (mostRecentChangeForKey->collectionKey == nil) - mostRecentChangeForKey->collectionKey = laterChange->collectionKey; - else - laterChange->collectionKey = mostRecentChangeForKey->collectionKey; + // Compare keys - if (firstChangeForKey->collectionKey == nil) - firstChangeForKey->collectionKey = mostRecentChangeForKey->collectionKey; + if (YapCollectionKeyEqual(laterChange->collectionKey, firstChangeForKey->collectionKey)) + changesAreForSameKey = YES; + } + else + { + // Compare indexes & groups + // + // This technique is used if one of the keys is nil, + // and applies to situations where one of the changes is an Update with a nil key, + // which was injected during pre-processing due to cell drawing dependencies. + + if (mostRecentChangeForKey->type == YapDatabaseViewChangeUpdate) + { + if (laterChange->type == YapDatabaseViewChangeUpdate || + laterChange->type == YapDatabaseViewChangeDelete) + { + if (mostRecentChangeForKey_OpIndex == laterChange->opOriginalIndex && + [mostRecentChangeForKey->originalGroup isEqualToString:laterChange->originalGroup]) { + changesAreForSameKey = YES; + } + } + } + else if (mostRecentChangeForKey->type == YapDatabaseViewChangeInsert) + { + if (laterChange->type == YapDatabaseViewChangeUpdate) + { + if (mostRecentChangeForKey_OpIndex == laterChange->opOriginalIndex && + [mostRecentChangeForKey->finalGroup isEqualToString:laterChange->finalGroup]) { + changesAreForSameKey = YES; + } + } + } + + if (changesAreForSameKey) + { + if (mostRecentChangeForKey->collectionKey == nil) + mostRecentChangeForKey->collectionKey = laterChange->collectionKey; + else + laterChange->collectionKey = mostRecentChangeForKey->collectionKey; + + if (firstChangeForKey->collectionKey == nil) + firstChangeForKey->collectionKey = mostRecentChangeForKey->collectionKey; + } } } @@ -1084,8 +1097,38 @@ [indexesThatMatch addIndex:j]; mostRecentChangeForKey = laterChange; + + if (mostRecentChangeForKey->type == YapDatabaseViewChangeUpdate || + mostRecentChangeForKey->type == YapDatabaseViewChangeInsert) + mostRecentChangeForKey_OpIndex = mostRecentChangeForKey->opFinalIndex; + else + mostRecentChangeForKey_OpIndex = 0; } - } + else + { + if (mostRecentChangeForKey->type == YapDatabaseViewChangeUpdate || + mostRecentChangeForKey->type == YapDatabaseViewChangeInsert) + { + if (laterChange->type == YapDatabaseViewChangeInsert) + { + if (laterChange->opFinalIndex <= mostRecentChangeForKey_OpIndex && + [laterChange->finalGroup isEqualToString:mostRecentChangeForKey->finalGroup]) + { + mostRecentChangeForKey_OpIndex++; + } + } + else if (laterChange->type == YapDatabaseViewChangeDelete) + { + if (laterChange->opOriginalIndex < mostRecentChangeForKey_OpIndex && + [laterChange->originalGroup isEqualToString:mostRecentChangeForKey->finalGroup]) + { + mostRecentChangeForKey_OpIndex--; + } + } + } + } + + } // end for (j = i+1; j < changesCount; j++) if ([indexesThatMatch count] > 0) { @@ -1386,7 +1429,7 @@ // The user has a hard range on group "fiction" in the "bookSalesRank" view in order to display the top 20. // So any items outside of that range must be filtered. - __block BOOL rangeOptionsChanged = YES; + __block BOOL rangeOptionsChanged = NO; void (^ApplyRangeOptionsForGroup)(NSString *group); ApplyRangeOptionsForGroup = ^(NSString *group) @@ -2026,7 +2069,7 @@ // // STEP 4.A : Update finalMappings if needed (by updating rangeOpts.length & rangeOpts.offset) - if ((originalRangeLength != finalRangeLength) || (originalRangeOffset != finalRangeOffset)) + if ((finalRangeLength != finalRangeOpts.length) || (finalRangeOffset != finalRangeOpts.offset)) { [finalMappings updateRangeOptionsForGroup:group withNewLength:finalRangeLength newOffset:finalRangeOffset]; rangeOptionsChanged = YES; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h index f321d50..ee52d7e 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h @@ -6,19 +6,19 @@ /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseView is an extension designed to work with YapDatabase. * It gives you a persistent sorted "view" of a configurable subset of your data. * * For the full documentation on Views, please see the related wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Views + * https://github.com/yapstudios/YapDatabase/wiki/Views * * There is also an entire section that details YapDatabaseViewMappings: - * https://github.com/yaptv/YapDatabase/wiki/Views#mappings + * https://github.com/yapstudios/YapDatabase/wiki/Views#mappings * * YapDatabaseViewMappings helps you map from groups to sections. * Let's take a look at a concrete example: @@ -117,12 +117,12 @@ * * for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * for (YapDatabaseViewRowChange *rowChange in rowChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * [self.tableView endUpdates]; @@ -831,12 +831,12 @@ typedef NSComparisonResult (^YapDatabaseViewMappingGroupSort)(NSString *group1, * * for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * for (YapDatabaseViewRowChange *rowChange in rowChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * [self.tableView endUpdates]; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m index 34d90ed..0d4c3b3 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m @@ -4,6 +4,10 @@ #import "YapDatabasePrivate.h" #import "YapDatabaseLogging.h" +#if TARGET_OS_IPHONE +#import +#endif + #if ! __has_feature(objc_arc) #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). #endif @@ -349,7 +353,7 @@ @" YapDatabaseModifiedNotifications. This ensures that the data-source for your UI remains in a steady" @" state at all times, and that updates are properly handled using the appropriate update mechanisms" @" (and properly animated if desired)." - @" For example code, please see the wiki: https://github.com/yaptv/YapDatabase/wiki/Views"; + @" For example code, please see the wiki: https://github.com/yapstudios/YapDatabase/wiki/Views"; NSString *suggestion = @"You must invoke [databaseConnection beginLongLivedReadTransaction] before you initialize the mappings"; @@ -1499,12 +1503,12 @@ * * for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * for (YapDatabaseViewRowChange *rowChange in rowChanges) * { - * // ... (see https://github.com/yaptv/YapDatabase/wiki/Views ) + * // ... (see https://github.com/yapstudios/YapDatabase/wiki/Views ) * } * * [self.tableView endUpdates]; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h index 7fe9e61..c4c4fce 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h @@ -12,19 +12,16 @@ /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseView is an extension designed to work with YapDatabase. * It gives you a persistent sorted "view" of a configurable subset of your data. * * For the full documentation on Views, please see the related wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Views - * - * Just in case you don't have Internet access, - * see the quick overview in YapDatabaseView.h. + * https://github.com/yapstudios/YapDatabase/wiki/Views **/ @interface YapDatabaseView : YapDatabaseExtension @@ -36,31 +33,21 @@ /** * See the wiki for an example of how to initialize a view: - * https://github.com/yaptv/YapDatabase/wiki/Views#wiki-initializing_a_view + * https://github.com/yapstudios/YapDatabase/wiki/Views#wiki-initializing_a_view * - * @param groupingBlock + * @param grouping * * The grouping block handles both filtering and grouping. + * There are multiple groupingBlock types that are supported. * - * @see YapDatabaseViewTypes.h for block type definition(s). + * @see YapDatabaseViewTypes.h for block type definitions. * - * @param groupingBlockType - * - * Specify the type of groupingBlock that is being passed. - * - * @see YapDatabaseViewTypes.h for block type definition(s). - * - * @param sortingBlock + * @param sorting * * The sorting block handles sorting of objects within their group. + * There are multiple sortingBlock types that are supported. * - * @see YapDatabaseViewTypes.h for block type definition(s). - * - * @param sortingBlockType - * - * Specify the type of sortingBlock that is being passed. - * - * @see YapDatabaseViewTypes.h for block type definition(s). + * @see YapDatabaseViewTypes.h for block type definitions. * * @param versionTag * @@ -73,23 +60,38 @@ * The options allow you to specify things like creating an in-memory-only view (non persistent). **/ -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock - groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock - sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType; +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting; + +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)versionTag; + +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)versionTag + options:(YapDatabaseViewOptions *)options; - (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType - versionTag:(NSString *)versionTag; +__attribute((deprecated("Use method initWithGrouping:sorting: instead"))); - (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType versionTag:(NSString *)versionTag - options:(YapDatabaseViewOptions *)options; +__attribute((deprecated("Use method initWithGrouping:sorting:versionTag: instead"))); + +- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock + groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType + sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock + sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType + versionTag:(NSString *)versionTag + options:(YapDatabaseViewOptions *)options +__attribute((deprecated("Use method initWithGrouping:sorting:versionTag:options: instead"))); @property (nonatomic, strong, readonly) YapDatabaseViewGroupingBlock groupingBlock; @property (nonatomic, strong, readonly) YapDatabaseViewSortingBlock sortingBlock; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m index 26d752c..ae707b2 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m @@ -100,62 +100,40 @@ #pragma mark Init -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting { - return [self initWithGroupingBlock:inGroupingBlock - groupingBlockType:inGroupingBlockType - sortingBlock:inSortingBlock - sortingBlockType:inSortingBlockType - versionTag:nil - options:nil]; + return [self initWithGrouping:grouping + sorting:sorting + versionTag:nil + options:nil]; } -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType - versionTag:(NSString *)inVersionTag +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)inVersionTag { - return [self initWithGroupingBlock:inGroupingBlock - groupingBlockType:inGroupingBlockType - sortingBlock:inSortingBlock - sortingBlockType:inSortingBlockType - versionTag:inVersionTag - options:nil]; + return [self initWithGrouping:grouping + sorting:sorting + versionTag:inVersionTag + options:nil]; } -- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)inGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)inGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)inSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)inSortingBlockType - versionTag:(NSString *)inVersionTag - options:(YapDatabaseViewOptions *)inOptions +- (instancetype)initWithGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)inVersionTag + options:(YapDatabaseViewOptions *)inOptions { - NSAssert(inGroupingBlock != NULL, @"Invalid grouping block"); - NSAssert(inSortingBlock != NULL, @"Invalid sorting block"); - - NSAssert(inGroupingBlockType == YapDatabaseViewBlockTypeWithKey || - inGroupingBlockType == YapDatabaseViewBlockTypeWithObject || - inGroupingBlockType == YapDatabaseViewBlockTypeWithMetadata || - inGroupingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid grouping block type"); - - NSAssert(inSortingBlockType == YapDatabaseViewBlockTypeWithKey || - inSortingBlockType == YapDatabaseViewBlockTypeWithObject || - inSortingBlockType == YapDatabaseViewBlockTypeWithMetadata || - inSortingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid sorting block type"); + NSAssert(grouping != NULL, @"Invalid parameter: grouping == nil"); + NSAssert(sorting != NULL, @"Invalid parameter: sorting == nil"); if ((self = [super init])) { - groupingBlock = inGroupingBlock; - groupingBlockType = inGroupingBlockType; + groupingBlock = grouping.groupingBlock; + groupingBlockType = grouping.groupingBlockType; - sortingBlock = inSortingBlock; - sortingBlockType = inSortingBlockType; + sortingBlock = sorting.sortingBlock; + sortingBlockType = sorting.sortingBlockType; versionTag = inVersionTag ? [inVersionTag copy] : @""; @@ -164,6 +142,63 @@ return self; } +/** + * DEPRECATED + * Replaced by [YapDatabaseView initWithGrouping:sorting:] +**/ +- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + return [self initWithGrouping:grouping + sorting:sorting + versionTag:nil + options:nil]; +} + +/** + * DEPRECATED + * Replaced by [YapDatabaseView initWithGrouping:sorting:versionTag:] +**/ +- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + return [self initWithGrouping:grouping + sorting:sorting + versionTag:inVersionTag + options:nil]; +} + +/** + * DEPRECATED + * Replaced by [YapDatabaseView initWithGrouping:sorting:versionTag:options:] +**/ +- (id)initWithGroupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType + versionTag:(NSString *)inVersionTag + options:(YapDatabaseViewOptions *)inOptions +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + return [self initWithGrouping:grouping + sorting:sorting + versionTag:inVersionTag + options:inOptions]; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Custom Getters //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -313,16 +348,6 @@ #pragma mark YapDatabaseExtension Protocol //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Subclasses must implement this method. - * This method is called during the view registration process to enusre the extension supports - * the database configuration. -**/ -- (BOOL)supportsDatabase:(YapDatabase *)database withRegisteredExtensions:(NSDictionary *)registeredExtensions -{ - return YES; -} - /** * Subclasses MUST implement this method IF they are non-persistent (in-memory only). * By doing so, they allow various optimizations, such as not persisting extension info in the yap2 table. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h index 917cfd8..eefa5dd 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h @@ -9,16 +9,16 @@ /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseView is an extension designed to work with YapDatabase. * It gives you a persistent sorted "view" of a configurable subset of your data. * * For the full documentation on Views, please see the related wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Views + * https://github.com/yapstudios/YapDatabase/wiki/Views * * * As a extension, YapDatabaseViewConnection is automatically created by YapDatabaseConnnection. diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m index 44809a7..605091c 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m @@ -71,8 +71,13 @@ view = inView; databaseConnection = inDbC; - mapCache = [[YapCache alloc] initWithKeyClass:[NSNumber class]]; - pageCache = [[YapCache alloc] initWithKeyClass:[NSString class]]; + mapCache = [[YapCache alloc] initWithCountLimit:100]; + mapCache.allowedKeyClasses = [NSSet setWithObject:[NSNumber class]]; + mapCache.allowedObjectClasses = [NSSet setWithObjects:[NSString class], [NSNull class], nil]; + + pageCache = [[YapCache alloc] initWithCountLimit:40]; + pageCache.allowedKeyClasses = [NSSet setWithObject:[NSString class]]; + pageCache.allowedObjectClasses = [NSSet setWithObjects:[YapDatabaseViewPage class], nil]; sharedKeySetForInternalChangeset = [NSDictionary sharedKeySetForKeys:[self internalChangesetKeys]]; sharedKeySetForExternalChangeset = [NSDictionary sharedKeySetForKeys:[self externalChangesetKeys]]; @@ -239,7 +244,7 @@ [changes removeAllObjects]; // Don't keep cached blocks in memory. - // These are loaded on-demand withing readwrite transactions. + // These are loaded on-demand within readwrite transactions. groupingBlock = NULL; groupingBlockType = 0; sortingBlock = NULL; @@ -407,10 +412,10 @@ } else if ([changeset_dirtyMaps count] > 0) { - NSUInteger removeCapacity = [mapCache count]; + NSUInteger removeCapacity = changeset_reset ? [mapCache count] : 0; NSUInteger updateCapacity = MIN([mapCache count], [changeset_dirtyMaps count]); - NSMutableArray *keysToRemove = [NSMutableArray arrayWithCapacity:removeCapacity]; + NSMutableArray *keysToRemove = changeset_reset ? [NSMutableArray arrayWithCapacity:removeCapacity] : nil; NSMutableArray *keysToUpdate = [NSMutableArray arrayWithCapacity:updateCapacity]; [mapCache enumerateKeysWithBlock:^(id key, BOOL *stop) { @@ -450,10 +455,10 @@ } else if ([changeset_dirtyPages count]) { - NSUInteger removeCapacity = [pageCache count]; + NSUInteger removeCapacity = changeset_reset ? [pageCache count] : 0; NSUInteger updateCapacity = MIN([pageCache count], [changeset_dirtyPages count]); - NSMutableArray *keysToRemove = [NSMutableArray arrayWithCapacity:removeCapacity]; + NSMutableArray *keysToRemove = changeset_reset ? [NSMutableArray arrayWithCapacity:removeCapacity] : nil; NSMutableArray *keysToUpdate = [NSMutableArray arrayWithCapacity:updateCapacity]; [pageCache enumerateKeysWithBlock:^(id key, BOOL *stop) { @@ -522,7 +527,7 @@ @" You need to invoke [mappings updateWithTransaction:transaction] once in order to initialize" @" the mappings object. You should do this after invoking" @" [databaseConnection beginLongLivedReadTransaction]. For example code, please see" - @" YapDatabaseViewMappings.h, or see the wiki: https://github.com/yaptv/YapDatabase/wiki/Views"}; + @" YapDatabaseViewMappings.h, or see the wiki: https://github.com/yapstudios/YapDatabase/wiki/Views"}; @throw [NSException exceptionWithName:@"YapDatabaseException" reason:reason userInfo:userInfo]; } @@ -585,8 +590,8 @@ NSString *failureReason = [NSString stringWithFormat: @"preMappings.snapshotOfLastUpdate: expected(%llu) != found(%llu), " @"postMappings.snapshotOfLastUpdate: expected(%llu) != found(%llu), ", - originalMappings.snapshotOfLastUpdate, (firstSnapshot - 1), - mappings.snapshotOfLastUpdate, lastSnapshot]; + (firstSnapshot - 1), originalMappings.snapshotOfLastUpdate, + lastSnapshot, mappings.snapshotOfLastUpdate]; NSString *suggestion = [NSString stringWithFormat: @"When you initialize the database, the snapshot (uint64) is set to zero." @@ -618,7 +623,7 @@ // then you need to follow the instructions for setting up your connection, mappings, & notifications. // // For complete code samples, check out the wiki: - // https://github.com/yaptv/YapDatabase/wiki/Views + // https://github.com/yapstudios/YapDatabase/wiki/Views // // You may be tempted to simply comment out the exception below. // If you do, you're not fixing the root cause of your problem. @@ -632,7 +637,7 @@ exception, failureReason, suggestion); // For more help, go here: - // https://github.com/yaptv/YapDatabase/wiki/Views#managing-mappings + // https://github.com/yapstudios/YapDatabase/wiki/Views#managing-mappings @throw exception; } @@ -699,7 +704,7 @@ __unsafe_unretained YapDatabaseViewRowChange *rowChange = (YapDatabaseViewRowChange *)change; - if ([rowChange->originalGroup isEqualToString:group]) + if ([rowChange->originalGroup isEqualToString:group] || [rowChange->finalGroup isEqualToString:group]) { return YES; } @@ -743,7 +748,7 @@ __unsafe_unretained YapDatabaseViewRowChange *rowChange = (YapDatabaseViewRowChange *)change; - if ([groups containsObject:rowChange->originalGroup]) + if ([groups containsObject:rowChange->originalGroup] || [groups containsObject:rowChange->finalGroup]) { return YES; } @@ -776,6 +781,25 @@ return count; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Statements - Utilities +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)prepareStatement:(sqlite3_stmt **)statement withString:(NSString *)stmtString caller:(SEL)caller_cmd +{ + sqlite3 *db = databaseConnection->db; + YapDatabaseString stmt; MakeYapDatabaseString(&stmt, stmtString); + + int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@: Error creating prepared statement: %d %s", + NSStringFromSelector(caller_cmd), status, sqlite3_errmsg(db)); + } + + FreeYapDatabaseString(&stmt); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Statements - KeyTable //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -790,16 +814,7 @@ NSString *string = [NSString stringWithFormat: @"SELECT \"pageKey\" FROM \"%@\" WHERE \"rowid\" = ?;", [view mapTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -815,16 +830,7 @@ NSString *string = [NSString stringWithFormat: @"INSERT OR REPLACE INTO \"%@\" (\"rowid\", \"pageKey\") VALUES (?, ?);", [view mapTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -840,16 +846,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\" WHERE \"rowid\" = ?;", [view mapTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -865,16 +862,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\";", [view mapTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -894,16 +882,7 @@ NSString *string = [NSString stringWithFormat: @"SELECT \"data\" FROM \"%@\" WHERE \"pageKey\" = ?;", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -921,16 +900,7 @@ @" (\"pageKey\", \"group\", \"prevPageKey\", \"count\", \"data\") VALUES (?, ?, ?, ?, ?);", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -947,16 +917,7 @@ @"UPDATE \"%@\" SET \"prevPageKey\" = ?, \"count\" = ?, \"data\" = ? WHERE \"pageKey\" = ?;", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -972,16 +933,7 @@ NSString *string = [NSString stringWithFormat: @"UPDATE \"%@\" SET \"count\" = ?, \"data\" = ? WHERE \"pageKey\" = ?;", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -997,16 +949,7 @@ NSString *string = [NSString stringWithFormat: @"UPDATE \"%@\" SET \"prevPageKey\" = ? WHERE \"pageKey\" = ?;", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -1022,16 +965,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\" WHERE \"pageKey\" = ?;", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; @@ -1047,16 +981,7 @@ NSString *string = [NSString stringWithFormat: @"DELETE FROM \"%@\";", [view pageTableName]]; - sqlite3 *db = databaseConnection->db; - YapDatabaseString stmt; MakeYapDatabaseString(&stmt, string); - - int status = sqlite3_prepare_v2(db, stmt.str, stmt.length+1, statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@: Error creating prepared statement: %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); - } - - FreeYapDatabaseString(&stmt); + [self prepareStatement:statement withString:string caller:_cmd]; } return *statement; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h index 73a8291..441d936 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h @@ -1,18 +1,19 @@ #import +#import "YapWhitelistBlacklist.h" /** * Welcome to YapDatabase! * - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * The project wiki has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseView is an extension designed to work with YapDatabase. * It gives you a persistent sorted "view" of a configurable subset of your data. * * For the full documentation on Views, please see the related wiki article: - * https://github.com/yaptv/YapDatabase/wiki/Views + * https://github.com/yapstudios/YapDatabase/wiki/Views **/ @interface YapDatabaseViewOptions : NSObject @@ -58,6 +59,13 @@ * * The default value is nil. **/ -@property (nonatomic, copy, readwrite) NSSet *allowedCollections; +@property (nonatomic, strong, readwrite) YapWhitelistBlacklist *allowedCollections; + +/** + * You can configure the view to skip the initial view population. + * + * The default value is NO. +**/ +@property (nonatomic, assign, readwrite) BOOL skipInitialViewPopulation; @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m index 2d7742e..bf6bb3e 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m @@ -5,6 +5,7 @@ @synthesize isPersistent = isPersistent; @synthesize allowedCollections = allowedCollections; +@synthesize skipInitialViewPopulation = skipInitialViewPopulation; - (id)init { @@ -20,7 +21,8 @@ YapDatabaseViewOptions *copy = [[[self class] alloc] init]; // [self class] required to support subclassing copy->isPersistent = isPersistent; copy->allowedCollections = allowedCollections; - + copy->skipInitialViewPopulation = skipInitialViewPopulation; + return copy; } diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h index fb3af3c..da46216 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h @@ -8,16 +8,16 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to check out the wiki - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * YapDatabaseView is an extension designed to work with YapDatabase. * It gives you a persistent sorted "view" of a configurable subset of your data. * * For more information, please see the wiki article about Views: - * https://github.com/yaptv/YapDatabase/wiki/Views + * https://github.com/yapstudios/YapDatabase/wiki/Views * * You may also wish to consult the documentation in YapDatabaseView.h for information on setting up a view. * @@ -69,8 +69,15 @@ **/ - (NSUInteger)numberOfItemsInAllGroups; +/** + * Returns YES if the group is empty (has zero items). + * Shorthand for: [[transaction ext:viewName] numberOfItemsInGroup:group] == 0 +**/ +- (BOOL)isEmptyGroup:(NSString *)group; + /** * Returns YES if the view is empty (has zero groups). + * Shorthand for: [[transaction ext:viewName] numberOfItemsInAllGroups] == 0 **/ - (BOOL)isEmpty; @@ -345,16 +352,21 @@ typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \ - (void)touchMetadataForKey:(NSString *)key inCollection:(NSString *)collection; /** - * This method allows you to change the groupingBlock and/or sortingBlock on-the-fly. + * This method allows you to change the grouping and/or sorting on-the-fly. * * Note: You must pass a different versionTag, or this method does nothing. * If needed, you can fetch the current versionTag via the [viewTransaction versionTag] method. **/ +- (void)setGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)versionTag; + - (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)groupingBlock groupingBlockType:(YapDatabaseViewBlockType)groupingBlockType sortingBlock:(YapDatabaseViewSortingBlock)sortingBlock sortingBlockType:(YapDatabaseViewBlockType)sortingBlockType - versionTag:(NSString *)versionTag; + versionTag:(NSString *)versionTag +__attribute((deprecated("Use method setGrouping:sorting:versionTag: instead"))); @end @@ -433,10 +445,10 @@ typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \ - (void)enumerateKeysAndMetadataInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: - (void (^)(NSString *collection, NSString *key, id metadata, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter; + (void (^)(NSString *collection, NSString *key, id metadata, NSUInteger index, BOOL *stop))block; /** * The following methods are similar to invoking the enumerateKeysInGroup:... methods, @@ -461,10 +473,10 @@ typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \ - (void)enumerateKeysAndObjectsInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: - (void (^)(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter; + (void (^)(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop))block; /** * The following methods are similar to invoking the enumerateKeysInGroup:... methods, @@ -489,10 +501,10 @@ typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \ - (void)enumerateRowsInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: - (void (^)(NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter; + (void (^)(NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop))block; @end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m index 32ccca1..0b6bfec 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m @@ -11,6 +11,10 @@ #import "YapDatabaseString.h" #import "YapDatabaseLogging.h" +#if TARGET_OS_IPHONE +#import +#endif + #if ! __has_feature(objc_arc) #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). #endif @@ -116,7 +120,11 @@ static NSString *const ExtKey_version_deprecated = @"version"; // So we can skip all the checks because we know we need to create the memory tables. if (![self createTables]) return NO; - if (![self populateView]) return NO; + + if (!viewConnection->view->options.skipInitialViewPopulation) + { + if (![self populateView]) return NO; + } // Store initial versionTag in prefs table @@ -162,7 +170,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; // First time registration needsCreateTables = YES; - needsPopulateView = YES; + needsPopulateView = !viewConnection->view->options.skipInitialViewPopulation; } else if (oldClassVersion != classVersion) { @@ -170,7 +178,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; [self dropTablesForOldClassVersion:oldClassVersion]; needsCreateTables = YES; - needsPopulateView = YES; + needsPopulateView = YES; // Not initialViewPopulation, but rather codebase upgrade. } // Create the database tables (if needed) @@ -211,7 +219,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; if (![oldVersionTag isEqualToString:versionTag]) { - needsPopulateView = YES; + needsPopulateView = YES; // Not initialViewPopulation, but rather versionTag upgrade. } } @@ -751,12 +759,17 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateRowsInCollections:[allowedCollections allObjects] usingBlock:block]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *outerStop) { + + if ([allowedCollections isAllowed:collection]) { + [databaseTransaction _enumerateRowsInCollections:@[ collection ] usingBlock:block]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:block]; } @@ -787,14 +800,20 @@ static NSString *const ExtKey_version_deprecated = @"version"; inGroup:group withChanges:flags isNew:YES]; }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateRowsInCollections:[allowedCollections allObjects] - usingBlock:block - withFilter:filter]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateRowsInCollections:@[ collection ] + usingBlock:block + withFilter:filter]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateRowsInAllCollectionsUsingBlock:block withFilter:filter]; } @@ -820,13 +839,19 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateKeysAndObjectsInCollections:[allowedCollections allObjects] - usingBlock:block]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndObjectsInCollections:@[ collection ] + usingBlock:block]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:block]; } @@ -857,14 +882,20 @@ static NSString *const ExtKey_version_deprecated = @"version"; inGroup:group withChanges:flags isNew:YES]; }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateKeysAndObjectsInCollections:[allowedCollections allObjects] - usingBlock:block - withFilter:filter]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndObjectsInCollections:@[ collection ] + usingBlock:block + withFilter:filter]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateKeysAndObjectsInAllCollectionsUsingBlock:block withFilter:filter]; } @@ -891,13 +922,19 @@ static NSString *const ExtKey_version_deprecated = @"version"; }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateKeysAndMetadataInCollections:[allowedCollections allObjects] - usingBlock:block]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndMetadataInCollections:@[ collection ] + usingBlock:block]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:block]; } @@ -928,14 +965,20 @@ static NSString *const ExtKey_version_deprecated = @"version"; inGroup:group withChanges:flags isNew:YES]; }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateKeysAndMetadataInCollections:[allowedCollections allObjects] - usingBlock:block - withFilter:filter]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysAndMetadataInCollections:@[ collection ] + usingBlock:block + withFilter:filter]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateKeysAndMetadataInAllCollectionsUsingBlock:block withFilter:filter]; } @@ -959,12 +1002,18 @@ static NSString *const ExtKey_version_deprecated = @"version"; } }; - NSSet *allowedCollections = viewConnection->view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = viewConnection->view->options.allowedCollections; if (allowedCollections) { - [databaseTransaction _enumerateKeysInCollections:[allowedCollections allObjects] usingBlock:block]; + [databaseTransaction enumerateCollectionsUsingBlock:^(NSString *collection, BOOL *stop) { + + if ([allowedCollections isAllowed:collection]) + { + [databaseTransaction _enumerateKeysInCollections:@[ collection ] usingBlock:block]; + } + }]; } - else + else // if (!allowedCollections) { [databaseTransaction _enumerateKeysInAllCollectionsUsingBlock:block]; } @@ -1118,7 +1167,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; pageKey = [viewConnection->dirtyMaps objectForKey:rowidNumber]; if (pageKey) { - if ((__bridge void *)pageKey == (__bridge void *)[NSNull null]) + if ((id)pageKey == (id)[NSNull null]) return nil; else return pageKey; @@ -1127,7 +1176,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; pageKey = [viewConnection->mapCache objectForKey:rowidNumber]; if (pageKey) { - if ((__bridge void *)pageKey == (__bridge void *)[NSNull null]) + if ((id)pageKey == (id)[NSNull null]) return nil; else return pageKey; @@ -1194,133 +1243,197 @@ static NSString *const ExtKey_version_deprecated = @"version"; **/ - (NSDictionary *)pageKeysForRowids:(NSArray **)rowidsPtr withKeyMappings:(NSDictionary *)keyMappings { - NSArray *rowids = *rowidsPtr; - NSMutableArray *outRowids = [NSMutableArray arrayWithCapacity:[rowids count]]; - - NSUInteger count = [rowids count]; - if (count == 0) + if ([*rowidsPtr count] == 0) { - *rowidsPtr = outRowids; + *rowidsPtr = [NSArray array]; return [NSDictionary dictionary]; } - NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:count]; + NSMutableArray *inRowids = [*rowidsPtr mutableCopy]; + NSMutableArray *outRowids = [NSMutableArray arrayWithCapacity:[inRowids count]]; - if ([self isPersistentView]) + NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[inRowids count]]; + + // Step 1 of 2: + // + // Check for any (rowid, pageKey) information we already have in memory. + // + // This is actually a requirement if the information is in dirtyMaps. + // If the info is in mapCache, then its just an optimization. + + for (NSUInteger iPlusOne = [inRowids count]; iPlusOne > 0; iPlusOne--) { - sqlite3 *db = databaseTransaction->connection->db; + NSUInteger i = iPlusOne - 1; + NSNumber *rowidNumber = [inRowids objectAtIndex:i]; - // Note: - // The handleRemoveObjectsForKeys:inCollection:withRowids: has the following guarantee: - // count <= (SQLITE_LIMIT_VARIABLE_NUMBER - 1) - // - // So we don't have to worry about sqlite's upper bound on host parameters. + NSString *pageKey = nil; - // SELECT "rowid", "pageKey" FROM "mapTableName" WHERE "rowid" IN (?, ?, ...); - - NSUInteger capacity = 50 + (count * 3); - NSMutableString *query = [NSMutableString stringWithCapacity:capacity]; - - [query appendFormat:@"SELECT \"rowid\", \"pageKey\" FROM \"%@\" WHERE \"rowid\" IN (", [self mapTableName]]; - - for (NSUInteger i = 0; i < count; i++) + pageKey = [viewConnection->dirtyMaps objectForKey:rowidNumber]; + if (pageKey == nil) { - if (i == 0) - [query appendFormat:@"?"]; + pageKey = [viewConnection->mapCache objectForKey:rowidNumber]; + } + + if (pageKey) + { + if ((id)pageKey == (id)[NSNull null]) + { + // This rowid has already been removed from the view, + // and is marked for deletion from the mapTable. + // + // However, it has not been deleted yet, as that will occur during flushPendingChangesToExtensionTables. + // So we need to remove it from inRowids, as the mapTable will still contain the rowid. + + [inRowids removeObjectAtIndex:i]; + } else - [query appendFormat:@", ?"]; - } - - [query appendString:@");"]; - - sqlite3_stmt *statement; - int status; - - status = sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL); - if (status != SQLITE_OK) - { - YDBLogError(@"%@ (%@): Error creating statement\n" - @" - status(%d), errmsg: %s\n" - @" - query: %@", - THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db), query); - - *rowidsPtr = nil; - return nil; - } - - for (NSUInteger i = 0; i < count; i++) - { - int64_t rowid = [[rowids objectAtIndex:i] longLongValue]; - - sqlite3_bind_int64(statement, (int)(i + 1), rowid); - } - - while ((status = sqlite3_step(statement)) == SQLITE_ROW) - { - // Extract rowid & pageKey from row - - int64_t rowid = sqlite3_column_int64(statement, 0); - - const unsigned char *text = sqlite3_column_text(statement, 1); - int textSize = sqlite3_column_bytes(statement, 1); - - NSNumber *rowidNumber = @(rowid); - NSString *pageKey = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding]; - - // Add to result dictionary - - NSMutableDictionary *subKeyMappings = [result objectForKey:pageKey]; - if (subKeyMappings == nil) { - subKeyMappings = [NSMutableDictionary dictionaryWithCapacity:1]; - [result setObject:subKeyMappings forKey:pageKey]; - } - - YapCollectionKey *collectionKey = [keyMappings objectForKey:rowidNumber]; - [subKeyMappings setObject:collectionKey forKey:rowidNumber]; - - // Add to outRowids - - [outRowids addObject:rowidNumber]; - } - - if (status != SQLITE_DONE) - { - YDBLogError(@"%@ (%@): Error executing statement: %d %s", - THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db)); - - *rowidsPtr = nil; - return nil; - } - - } - else // if (isNonPersistentView) - { - [mapTableTransaction accessWithBlock:^{ @autoreleasepool { - - for (NSNumber *rowidNumber in rowids) - { - NSString *pageKey = [mapTableTransaction objectForKey:rowidNumber]; - if (pageKey) + // Add to result dictionary + + NSMutableDictionary *subKeyMappings = [result objectForKey:pageKey]; + if (subKeyMappings == nil) { - // Add to result dictionary - - NSMutableDictionary *subKeyMappings = [result objectForKey:pageKey]; - if (subKeyMappings == nil) - { - subKeyMappings = [NSMutableDictionary dictionaryWithCapacity:1]; - [result setObject:subKeyMappings forKey:pageKey]; - } - - NSString *key = [keyMappings objectForKey:rowidNumber]; - [subKeyMappings setObject:key forKey:rowidNumber]; - - // Add to outRowids - - [outRowids addObject:rowidNumber]; + subKeyMappings = [NSMutableDictionary dictionaryWithCapacity:1]; + [result setObject:subKeyMappings forKey:pageKey]; } + + YapCollectionKey *collectionKey = [keyMappings objectForKey:rowidNumber]; + [subKeyMappings setObject:collectionKey forKey:rowidNumber]; + + // Add to outRowids + + [outRowids addObject:rowidNumber]; + + // Remove from inRowids + + [inRowids removeObjectAtIndex:i]; } - }}]; + } + + } + + // Step 2 of 2: + // + // Fetch any pageKey information we're still missing from the database. + + NSUInteger count = [inRowids count]; + if (count > 0) + { + if ([self isPersistentView]) + { + sqlite3 *db = databaseTransaction->connection->db; + + // Note: + // The handleRemoveObjectsForKeys:inCollection:withRowids: has the following guarantee: + // count <= (SQLITE_LIMIT_VARIABLE_NUMBER - 1) + // + // So we don't have to worry about sqlite's upper bound on host parameters. + + // SELECT "rowid", "pageKey" FROM "mapTableName" WHERE "rowid" IN (?, ?, ...); + + NSUInteger capacity = 50 + (count * 3); + NSMutableString *query = [NSMutableString stringWithCapacity:capacity]; + + [query appendFormat:@"SELECT \"rowid\", \"pageKey\" FROM \"%@\" WHERE \"rowid\" IN (", [self mapTableName]]; + + for (NSUInteger i = 0; i < count; i++) + { + if (i == 0) + [query appendFormat:@"?"]; + else + [query appendFormat:@", ?"]; + } + + [query appendString:@");"]; + + sqlite3_stmt *statement; + int status; + + status = sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL); + if (status != SQLITE_OK) + { + YDBLogError(@"%@ (%@): Error creating statement\n" + @" - status(%d), errmsg: %s\n" + @" - query: %@", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db), query); + + *rowidsPtr = nil; + return nil; + } + + for (NSUInteger i = 0; i < count; i++) + { + int64_t rowid = [[inRowids objectAtIndex:i] longLongValue]; + + sqlite3_bind_int64(statement, (int)(i + 1), rowid); + } + + while ((status = sqlite3_step(statement)) == SQLITE_ROW) + { + // Extract rowid & pageKey from row + + int64_t rowid = sqlite3_column_int64(statement, 0); + + const unsigned char *text = sqlite3_column_text(statement, 1); + int textSize = sqlite3_column_bytes(statement, 1); + + NSNumber *rowidNumber = @(rowid); + NSString *pageKey = [[NSString alloc] initWithBytes:text length:textSize encoding:NSUTF8StringEncoding]; + + // Add to result dictionary + + NSMutableDictionary *subKeyMappings = [result objectForKey:pageKey]; + if (subKeyMappings == nil) + { + subKeyMappings = [NSMutableDictionary dictionaryWithCapacity:1]; + [result setObject:subKeyMappings forKey:pageKey]; + } + + YapCollectionKey *collectionKey = [keyMappings objectForKey:rowidNumber]; + [subKeyMappings setObject:collectionKey forKey:rowidNumber]; + + // Add to outRowids + + [outRowids addObject:rowidNumber]; + } + + if (status != SQLITE_DONE) + { + YDBLogError(@"%@ (%@): Error executing statement: %d %s", + THIS_METHOD, [self registeredName], status, sqlite3_errmsg(db)); + } + + sqlite3_finalize(statement); + + } + else // if (isNonPersistentView) + { + [mapTableTransaction accessWithBlock:^{ @autoreleasepool { + + for (NSNumber *rowidNumber in inRowids) + { + NSString *pageKey = [mapTableTransaction objectForKey:rowidNumber]; + if (pageKey) + { + // Add to result dictionary + + NSMutableDictionary *subKeyMappings = [result objectForKey:pageKey]; + if (subKeyMappings == nil) + { + subKeyMappings = [NSMutableDictionary dictionaryWithCapacity:1]; + [result setObject:subKeyMappings forKey:pageKey]; + } + + NSString *key = [keyMappings objectForKey:rowidNumber]; + [subKeyMappings setObject:key forKey:rowidNumber]; + + // Add to outRowids + + [outRowids addObject:rowidNumber]; + } + } + }}]; + } } *rowidsPtr = outRowids; @@ -2204,10 +2317,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; if (count == 0) return; if (count == 1) { - for (NSNumber *number in keyMappings) + for (NSNumber *rowidNumber in keyMappings) { - int64_t rowid = [number longLongValue]; - YapCollectionKey *collectionKey = [keyMappings objectForKey:number]; + int64_t rowid = [rowidNumber longLongValue]; + YapCollectionKey *collectionKey = [keyMappings objectForKey:rowidNumber]; [self removeRowid:rowid collectionKey:collectionKey withPageKey:pageKey @@ -2290,10 +2403,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; // Mark rowid mappings for deletion - for (NSNumber *number in keyMappings) + for (NSNumber *rowidNumber in keyMappings) { - [viewConnection->dirtyMaps setObject:[NSNull null] forKey:number]; - [viewConnection->mapCache removeObjectForKey:number]; + [viewConnection->dirtyMaps setObject:[NSNull null] forKey:rowidNumber]; + [viewConnection->mapCache removeObjectForKey:rowidNumber]; } } @@ -2671,12 +2784,13 @@ static NSString *const ExtKey_version_deprecated = @"version"; } /** - * This method is only called if within a readwrite transaction. - * - * Extensions may implement it to perform any "cleanup" before the changeset is requested. - * Remember, the changeset is requested before the commitTransaction method is invoked. + * This method performs the appropriate actions in order to keep the pages of an appropriate size. + * Specifically it does the following: + * + * - Splits oversized pages to hit our target max_page_size + * - Drops empty pages to reduce disk usage **/ -- (void)prepareChangeset +- (void)cleanupPages { YDBLogAutoTrace(); @@ -2726,10 +2840,23 @@ static NSString *const ExtKey_version_deprecated = @"version"; } } -- (void)commitTransaction +/** + * Subclasses MUST implement this method. + * This method is only called if within a readwrite transaction. + * + * Subclasses should write any last changes to their database table(s) if needed, + * and should perform any needed cleanup before the changeset is requested. + * + * Remember, the changeset is requested immediately after this method is invoked. +**/ +- (void)flushPendingChangesToExtensionTables { YDBLogAutoTrace(); + // Cleanup pages (as needed) + + [self cleanupPages]; + // During the transaction we stored all changes in the "dirty" dictionaries. // This allows the view to make multiple changes to a page, yet only write it once. @@ -2782,8 +2909,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; if ((id)page == (id)[NSNull null]) { sqlite3_stmt *statement = [viewConnection pageTable_removeForPageKeyStatement]; - if (statement == NULL) { - *stop = YES; + if (statement == NULL) + { + NSAssert(NO, @"Cannot get proper statement! View will become corrupt!"); return;//from block } @@ -2810,8 +2938,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; else if (needsInsert) { sqlite3_stmt *statement = [viewConnection pageTable_insertForPageKeyStatement]; - if (statement == NULL) { - *stop = YES; + if (statement == NULL) + { + NSAssert(NO, @"Cannot get proper statement! View will become corrupt!"); return;//from block } @@ -2859,8 +2988,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; else if (hasDirtyLink) { sqlite3_stmt *statement = [viewConnection pageTable_updateAllForPageKeyStatement]; - if (statement == NULL) { - *stop = YES; + if (statement == NULL) + { + NSAssert(NO, @"Cannot get proper statement! View will become corrupt!"); return;//from block } @@ -2901,8 +3031,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; else { sqlite3_stmt *statement = [viewConnection pageTable_updatePageForPageKeyStatement]; - if (statement == NULL) { - *stop = YES; + if (statement == NULL) + { + NSAssert(NO, @"Cannot get proper statement! View will become corrupt!"); return;//from block } @@ -3181,6 +3312,11 @@ static NSString *const ExtKey_version_deprecated = @"version"; [pageTableTransaction commit]; [pageMetadataTableTransaction commit]; } +} + +- (void)didCommitTransaction +{ + YDBLogAutoTrace(); // Commit is complete. // Forward to connection for further cleanup. @@ -3196,9 +3332,11 @@ static NSString *const ExtKey_version_deprecated = @"version"; databaseTransaction = nil; // Do not remove ! } -- (void)rollbackTransaction +- (void)didRollbackTransaction { - if ([self isPersistentView]) + YDBLogAutoTrace(); + + if (![self isPersistentView]) { [mapTableTransaction rollback]; [pageTableTransaction rollback]; @@ -3242,9 +3380,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; // Invoke the grouping block to find out if the object should be included in the view. NSString *group = nil; - NSSet *allowedCollections = view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = view->options.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { YapDatabaseViewGroupingBlock groupingBlock_generic; YapDatabaseViewBlockType groupingBlockType; @@ -3322,9 +3460,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; // Invoke the grouping block to find out if the object should be included in the view. NSString *group = nil; - NSSet *allowedCollections = view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = view->options.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { YapDatabaseViewGroupingBlock groupingBlock_generic; YapDatabaseViewBlockType groupingBlockType; @@ -3470,9 +3608,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = view->options.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { if (groupingBlockType == YapDatabaseViewBlockTypeWithObject) { @@ -3633,9 +3771,9 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSString *collection = collectionKey.collection; __unsafe_unretained NSString *key = collectionKey.key; - NSSet *allowedCollections = view->options.allowedCollections; + YapWhitelistBlacklist *allowedCollections = view->options.allowedCollections; - if (!allowedCollections || [allowedCollections containsObject:collection]) + if (!allowedCollections || [allowedCollections isAllowed:collection]) { if (groupingBlockType == YapDatabaseViewBlockTypeWithMetadata) { @@ -3819,6 +3957,7 @@ static NSString *const ExtKey_version_deprecated = @"version"; __unsafe_unretained NSDictionary *keyMappingsForPage = (NSDictionary *)dictObj; NSString *group = [viewConnection->state groupForPageKey:pageKey]; + NSAssert(group != nil, @"Unknown group for pageKey: %@", pageKey); [self removeRowidsWithKeyMappings:keyMappingsForPage pageKey:pageKey inGroup:group]; }]; @@ -3945,6 +4084,28 @@ static NSString *const ExtKey_version_deprecated = @"version"; return count; } +/** + * Returns YES if the group is empty (has zero items). + * Shorthand for: [[transaction ext:viewName] numberOfItemsInGroup:group] == 0 +**/ +- (BOOL)isEmptyGroup:(NSString *)group +{ + NSArray *pagesMetadataForGroup = [viewConnection->state pagesMetadataForGroup:group]; + + for (YapDatabaseViewPageMetadata *pageMetadata in pagesMetadataForGroup) + { + if (pageMetadata->count > 0) { + return NO; + } + } + + return YES; +} + +/** + * Returns YES if the view is empty (has zero groups). + * Shorthand for: [[transaction ext:viewName] numberOfItemsInAllGroups] == 0 +**/ - (BOOL)isEmpty { __block BOOL result = YES; @@ -4859,32 +5020,18 @@ static NSString *const ExtKey_version_deprecated = @"version"; } /** - * This method allows you to change the groupingBlock and/or sortingBlock on-the-fly. + * This method allows you to change the grouping and/or sorting on-the-fly. * * Note: You must pass a different versionTag, or this method does nothing. **/ -- (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)newGroupingBlock - groupingBlockType:(YapDatabaseViewBlockType)newGroupingBlockType - sortingBlock:(YapDatabaseViewSortingBlock)newSortingBlock - sortingBlockType:(YapDatabaseViewBlockType)newSortingBlockType - versionTag:(NSString *)inVersionTag +- (void)setGrouping:(YapDatabaseViewGrouping *)grouping + sorting:(YapDatabaseViewSorting *)sorting + versionTag:(NSString *)inVersionTag { YDBLogAutoTrace(); - NSAssert(newGroupingBlock != NULL, @"Invalid grouping block"); - NSAssert(newSortingBlock != NULL, @"Invalid grouping block"); - - NSAssert(newGroupingBlockType == YapDatabaseViewBlockTypeWithKey || - newGroupingBlockType == YapDatabaseViewBlockTypeWithObject || - newGroupingBlockType == YapDatabaseViewBlockTypeWithMetadata || - newGroupingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid grouping block type"); - - NSAssert(newSortingBlockType == YapDatabaseViewBlockTypeWithKey || - newSortingBlockType == YapDatabaseViewBlockTypeWithObject || - newSortingBlockType == YapDatabaseViewBlockTypeWithMetadata || - newSortingBlockType == YapDatabaseViewBlockTypeWithRow, - @"Invalid sorting block type"); + NSAssert(grouping != nil, @"Invalid parameter: grouping == nil"); + NSAssert(sorting != nil, @"Invalid parameter: sorting == nil"); if (!databaseTransaction->isReadWriteTransaction) { @@ -4900,10 +5047,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; return; } - [viewConnection setGroupingBlock:newGroupingBlock - groupingBlockType:newGroupingBlockType - sortingBlock:newSortingBlock - sortingBlockType:newSortingBlockType + [viewConnection setGroupingBlock:grouping.groupingBlock + groupingBlockType:grouping.groupingBlockType + sortingBlock:sorting.sortingBlock + sortingBlockType:sorting.sortingBlockType versionTag:newVersionTag]; [self repopulateView]; @@ -4935,6 +5082,22 @@ static NSString *const ExtKey_version_deprecated = @"version"; }]; } +/** + * DEPRECATED + * Use method setGrouping:sorting:versionTag: instead. +**/ +- (void)setGroupingBlock:(YapDatabaseViewGroupingBlock)grpBlock + groupingBlockType:(YapDatabaseViewBlockType)grpBlockType + sortingBlock:(YapDatabaseViewSortingBlock)srtBlock + sortingBlockType:(YapDatabaseViewBlockType)srtBlockType + versionTag:(NSString *)inVersionTag +{ + YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withBlock:grpBlock blockType:grpBlockType]; + YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withBlock:srtBlock blockType:srtBlockType]; + + [self setGrouping:grouping sorting:sorting versionTag:inVersionTag]; +} + @end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5053,10 +5216,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; - (void)enumerateKeysAndMetadataInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: (void (^)(NSString *collection, NSString *key, id metadata, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter { if (filter == NULL) { [self enumerateKeysAndMetadataInGroup:group withOptions:options range:range usingBlock:block]; @@ -5143,10 +5306,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; - (void)enumerateKeysAndObjectsInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: (void (^)(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter { if (filter == NULL) { [self enumerateKeysAndObjectsInGroup:group withOptions:options range:range usingBlock:block]; @@ -5236,10 +5399,10 @@ static NSString *const ExtKey_version_deprecated = @"version"; - (void)enumerateRowsInGroup:(NSString *)group withOptions:(NSEnumerationOptions)options range:(NSRange)range + filter: + (BOOL (^)(NSString *collection, NSString *key))filter usingBlock: (void (^)(NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop))block - withFilter: - (BOOL (^)(NSString *collection, NSString *key))filter { if (filter == NULL) { [self enumerateRowsInGroup:group withOptions:options range:range usingBlock:block]; diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h index f002ccf..159d08c 100644 --- a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h @@ -1,10 +1,20 @@ #import +/** + * Corresponds to the different type of blocks supported by YapDatabaseView. +**/ +typedef NS_ENUM(NSInteger, YapDatabaseViewBlockType) { + YapDatabaseViewBlockTypeWithKey = 1, + YapDatabaseViewBlockTypeWithObject = 2, + YapDatabaseViewBlockTypeWithMetadata = 3, + YapDatabaseViewBlockTypeWithRow = 4 +}; + /** * The grouping block handles both filtering and grouping. * - * When you add or update rows in the databse the grouping block is invoked. + * When you add or update rows in the database the grouping block is invoked. * Your grouping block can inspect the row and determine if it should be a part of the view. * If not, your grouping block simply returns 'nil' and the object is excluded from the view (removing it if needed). * Otherwise your grouping block returns a group, which can be any string you want. @@ -14,6 +24,8 @@ * You should choose a block type that takes the minimum number of required parameters. * The view can make various optimizations based on required parameters of the block. **/ +@interface YapDatabaseViewGrouping : NSObject + typedef id YapDatabaseViewGroupingBlock; // One of the YapDatabaseViewGroupingX types below. typedef NSString* (^YapDatabaseViewGroupingWithKeyBlock)(NSString *collection, NSString *key); @@ -21,6 +33,15 @@ typedef NSString* (^YapDatabaseViewGroupingWithObjectBlock)(NSString *collection typedef NSString* (^YapDatabaseViewGroupingWithMetadataBlock)(NSString *collection, NSString *key, id metadata); typedef NSString* (^YapDatabaseViewGroupingWithRowBlock)(NSString *collection, NSString *key, id object, id metadata); ++ (instancetype)withKeyBlock:(YapDatabaseViewGroupingWithKeyBlock)groupingBlock; ++ (instancetype)withObjectBlock:(YapDatabaseViewGroupingWithObjectBlock)groupingBlock; ++ (instancetype)withMetadataBlock:(YapDatabaseViewGroupingWithMetadataBlock)groupingBlock; ++ (instancetype)withRowBlock:(YapDatabaseViewGroupingWithRowBlock)groupingBlock; + +@property (nonatomic, strong, readonly) YapDatabaseViewGroupingBlock groupingBlock; +@property (nonatomic, assign, readonly) YapDatabaseViewBlockType groupingBlockType; + +@end /** * The sorting block handles sorting of objects within their group. @@ -54,8 +75,7 @@ typedef NSString* (^YapDatabaseViewGroupingWithRowBlock)(NSString *collection, N * For example, adding objects to a view that are sorted by timestamp of when they arrived. * * The optimizations are not always performed. - * That is, if the row is added to a group it didn't previously belong, - * or if the last change didn't place an item at the beginning or end of the view. + * For example, if the last change didn't place an item at the beginning or end of the view. * * If optimizations fail, or are skipped, then the view uses a binary search algorithm. * @@ -64,10 +84,13 @@ typedef NSString* (^YapDatabaseViewGroupingWithRowBlock)(NSString *collection, N * * Another common pattern is to fetch a number of objects in a batch, and then insert them into the database. * Now imagine a situation in which the view is sorting posts based on timestamp, - * and you just fetched the most recent 10 posts. You can enumerate these 10 posts in forwards or backwards + * and you just fetched the most recent 10 posts. You can enumerate these 10 posts either forwards or backwards * while adding them to the database. One direction will hit the optimization every time. The other will cause - * the view to perform a binary search every time. These little one-liner optimzations are easy. + * the view to perform a binary search every time. + * These little one-liner optimzations are easy (given this internal information is known). **/ +@interface YapDatabaseViewSorting : NSObject + typedef id YapDatabaseViewSortingBlock; // One of the YapDatabaseViewSortingX types below. typedef NSComparisonResult (^YapDatabaseViewSortingWithKeyBlock) \ @@ -83,17 +106,12 @@ typedef NSComparisonResult (^YapDatabaseViewSortingWithRowBlock) \ (NSString *group, NSString *collection1, NSString *key1, id object1, id metadata1, \ NSString *collection2, NSString *key2, id object2, id metadata2); ++ (instancetype)withKeyBlock:(YapDatabaseViewSortingWithKeyBlock)sortingBlock; ++ (instancetype)withObjectBlock:(YapDatabaseViewSortingWithObjectBlock)sortingBlock; ++ (instancetype)withMetadataBlock:(YapDatabaseViewSortingWithMetadataBlock)sortingBlock; ++ (instancetype)withRowBlock:(YapDatabaseViewSortingWithRowBlock)sortingBlock; -/** - * I wish there was a way to inspect a given block and see what kind of parameters it takes. - * Sadly this does not appear to be possible (at least not in any kind of standard legal way). - * - * Thus you will have to specify what kind of block you're passing. -**/ -typedef NS_ENUM(NSInteger, YapDatabaseViewBlockType) { - YapDatabaseViewBlockTypeWithKey = 1, - YapDatabaseViewBlockTypeWithObject = 2, - YapDatabaseViewBlockTypeWithMetadata = 3, - YapDatabaseViewBlockTypeWithRow = 4 -}; +@property (nonatomic, strong, readonly) YapDatabaseViewSortingBlock sortingBlock; +@property (nonatomic, assign, readonly) YapDatabaseViewBlockType sortingBlockType; +@end diff --git a/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.m b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.m new file mode 100644 index 0000000..f76fcd3 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.m @@ -0,0 +1,221 @@ +#import "YapDatabaseViewTypes.h" + +/** + * The grouping block handles both filtering and grouping. + * + * When you add or update rows in the database the grouping block is invoked. + * Your grouping block can inspect the row and determine if it should be a part of the view. + * If not, your grouping block simply returns 'nil' and the object is excluded from the view (removing it if needed). + * Otherwise your grouping block returns a group, which can be any string you want. + * Once the view knows what group the row belongs to, + * it will then determine the position of the row within the group (using the sorting block). + * + * You should choose a block type that takes the minimum number of required parameters. + * The view can make various optimizations based on required parameters of the block. +**/ +@implementation YapDatabaseViewGrouping + +@synthesize groupingBlock = groupingBlock; +@synthesize groupingBlockType = groupingBlockType; + ++ (instancetype)withKeyBlock:(YapDatabaseViewGroupingWithKeyBlock)groupingBlock +{ + if (groupingBlock == NULL) return nil; + + YapDatabaseViewGrouping *grouping = [[YapDatabaseViewGrouping alloc] init]; + grouping->groupingBlock = groupingBlock; + grouping->groupingBlockType = YapDatabaseViewBlockTypeWithKey; + + return grouping; +} + ++ (instancetype)withObjectBlock:(YapDatabaseViewGroupingWithObjectBlock)groupingBlock +{ + if (groupingBlock == NULL) return nil; + + YapDatabaseViewGrouping *grouping = [[YapDatabaseViewGrouping alloc] init]; + grouping->groupingBlock = groupingBlock; + grouping->groupingBlockType = YapDatabaseViewBlockTypeWithObject; + + return grouping; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseViewGroupingWithMetadataBlock)groupingBlock +{ + if (groupingBlock == NULL) return nil; + + YapDatabaseViewGrouping *grouping = [[YapDatabaseViewGrouping alloc] init]; + grouping->groupingBlock = groupingBlock; + grouping->groupingBlockType = YapDatabaseViewBlockTypeWithMetadata; + + return grouping; +} + ++ (instancetype)withRowBlock:(YapDatabaseViewGroupingWithRowBlock)groupingBlock +{ + if (groupingBlock == NULL) return nil; + + YapDatabaseViewGrouping *grouping = [[YapDatabaseViewGrouping alloc] init]; + grouping->groupingBlock = groupingBlock; + grouping->groupingBlockType = YapDatabaseViewBlockTypeWithRow; + + return grouping; +} + +// Helper method for supporting deprecated methods. +// This method will disappear in the future. ++ (instancetype)withBlock:(YapDatabaseViewGroupingBlock)block blockType:(YapDatabaseViewBlockType)blockType +{ + YapDatabaseViewGrouping *grouping = nil; + switch (blockType) + { + case YapDatabaseViewBlockTypeWithKey : { + grouping = [YapDatabaseViewGrouping withKeyBlock:(YapDatabaseViewGroupingWithKeyBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithObject : { + grouping = [YapDatabaseViewGrouping withObjectBlock:(YapDatabaseViewGroupingWithObjectBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithMetadata : { + grouping = [YapDatabaseViewGrouping withMetadataBlock:(YapDatabaseViewGroupingWithMetadataBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithRow : { + grouping = [YapDatabaseViewGrouping withRowBlock:(YapDatabaseViewGroupingWithRowBlock)block]; + break; + } + } + + return grouping; +} + +@end + +#pragma mark - + +/** + * The sorting block handles sorting of objects within their group. + * + * After the view invokes the grouping block to determine what group a database row belongs to (if any), + * the view then needs to determine what index within that group the row should be. + * In order to do this, it needs to compare the new/updated row with existing rows in the same view group. + * This is what the sorting block is used for. + * So the sorting block will be invoked automatically during this process until the view has come to a conclusion. + * + * You should choose a block type that takes the minimum number of required parameters. + * The view can make various optimizations based on required parameters of the block. + * + * For example, if sorting is based on the object, and the metadata of a row is updated, + * then the view can deduce that the index hasn't changed (if the group hans't), and can skip this step. + * + * Performance Note: + * + * The view uses various optimizations (based on common patterns) + * to reduce the number of times it needs to invoke the sorting block. + * + * - Pattern : row is updated, but its index in the view doesn't change. + * Optimization : if an updated row doesn't change groups, the view will first compare it with + * objects to the left and right. + * + * - Pattern : rows are added to the beginning or end or a view + * Optimization : if the last change put an object at the beginning of the view, then it will test this quickly. + * if the last change put an object at the end of the view, then it will test this quickly. + * + * These optimizations offer huge performance benefits to many common cases. + * For example, adding objects to a view that are sorted by timestamp of when they arrived. + * + * The optimizations are not always performed. + * For example, if the last change didn't place an item at the beginning or end of the view. + * + * If optimizations fail, or are skipped, then the view uses a binary search algorithm. + * + * Although this may be considered "internal information", + * I feel it is important to explain for the following reason: + * + * Another common pattern is to fetch a number of objects in a batch, and then insert them into the database. + * Now imagine a situation in which the view is sorting posts based on timestamp, + * and you just fetched the most recent 10 posts. You can enumerate these 10 posts either forwards or backwards + * while adding them to the database. One direction will hit the optimization every time. The other will cause + * the view to perform a binary search every time. + * These little one-liner optimzations are easy (given this internal information is known). +**/ +@implementation YapDatabaseViewSorting + +@synthesize sortingBlock = sortingBlock; +@synthesize sortingBlockType = sortingBlockType; + ++ (instancetype)withKeyBlock:(YapDatabaseViewSortingWithKeyBlock)sortingBlock +{ + if (sortingBlock == NULL) return nil; + + YapDatabaseViewSorting *sorting = [[YapDatabaseViewSorting alloc] init]; + sorting->sortingBlock = sortingBlock; + sorting->sortingBlockType = YapDatabaseViewBlockTypeWithKey; + + return sorting; +} + ++ (instancetype)withObjectBlock:(YapDatabaseViewSortingWithObjectBlock)sortingBlock +{ + if (sortingBlock == NULL) return nil; + + YapDatabaseViewSorting *sorting = [[YapDatabaseViewSorting alloc] init]; + sorting->sortingBlock = sortingBlock; + sorting->sortingBlockType = YapDatabaseViewBlockTypeWithObject; + + return sorting; +} + ++ (instancetype)withMetadataBlock:(YapDatabaseViewSortingWithMetadataBlock)sortingBlock +{ + if (sortingBlock == NULL) return nil; + + YapDatabaseViewSorting *sorting = [[YapDatabaseViewSorting alloc] init]; + sorting->sortingBlock = sortingBlock; + sorting->sortingBlockType = YapDatabaseViewBlockTypeWithMetadata; + + return sorting; +} + ++ (instancetype)withRowBlock:(YapDatabaseViewSortingWithRowBlock)sortingBlock +{ + if (sortingBlock == NULL) return nil; + + YapDatabaseViewSorting *sorting = [[YapDatabaseViewSorting alloc] init]; + sorting->sortingBlock = sortingBlock; + sorting->sortingBlockType = YapDatabaseViewBlockTypeWithRow; + + return sorting; +} + +// Helper method for supporting deprecated methods. +// This method will disappear in the future. ++ (instancetype)withBlock:(YapDatabaseViewSortingBlock)block blockType:(YapDatabaseViewBlockType)blockType +{ + YapDatabaseViewSorting *sorting = nil; + switch (blockType) + { + case YapDatabaseViewBlockTypeWithKey : { + sorting = [YapDatabaseViewSorting withKeyBlock:(YapDatabaseViewSortingWithKeyBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithObject : { + sorting = [YapDatabaseViewSorting withObjectBlock:(YapDatabaseViewSortingWithObjectBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithMetadata : { + sorting = [YapDatabaseViewSorting withMetadataBlock:(YapDatabaseViewSortingWithMetadataBlock)block]; + break; + } + case YapDatabaseViewBlockTypeWithRow : { + sorting = [YapDatabaseViewSorting withRowBlock:(YapDatabaseViewSortingWithRowBlock)block]; + break; + } + } + + return sorting; +} + +@end + diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapCache.h b/Pods/YapDatabase/YapDatabase/Internal/YapCache.h deleted file mode 100644 index b833d80..0000000 --- a/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +++ /dev/null @@ -1,94 +0,0 @@ -#import - -#define YAP_CACHE_STATISTICS 0 - -/** - * YapCache implements a simple strict cache. - * - * It is very similar to NSCache and shares a similar API. - * However, YapCache implements a strict countLimit and monitors usage so eviction is properly ordered. - * - * For example: - * If you set a countLimit of 4, then when you add the 5th item to the cache, another item is automatically evicted. - * It doesn't happen at a later time as with NSCache. It happens atomically during the addition of the 5th item. - - * Which item gets evicted? That depends entirely on usage. - * YapCache maintains a doubly linked-list of keys ordered by access. - * The most recently accessed key is at the front of the linked-list, - * and the least recently accessed key is at the back. - * So it's very quick and efficient to evict items based on recent usage. - * - * YapCache is NOT thread-safe. - * It is designed to be used by the various YapDatabase classes, which inherently serialize access to the cache. -**/ - -@interface YapCache : NSObject - -/** - * Initializes a cache. - * - * Since the countLimit is a common configuration, it may optionally be passed during initialization. -**/ -- (id)initWithKeyClass:(Class)keyClass; -- (id)initWithKeyClass:(Class)keyClass countLimit:(NSUInteger)countLimit; - -- (id)initWithKeyClass:(Class)keyClass - keyCallbacks:(CFDictionaryKeyCallBacks)keyCallbacks - countLimit:(NSUInteger)countLimit; - -/** - * The countLimit specifies the maximum number of items to keep in the cache. - * This limit is strictly enforced. - * - * The default countLimit is 40. - * - * You may optionally disable the countLimit by setting it to zero. - * - * You may change the countLimit at any time. - * Changes to the countLimit take immediate effect on the cache (before the set method returns). - * Thus, if needed, you can temporarily increase the cache size for certain operations. -**/ -@property (nonatomic, assign, readwrite) NSUInteger countLimit; - -// -// The normal cache stuff... -// - -- (void)setObject:(id)object forKey:(id)key; - -- (id)objectForKey:(id)key; -- (BOOL)containsKey:(id)key; - -- (NSUInteger)count; - -- (void)removeAllObjects; -- (void)removeObjectForKey:(id)key; -- (void)removeObjectsForKeys:(NSArray *)keys; - -- (void)enumerateKeysWithBlock:(void (^)(id key, BOOL *stop))block; -- (void)enumerateKeysAndObjectsWithBlock:(void (^)(id key, id obj, BOOL *stop))block; - -// -// Some debugging stuff that gets compiled out -// - -#if YAP_CACHE_STATISTICS - -/** - * When querying the cache for an object via objectForKey, - * the hitCount is incremented if the object is in the cache, - * and the missCount is incremented if the object is not in the cache. -**/ -@property (nonatomic, readonly) NSUInteger hitCount; -@property (nonatomic, readonly) NSUInteger missCount; - -/** - * When adding objects to the cache via setObject:forKey:, - * the evictionCount is incremented if the cache is full, - * and the added object causes another object (the least recently used object) to be evicted. -**/ -@property (nonatomic, readonly) NSUInteger evictionCount; - -#endif - -@end diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h b/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h index 2b1a9f9..53333a8 100644 --- a/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +++ b/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h @@ -23,6 +23,14 @@ NS_INLINE void sqlite_finalize_null(sqlite3_stmt **stmtPtr) } } +#ifndef SQLITE_BIND_START +#define SQLITE_BIND_START 1 +#endif + +#ifndef SQLITE_COL_START +#define SQLITE_COL_START 0 +#endif + extern NSString *const YapDatabaseRegisteredExtensionsKey; extern NSString *const YapDatabaseRegisteredMemoryTablesKey; extern NSString *const YapDatabaseExtensionsOrderKey; @@ -31,34 +39,6 @@ extern NSString *const YapDatabaseRemovedRowidsKey; extern NSString *const YapDatabaseNotificationKey; @interface YapDatabase () { -@private - - YapDatabaseOptions *options; - - NSMutableArray *changesets; - uint64_t snapshot; - - dispatch_queue_t internalQueue; - dispatch_queue_t checkpointQueue; - - YapDatabaseConnectionDefaults *connectionDefaults; - - NSDictionary *registeredExtensions; - NSDictionary *registeredMemoryTables; - - NSArray *extensionsOrder; - NSDictionary *extensionDependencies; - - YapDatabaseConnection *registrationConnection; - - NSUInteger maxConnectionPoolCount; - NSTimeInterval connectionPoolLifetime; - dispatch_source_t connectionPoolTimer; - NSMutableArray *connectionPoolValues; - NSMutableArray *connectionPoolDates; - - sqlite3 *db; // Used for setup & checkpoints - @public void *IsOnSnapshotQueueKey; // Only to be used by YapDatabaseConnection @@ -69,22 +49,25 @@ extern NSString *const YapDatabaseNotificationKey; NSMutableArray *connectionStates; // Only to be used by YapDatabaseConnection - NSArray *previouslyRegisteredExtensionNames; // Only to be used by YapDatabaseConnection + NSArray *previouslyRegisteredExtensionNames; // Writeable only within snapshot queue - YapDatabaseSerializer objectSerializer; // Read-only by transactions - YapDatabaseDeserializer objectDeserializer; // Read-only by transactions + YapDatabaseSerializer objectSerializer; // Read-only by transactions + YapDatabaseDeserializer objectDeserializer; // Read-only by transactions - YapDatabaseSerializer metadataSerializer; // Read-only by transactions - YapDatabaseDeserializer metadataDeserializer; // Read-only by transactions + YapDatabaseSerializer metadataSerializer; // Read-only by transactions + YapDatabaseDeserializer metadataDeserializer; // Read-only by transactions - YapDatabaseSanitizer objectSanitizer; // Read-only by transactions - YapDatabaseSanitizer metadataSanitizer; // Read-only by transactions + YapDatabasePreSanitizer objectPreSanitizer; // Read-only by transactions + YapDatabasePostSanitizer objectPostSanitizer; // Read-only by transactions + + YapDatabasePreSanitizer metadataPreSanitizer; // Read-only by transactions + YapDatabasePostSanitizer metadataPostSanitizer; // Read-only by transactions } /** * General utility methods. **/ -+ (int)pragma:(NSString *)pragmaSetting using:(sqlite3 *)db; ++ (int)pragma:(NSString *)pragmaSetting using:(sqlite3 *)aDb; + (NSString *)pragmaValueForAutoVacuum:(int)auto_vacuum; + (NSString *)pragmaValueForSynchronous:(int)synchronous; + (BOOL)tableExists:(NSString *)tableName using:(sqlite3 *)aDb; @@ -172,28 +155,7 @@ extern NSString *const YapDatabaseNotificationKey; #pragma mark - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -@interface YapDatabaseConnection () { -@private - uint64_t snapshot; - - id sharedKeySetForInternalChangeset; - id sharedKeySetForExternalChangeset; - - YapDatabaseReadTransaction *longLivedReadTransaction; - BOOL throwExceptionsForImplicitlyEndingLongLivedReadTransaction; - NSMutableArray *pendingChangesets; - NSMutableArray *processedChangesets; - - NSDictionary *registeredExtensions; - BOOL registeredExtensionsChanged; - - NSDictionary *registeredMemoryTables; - BOOL registeredMemoryTablesChanged; - - NSMutableDictionary *extensions; - BOOL extensionsReady; - id sharedKeySetForExtensions; - +@interface YapDatabaseConnection () { @public __strong YapDatabase *database; @@ -439,11 +401,17 @@ extern NSString *const YapDatabaseNotificationKey; id customObjectForNotification; } -- (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid; +- (void)replaceObject:(id)object + forKey:(NSString *)key + inCollection:(NSString *)collection + withRowid:(int64_t)rowid + serializedObject:(NSData *)preSerializedObject; + - (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection - withRowid:(int64_t)rowid; + withRowid:(int64_t)rowid + serializedMetadata:(NSData *)preSerializedMetadata; - (void)removeObjectForKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid; diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.h b/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.h new file mode 100644 index 0000000..b894856 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.h @@ -0,0 +1,34 @@ +#import + + +/** + * This is a simple class to ensure that keys & objects we're putting into a dictionary are all of the desired class. + * It's intended only for debugging purposes, especially in refactoring cases. +**/ +@interface YapDebugDictionary : NSObject + +- (instancetype)initWithKeyClass:(Class)keyClass objectClass:(Class)objectClass; +- (instancetype)initWithKeyClass:(Class)keyClass objectClass:(Class)objectClass capacity:(NSUInteger)capacity; + +- (instancetype)initWithDictionary:(YapDebugDictionary *)dictionary copyItems:(BOOL)copyItems; + +// Inspection + +- (id)objectForKey:(id)aKey; + +- (void)setObject:(id)anObject forKey:(id)aKey; + +- (void)removeObjectForKey:(id)aKey; + +// Pass through + +@property (nonatomic, readonly) NSUInteger count; + +@property (nonatomic, readonly, copy) NSArray *allKeys; +@property (nonatomic, readonly, copy) NSArray *allValues; + +- (NSEnumerator *)objectEnumerator; + +- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.m b/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.m new file mode 100644 index 0000000..a934879 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Internal/YapDebugDictionary.m @@ -0,0 +1,108 @@ +#import "YapDebugDictionary.h" + + +/** + * This is a simple class to ensure that keys & objects we're putting into a dictionary are all of the desired class. + * It's intended only for debugging purposes, especially in refactoring cases. +**/ +@implementation YapDebugDictionary +{ + NSMutableDictionary *dict; + + Class keyClass; + Class objectClass; +} + +- (instancetype)initWithKeyClass:(Class)inKeyClass objectClass:(Class)inObjectClass +{ + return [self initWithKeyClass:inKeyClass objectClass:inObjectClass capacity:0]; +} + +- (instancetype)initWithKeyClass:(Class)inKeyClass objectClass:(Class)inObjectClass capacity:(NSUInteger)capacity +{ + if ((self = [super init])) + { + if (capacity > 0) + dict = [[NSMutableDictionary alloc] initWithCapacity:capacity]; + else + dict = [[NSMutableDictionary alloc] init]; + + keyClass = inKeyClass; + objectClass = inObjectClass; + } + return self; +} + +- (instancetype)initWithDictionary:(YapDebugDictionary *)ydd copyItems:(BOOL)copyItems +{ + if ((self = [super init])) + { + dict = [[NSMutableDictionary alloc] initWithDictionary:ydd->dict copyItems:copyItems]; + + keyClass = ydd->keyClass; + objectClass = ydd->objectClass; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone +{ + return [[YapDebugDictionary alloc] initWithDictionary:self copyItems:NO]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Inspection +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (id)objectForKey:(id)key +{ + NSAssert([key isKindOfClass:keyClass], @"Invalid key class"); + + return [dict objectForKey:key]; +} + +- (void)setObject:(id)object forKey:(id)key +{ + NSAssert([key isKindOfClass:keyClass], @"Invalid key class"); + NSAssert([object isKindOfClass:objectClass], @"Invalid key class"); + + [dict setObject:object forKey:key]; +} + +- (void)removeObjectForKey:(id)key +{ + NSAssert([key isKindOfClass:keyClass], @"Invalid key class"); + + [dict removeObjectForKey:key]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Pass Through +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (NSUInteger)count +{ + return dict.count; +} + +- (NSArray *)allKeys +{ + return [dict allKeys]; +} + +- (NSArray *)allValues +{ + return [dict allValues]; +} + +- (NSEnumerator *)objectEnumerator +{ + return [dict objectEnumerator]; +} + +- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block +{ + [dict enumerateKeysAndObjectsUsingBlock:block]; +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapRowidSet.h b/Pods/YapDatabase/YapDatabase/Internal/YapRowidSet.h index a18f87c..ec1ea96 100644 --- a/Pods/YapDatabase/YapDatabase/Internal/YapRowidSet.h +++ b/Pods/YapDatabase/YapDatabase/Internal/YapRowidSet.h @@ -2,12 +2,14 @@ * Wrapper for C++ code (std::unordered_set) **/ +#import + #ifndef YapDatabase_YapRowidSet_h #define YapDatabase_YapRowidSet_h #if defined(__cplusplus) extern "C" { -#endif /* defined(__cplusplus) */ +#endif typedef struct _YapRowidSet YapRowidSet; @@ -29,6 +31,6 @@ void YapRowidSetEnumerate(YapRowidSet *set, void (^block)(int64_t rowid, BOOL *s #if defined(__cplusplus) } -#endif /* defined(__cplusplus) */ +#endif #endif diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapCache.h b/Pods/YapDatabase/YapDatabase/Utilities/YapCache.h new file mode 100644 index 0000000..c754318 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapCache.h @@ -0,0 +1,144 @@ +#import + +#ifndef YAP_CACHE_STATISTICS +#define YAP_CACHE_STATISTICS 0 +#endif + +/** + * YapCache implements a simple strict cache. + * + * It is very similar to NSCache and shares a similar API. + * However, YapCache implements a strict countLimit and monitors usage so eviction is properly ordered. + * + * For example: + * If you set a countLimit of 4, then when you add the 5th item to the cache, another item is automatically evicted. + * It doesn't happen at a later time as with NSCache. It happens atomically during the addition of the 5th item. + * + * Which item gets evicted depends entirely on usage. + * YapCache maintains a doubly linked-list of keys ordered by access. + * The most recently accessed key is at the front of the linked-list, + * and the least recently accessed key is at the back. + * So it's very quick and efficient to evict items based on recent usage. + * + * YapCache is considerably faster than NSCache. + * The project even comes with a benchmarking tool for comparing the speed of YapCache vs NSCache. + * + * However, YapCache is NOT thread-safe. (Whereas NSCache is.) + * This is because YapCache was designed specifically for performance. + * Thus it's NOT recommended you use YapCache unless you're always going to be using it from the same thread, + * or from within the same serial dispatch queue. The various YapDatabase classes which use it inherently + * serialize access to the cache via their own internal serial queue. + * + * Also, YapCache does NOT automatically purge itself in the even of a low memory condition. (Whereas NSCache does.) + * This also has to do with YapCache not being thread-safe. + * And thus performing this action (if desired) is up to you. + * The various YapDatabase classes which use it do this themselves. +**/ + +@interface YapCache : NSObject + +/** + * Initializes a cache. + * If you don't define a countLimit, then the default countLimit of 40 is used. +**/ +- (instancetype)init; +- (instancetype)initWithCountLimit:(NSUInteger)countLimit; + +/** + * This init method allows you to define the keyCallbacks to be used by the internal CFDictionary. + * This is useful for a number of reasons. + * + * By default (if you use the other init methods), YapCache will use kCFTypeDictionaryKeyCallBacks. + * This means that the keys you use with the cache will be retained, and not copied. + * This is also how NSCache works. But is not how NSMutableDictionary works. + * In contrast NSMutableDictionary will copy (not retain) the keys you give it. + * In general: + * - retaining the keys is faster + * - copying the keys is safer + * + * But, in truth, it all depends on what you're using for keys. If you're using something like NSNumber, + * or some other immutable class, then there's no point in worrying about copying. But if you're using strings, + * and there's a possibility you might be using mutable strings, then copying is much safer. + * + * So basically, if you want a cache-style dictionary (limit enforcing), but you need the key-copy safety similar to + * NSMutableDictionary, then you can pass kCFCopyStringDictionaryKeyCallBacks to get it. + * + * Additionally, you can sometimes customize the keyCallbacks to get a performance boost. + * Various classes within YapDatabase, which use YapCache, use a YapCollectionKey object as the key. + * And the YapCollectionKey class actually provides its own CFDictionaryKeyCallBacks struct that provides + * a nice little performance boost. +**/ +- (instancetype)initWithCountLimit:(NSUInteger)countLimit keyCallbacks:(CFDictionaryKeyCallBacks)keyCallbacks; + +/** + * The countLimit specifies the maximum number of items to keep in the cache. + * This limit is strictly enforced. + * + * The default countLimit is 40. + * + * You may optionally disable the countLimit by setting it to zero. + * + * You may change the countLimit at any time. + * Changes to the countLimit take immediate effect on the cache (before the set method returns). + * Thus, if needed, you can temporarily increase the cache size for certain operations. +**/ +@property (nonatomic, assign, readwrite) NSUInteger countLimit; + +/** + * These methods are for "debugging". + * + * They allows you to specify a set of classes that you intend to use for the keys and/or values. + * If set, the class will check to ensure you're always using the proper class type when you set or query the cache. + * + * You can think of this feature as something similar to templates / generic types in C++. + * Except that it's run-time enforcement, and not compile-time. + * + * Since this is for debugging, the checks are ONLY run when assertions are enabled. + * In general, assertions are disabled when you compile for release. + * But to be precise, the checks are only run if NS_BLOCK_ASSERTIONS is not defined. +**/ +@property (nonatomic, copy, readwrite) NSSet *allowedKeyClasses; +@property (nonatomic, copy, readwrite) NSSet *allowedObjectClasses; + +// +// The normal cache stuff... +// + +- (void)setObject:(id)object forKey:(id)key; + +- (id)objectForKey:(id)key; +- (BOOL)containsKey:(id)key; + +- (NSUInteger)count; + +- (void)removeAllObjects; +- (void)removeObjectForKey:(id)key; +- (void)removeObjectsForKeys:(NSArray *)keys; + +- (void)enumerateKeysWithBlock:(void (^)(id key, BOOL *stop))block; +- (void)enumerateKeysAndObjectsWithBlock:(void (^)(id key, id obj, BOOL *stop))block; + +// +// Some debugging stuff that gets compiled out +// + +#if YAP_CACHE_STATISTICS + +/** + * When querying the cache for an object via objectForKey, + * the hitCount is incremented if the object is in the cache, + * and the missCount is incremented if the object is not in the cache. +**/ +@property (nonatomic, readonly) NSUInteger hitCount; +@property (nonatomic, readonly) NSUInteger missCount; + +/** + * When adding objects to the cache via setObject:forKey:, + * the evictionCount is incremented if the cache is full, + * and the added object causes another object (the least recently used object) to be evicted. +**/ +@property (nonatomic, readonly) NSUInteger evictionCount; + +#endif + +@end diff --git a/Pods/YapDatabase/YapDatabase/Internal/YapCache.m b/Pods/YapDatabase/YapDatabase/Utilities/YapCache.m similarity index 80% rename from Pods/YapDatabase/YapDatabase/Internal/YapCache.m rename to Pods/YapDatabase/YapDatabase/Utilities/YapCache.m index b5105c5..e8194e6 100644 --- a/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapCache.m @@ -56,9 +56,7 @@ @implementation YapCache { - Class keyClass; CFMutableDictionaryRef cfdict; - NSUInteger countLimit; __unsafe_unretained YapCacheItem *mostRecentCacheItem; @@ -73,53 +71,34 @@ #endif } +@synthesize allowedKeyClasses = allowedKeyClasses; +@synthesize allowedObjectClasses = allowedObjectClasses; + #if YAP_CACHE_STATISTICS @synthesize hitCount = hitCount; @synthesize missCount = missCount; @synthesize evictionCount = evictionCount; #endif -- (id)init +- (instancetype)init { - return [self initWithKeyClass:NULL - keyCallbacks:kCFTypeDictionaryKeyCallBacks - countLimit:0]; + return [self initWithCountLimit:0 keyCallbacks:kCFTypeDictionaryKeyCallBacks]; } -- (id)initWithKeyClass:(Class)inKeyClass +- (instancetype)initWithCountLimit:(NSUInteger)inCountLimit { - return [self initWithKeyClass:inKeyClass - keyCallbacks:kCFTypeDictionaryKeyCallBacks - countLimit:0]; + return [self initWithCountLimit:inCountLimit keyCallbacks:kCFTypeDictionaryKeyCallBacks]; } -- (id)initWithKeyClass:(Class)inKeyClass countLimit:(NSUInteger)inCountLimit -{ - return [self initWithKeyClass:inKeyClass - keyCallbacks:kCFTypeDictionaryKeyCallBacks - countLimit:inCountLimit]; -} - -- (id)initWithKeyClass:(Class)inKeyClass - keyCallbacks:(CFDictionaryKeyCallBacks)inKeyCallbacks - countLimit:(NSUInteger)inCountLimit +- (id)initWithCountLimit:(NSUInteger)inCountLimit keyCallbacks:(CFDictionaryKeyCallBacks)inKeyCallbacks { if ((self = [super init])) { - if (inKeyClass == NULL) - keyClass = [NSString class]; - else - keyClass = inKeyClass; - if (inCountLimit == 0) countLimit = YAP_CACHE_DEFAULT_COUNT_LIMIT; else countLimit = inCountLimit; - // We actually use countLimit plus one. - // This is because we evict items after the count surpasses the countLimit. - // In other words, we evict items when the count reaches countLimit plus one. - cfdict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &inKeyCallbacks, @@ -169,7 +148,9 @@ - (id)objectForKey:(id)key { - NSAssert([key isKindOfClass:keyClass], @"Unexpected key class. Expected %@, passed %@", keyClass, [key class]); + #ifndef NS_BLOCK_ASSERTIONS + AssertAllowedKeyClass(key, allowedKeyClasses); + #endif YapCacheItem *item = CFDictionaryGetValue(cfdict, (const void *)key); if (item) @@ -215,14 +196,19 @@ - (BOOL)containsKey:(id)key { - NSAssert([key isKindOfClass:keyClass], @"Unexpected key class. Expected %@, passed %@", keyClass, [key class]); + #ifndef NS_BLOCK_ASSERTIONS + AssertAllowedKeyClass(key, allowedKeyClasses); + #endif return CFDictionaryContainsKey(cfdict, (const void *)key); } - (void)setObject:(id)object forKey:(id)key { - NSAssert([key isKindOfClass:keyClass], @"Unexpected key class. Expected %@, passed %@", keyClass, [key class]); + #ifndef NS_BLOCK_ASSERTIONS + AssertAllowedKeyClass(key, allowedKeyClasses); + AssertAllowedObjectClass(object, allowedObjectClasses); + #endif YapCacheItem *item = CFDictionaryGetValue(cfdict, (const void *)key); if (item) @@ -355,7 +341,9 @@ - (void)removeObjectForKey:(id)key { - NSAssert([key isKindOfClass:keyClass], @"Unexpected key class. Expected %@, passed %@", keyClass, [key class]); + #ifndef NS_BLOCK_ASSERTIONS + AssertAllowedKeyClass(key, allowedKeyClasses); + #endif YapCacheItem *item = CFDictionaryGetValue(cfdict, (const void *)key); if (item) @@ -380,7 +368,9 @@ { for (id key in keys) { - NSAssert([key isKindOfClass:keyClass], @"Unexpected key class. Expected %@, passed %@", keyClass, [key class]); + #ifndef NS_BLOCK_ASSERTIONS + AssertAllowedKeyClass(key, allowedKeyClasses); + #endif YapCacheItem *item = CFDictionaryGetValue(cfdict, (const void *)key); if (item) @@ -446,6 +436,52 @@ return description; } +#ifndef NS_BLOCK_ASSERTIONS +static void AssertAllowedKeyClass(id key, NSSet *allowedKeyClasses) +{ + if (allowedKeyClasses == nil) return; + + // This doesn't work. + // For example, @(number) gives us class '__NSCFNumber', which is not NSNumber. + // And there are also class clusters which break this technique too. + // + // return [allowedKeyClasses containsObject:keyClass]; + + // So we have to use the isKindOfClass method, + // which means we need to enumerate the allowedKeyClasses. + + for (Class allowedKeyClass in allowedKeyClasses) + { + if ([key isKindOfClass:allowedKeyClass]) return; + } + + NSCAssert(NO, @"Unexpected key class. Passed %@, expected: %@", [key class], allowedKeyClasses); +} +#endif + +#ifndef NS_BLOCK_ASSERTIONS +static void AssertAllowedObjectClass(id obj, NSSet *allowedObjectClasses) +{ + if (allowedObjectClasses == nil) return; + + // This doesn't work. + // For example, @(number) gives us class '__NSCFNumber', which is not NSNumber. + // And there are also class clusters which break this technique too. + // + // return [allowedKeyClasses containsObject:keyClass]; + + // So we have to use the isKindOfClass method, + // which means we need to enumerate the allowedKeyClasses. + + for (Class allowedObjectClass in allowedObjectClasses) + { + if ([obj isKindOfClass:allowedObjectClass]) return; + } + + NSCAssert(NO, @"Unexpected object class. Passed %@, expected: %@", [obj class], allowedObjectClasses); +} +#endif + /* - (void)debug { diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m b/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m index 7056fa0..695613e 100644 --- a/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m @@ -1,128 +1,7 @@ #import "YapCollectionKey.h" +#import "YapMurmurHash.h" -/** - * MurmurHash2 was written by Austin Appleby, and is placed in the public domain. - * http://code.google.com/p/smhasher -**/ -static NSUInteger YDB_MurmurHash(NSUInteger hash1, NSUInteger hash2) -{ - if (NSUIntegerMax == UINT32_MAX) // Should be optimized out via compiler since these are constants - { - // MurmurHash2 (32-bit) - // - // uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) - // - // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). - // Instead we're going to use our 2 hashes. - // And we're going to randomly make up a 'seed'. - - const uint32_t seed = 0xa2f1b6f; // Some random value I made up - const uint32_t len = 8; // 2 hashes, each 4 bytes = 8 bytes - - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. - - const uint32_t m = 0x5bd1e995; - const int r = 24; - - // Initialize the hash to a 'random' value - - uint32_t h = seed ^ len; - uint32_t k; - - // Mix hash1 - - k = hash1; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - // Mix khash - - k = hash2; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return (NSUInteger)h; - } - else - { - // MurmurHash2 (64-bit) - // - // uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed ) - // - // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). - // Instead we're going to use our 3 hashes. - // And we're going to randomly make up a 'seed'. - - const uint32_t seed = 0xa2f1b6f; // Some random value I made up - const uint32_t len = 16; // 2 hashes, each 8 bytes = 16 bytes - - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. - - const uint64_t m = 0xc6a4a7935bd1e995LLU; - const int r = 47; - - // Initialize the hash to a 'random' value - - uint64_t h = seed ^ (len * m); - uint64_t k; - - // Mix hash1 - - k = hash1; - - k *= m; - k ^= k >> r; - k *= m; - - h ^= k; - h *= m; - - // Mix hash2 - - k = hash2; - - k *= m; - k ^= k >> r; - k *= m; - - h ^= k; - h *= m; - - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. - - h ^= h >> r; - h *= m; - h ^= h >> r; - - return (NSUInteger)h; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - @implementation YapCollectionKey { // When these objects are stored in a dictionary (as the key), the hash method is invoked extremely often. @@ -157,7 +36,7 @@ YapCollectionKey* YapCollectionKeyCreate(NSString *collection, NSString *key) else key = [aKey copy]; // copy == retain if aKey is immutable - hash = YDB_MurmurHash([collection hash], [key hash]); + hash = YapMurmurHash2([collection hash], [key hash]); } return self; } @@ -169,7 +48,7 @@ YapCollectionKey* YapCollectionKeyCreate(NSString *collection, NSString *key) collection = [decoder decodeObjectForKey:@"collection"]; key = [decoder decodeObjectForKey:@"key"]; - hash = YDB_MurmurHash([collection hash], [key hash]); + hash = YapMurmurHash2([collection hash], [key hash]); } return self; } diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h b/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h index 7d41d5e..56e6910 100644 --- a/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h @@ -35,6 +35,19 @@ **/ + (instancetype)queryWithFormat:(NSString *)format, ...; +/** + * Shim that allows YapDatabaseQuery to be used from Swift. + * + * Define the following somewhere in your Swift code: + * + * extension YapDatabaseQuery { + * class func queryWithFormat(format: String, _ arguments: CVarArgType...) -> YapDatabaseQuery? { + * return withVaList(arguments, { YapDatabaseQuery(format: format, arguments: $0) }) + * } + * } + **/ ++ (instancetype)queryWithFormat:(NSString *)format arguments:(va_list)arguments; + /** * Shorthand for a query with no 'WHERE' clause. * Equivalent to [YapDatabaseQuery queryWithFormat:@""]. diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m b/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m index cb1d663..7b9d43a 100644 --- a/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m @@ -47,8 +47,28 @@ * usingBlock:^(NSString *key, id object, BOOL *stop){ * ... * }]; -**/ + **/ + (instancetype)queryWithFormat:(NSString *)format, ... +{ + va_list arguments; + va_start(arguments, format); + id query = [self queryWithFormat:format arguments:arguments]; + va_end(arguments); + return query; +} + +/** + * Shim that allows YapDatabaseQuery to be used from Swift. + * + * Define the following somewhere in your Swift code: + * + * extension YapDatabaseQuery { + * class func queryWithFormat(format: String, _ arguments: CVarArgType...) -> YapDatabaseQuery? { + * return withVaList(arguments, { YapDatabaseQuery(format: format, arguments: $0) }) + * } + * } + **/ ++ (instancetype)queryWithFormat:(NSString *)format arguments:(va_list)args { if (format == nil) return nil; @@ -58,10 +78,14 @@ NSRange searchRange = NSMakeRange(0, formatLength); NSRange paramRange = [format rangeOfString:@"?" options:0 range:searchRange]; + NSMutableArray *paramLocations = [NSMutableArray array]; + while (paramRange.location != NSNotFound) { paramCount++; + [paramLocations addObject:@(paramRange.location)]; + searchRange.location = paramRange.location + 1; searchRange.length = formatLength - searchRange.location; @@ -74,16 +98,43 @@ NSMutableArray *queryParameters = [NSMutableArray arrayWithCapacity:paramCount]; - va_list args; - va_start(args, format); - @try { + NSMutableDictionary *paramIndexToElementCountMap = [NSMutableDictionary dictionary]; for (NSUInteger i = 0; i < paramCount; i++) { id param = va_arg(args, id); + if ([param isKindOfClass:[NSArray class]]) + { + paramIndexToElementCountMap[@(i)] = @([param count]); + [queryParameters addObjectsFromArray:param]; + } + else + { + [queryParameters addObject:param]; + } + } + + if (paramIndexToElementCountMap.count > 0) + { + NSUInteger unpackingOffset = 0; + NSString *queryString = [format copy]; + NSRange range; + for (NSNumber *index in paramIndexToElementCountMap) + { + NSInteger elementCount = [paramIndexToElementCountMap[index] intValue]; + NSMutableArray *unpackedParams = [NSMutableArray array]; + for (NSUInteger i = 0; i < elementCount; i++) + { + [unpackedParams addObject:@"?"]; + } + NSString *unpackedParamsStr = [unpackedParams componentsJoinedByString:@","]; + range = NSMakeRange([paramLocations[[index intValue]] intValue] + unpackingOffset, 1); + queryString = [queryString stringByReplacingCharactersInRange:range + withString:unpackedParamsStr]; + } - [queryParameters addObject:param]; + format = [queryString copy]; } } @catch (NSException *exception) @@ -94,8 +145,6 @@ queryParameters = nil; } - va_end(args); - if (queryParameters || (paramCount == 0)) { return [[YapDatabaseQuery alloc] initWithQueryString:format queryParameters:queryParameters]; @@ -106,11 +155,10 @@ } } - /** * Shorthand for a query with no 'WHERE' clause. * Equivalent to [YapDatabaseQuery queryWithFormat:@""]. -**/ + **/ + (instancetype)queryMatchingAll { return [[YapDatabaseQuery alloc] initWithQueryString:@"" queryParameters:nil]; diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.h b/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.h new file mode 100644 index 0000000..4444613 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.h @@ -0,0 +1,20 @@ +#import + +/** + * MurmurHash2 was written by Austin Appleby, and is placed in the public domain. + * http://code.google.com/p/smhasher +**/ + +#ifndef YapDatabase_YapMurmurHash_h +#define YapDatabase_YapMurmurHash_h + +NSUInteger YapMurmurHash2(NSUInteger hash1, NSUInteger hash2); + +NSUInteger YapMurmurHash3(NSUInteger hash1, NSUInteger hash2, NSUInteger hash3); + +NSUInteger YapMurmurHashData(NSData *data); + +int32_t YapMurmurHashData_32(NSData *data); +int64_t YapMurmurHashData_64(NSData *data); + +#endif diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.m b/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.m new file mode 100644 index 0000000..c3a8ef4 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapMurmurHash.m @@ -0,0 +1,403 @@ +#import "YapMurmurHash.h" + +/** + * MurmurHash2 was written by Austin Appleby, and is placed in the public domain. + * http://code.google.com/p/smhasher +**/ +NSUInteger YapMurmurHash2(NSUInteger hash1, NSUInteger hash2) +{ + if (NSUIntegerMax == UINT32_MAX) // Should be optimized out via compiler since these are constants + { + // MurmurHash2 (32-bit) + // + // uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) + // + // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). + // Instead we're going to use our 2 hashes. + // And we're going to randomly make up a 'seed'. + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + const uint32_t len = 8; // 2 hashes, each 4 bytes = 8 bytes + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint32_t m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + uint32_t h = seed ^ len; + uint32_t k; + + // Mix hash1 + + k = hash1; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + // Mix khash + + k = hash2; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return (NSUInteger)h; + } + else + { + // MurmurHash2 (64-bit) + // + // uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed ) + // + // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). + // Instead we're going to use our 3 hashes. + // And we're going to randomly make up a 'seed'. + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + const uint32_t len = 16; // 2 hashes, each 8 bytes = 16 bytes + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint64_t m = 0xc6a4a7935bd1e995LLU; + const int r = 47; + + // Initialize the hash to a 'random' value + + uint64_t h = seed ^ (len * m); + uint64_t k; + + // Mix hash1 + + k = hash1; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Mix hash2 + + k = hash2; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return (NSUInteger)h; + } +} + + +/** + * MurmurHash2 was written by Austin Appleby, and is placed in the public domain. + * http://code.google.com/p/smhasher +**/ +NSUInteger YapMurmurHash3(NSUInteger hash1, NSUInteger hash2, NSUInteger hash3) +{ + if (NSUIntegerMax == UINT32_MAX) // Should be optimized out via compiler since these are constants + { + // MurmurHash2 (32-bit) + // + // uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) + // + // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). + // Instead we're going to use our 3 hashes. + // And we're going to randomly make up a 'seed'. + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + const uint32_t len = 12; // 3 hashes, each 4 bytes = 12 bytes + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint32_t m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + uint32_t h = seed ^ len; + uint32_t k; + + // Mix hash1 + + k = hash1; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + // Mix hash2 + + k = hash2; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + // Mix hash3 + + k = hash3; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return (NSUInteger)h; + } + else + { + // MurmurHash2 (64-bit) + // + // uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed ) + // + // Normally one would pass a chunk of data ('key') and associated data chunk length ('len'). + // Instead we're going to use our 3 hashes. + // And we're going to randomly make up a 'seed'. + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + const uint32_t len = 24; // 3 hashes, each 8 bytes = 24 bytes + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint64_t m = 0xc6a4a7935bd1e995LLU; + const int r = 47; + + // Initialize the hash to a 'random' value + + uint64_t h = seed ^ (len * m); + uint64_t k; + + // Mix hash1 + + k = hash1; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Mix hash2 + + k = hash2; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Mix hash3 + + k = hash3; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return (NSUInteger)h; + } +} + +/** + * MurmurHash2 was written by Austin Appleby, and is placed in the public domain. + * http://code.google.com/p/smhasher +**/ +NSUInteger YapMurmurHashData(NSData *inData) +{ + if (NSUIntegerMax == UINT32_MAX) // Should be optimized out via compiler since these are constants + { + return (NSUInteger)YapMurmurHashData_32(inData); + } + else + { + return (NSUInteger)YapMurmurHashData_64(inData); + } +} + +int32_t YapMurmurHashData_32(NSData *inData) +{ + // MurmurHash2 (32-bit) + // + // uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) + // + // The 'key' and 'len' parameters come from the passed data. + // And we're going to randomly make up a 'seed'. + + const unsigned char *data = (const unsigned char *)[inData bytes]; + uint32_t len = (uint32_t)[inData length]; + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint32_t m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + uint32_t h = seed ^ len; + + // Mix 4 bytes at a time into the hash + + while (len >= 4) + { + uint32_t k = *(uint32_t*)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input data + + switch (len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return (int32_t)h; +} + +int64_t YapMurmurHashData_64(NSData *inData) +{ + // MurmurHash2 (64-bit) + // + // uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed ) + // + // he 'key' and 'len' parameters come from the passed data. + // And we're going to randomly make up a 'seed'. + + const uint32_t seed = 0xa2f1b6f; // Some random value I made up + + int len = (int)[inData length]; + + const uint64_t * data = (const uint64_t *)[inData bytes]; + const uint64_t * end = data + (len/8); + + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint64_t m = 0xc6a4a7935bd1e995LLU; + const int r = 47; + + // Initialize the hash to a 'random' value + + uint64_t h = seed ^ (len * m); + + // Mix 8 bytes at a time into the hash + + while(data != end) + { + uint64_t k = *data++; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + + // Handle the last few bytes of the input data + + const unsigned char *data2 = (const unsigned char *)data; + + switch (len & 7) + { + case 7: h ^= (uint64_t)(data2[6]) << 48; + case 6: h ^= (uint64_t)(data2[5]) << 40; + case 5: h ^= (uint64_t)(data2[4]) << 32; + case 4: h ^= (uint64_t)(data2[3]) << 24; + case 3: h ^= (uint64_t)(data2[2]) << 16; + case 2: h ^= (uint64_t)(data2[1]) << 8; + case 1: h ^= (uint64_t)(data2[0]); + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return (int64_t)h; +} diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h b/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h index c86859d..7cf26a9 100644 --- a/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h @@ -36,6 +36,6 @@ // It is designed to expose them in the form of a set. // // If you make improvements, feel free to submit a patch to the github project and get some good karma for it! -// https://github.com/yaptv/YapDatabase +// https://github.com/yapstudios/YapDatabase @end diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h b/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h new file mode 100644 index 0000000..15dcc0d --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.h @@ -0,0 +1,55 @@ +#import + + +typedef BOOL (^YapWhitelistBlacklistFilterBlock)(id item); + +/** + * This class provides a standardized way to create a sort of whitelist / blacklist. + * It is used often within the options of extensions to create the set of allowedCollections. +**/ +@interface YapWhitelistBlacklist : NSObject + +/** + * Creates a whitelist based instance. + * + * Only items in the whitelist are allowed. + * Any items not in the whitelist are disallowed. +**/ +- (instancetype)initWithWhitelist:(NSSet *)whitelist; + +/** + * Creates a blacklist based instance. + * + * Only items in the blacklist are disallowed. + * Any items not in the blacklist are allowed. +**/ +- (instancetype)initWithBlacklist:(NSSet *)blacklist; + +/** + * Creates a filterBlock based instance. + * + * Rather than a known whitelist/blacklist, the filterBlock makes it possible to use app-specific criteria. + * For example, using prefix matching, regular expressions, etc. + * + * When creating your block, you must keep in mind 2 things: + * + * 1.) YapDatabase extensions may invoke the filterBlock from background threads durind readWriteTransactions. + * Thus your filterBlock MUST be thread-safe. + * + * 2.) The filterBlock is expected to be IMMUTABLE. + * That is, if the fitlerBlock is invoked with item X, and the filterBlock returns YES, + * then the filterBlock must always return YES for X. + * It should not "change its mind" about X. + * + * If the filterBlock returns YES for a given item, that item is allowed. + * If the filterBlock returns NO for a given item, that item is disallowed. +**/ +- (instancetype)initWithFilterBlock:(YapWhitelistBlacklistFilterBlock)block; + +/** + * Inspects the whitelist or blacklist, or consults the filterBlock (depending on initialization), + * and returns whether or not the item is allowed. +**/ +- (BOOL)isAllowed:(id)item; + +@end diff --git a/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.m b/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.m new file mode 100644 index 0000000..bf8c865 --- /dev/null +++ b/Pods/YapDatabase/YapDatabase/Utilities/YapWhitelistBlacklist.m @@ -0,0 +1,61 @@ +#import "YapWhitelistBlacklist.h" + + +@implementation YapWhitelistBlacklist +{ + NSSet *whitelist; + NSSet *blacklist; + + YapWhitelistBlacklistFilterBlock filterBlock; +} + +// See header file for documentation +- (instancetype)initWithWhitelist:(NSSet *)inWhitelist +{ + if ((self = [super init])) + { + whitelist = inWhitelist ? [inWhitelist copy] : [[NSSet alloc] init]; + } + return self; +} + +// See header file for documentation +- (instancetype)initWithBlacklist:(NSSet *)inBlacklist +{ + if ((self = [super init])) + { + blacklist = inBlacklist ? [inBlacklist copy] : [[NSSet alloc] init]; + } + return self; +} + +// See header file for documentation +- (instancetype)initWithFilterBlock:(YapWhitelistBlacklistFilterBlock)block +{ + if (block == NULL) return nil; + + if ((self = [super init])) + { + filterBlock = block; + } + return self; +} + +// See header file for documentation +- (BOOL)isAllowed:(id)item +{ + if (whitelist) + { + return [whitelist containsObject:item]; + } + else if (blacklist) + { + return ![blacklist containsObject:item]; + } + else + { + return filterBlock(item); + } +} + +@end diff --git a/Pods/YapDatabase/YapDatabase/YapDatabase.h b/Pods/YapDatabase/YapDatabase/YapDatabase.h index 087eb87..5a6be03 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabase.h +++ b/Pods/YapDatabase/YapDatabase/YapDatabase.h @@ -9,10 +9,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * The YapDatabase class is the top level class used to initialize the database. * It largely represents the immutable aspects of the database such as: @@ -30,7 +30,7 @@ * How does YapDatabase store my objects to disk? * * That question is answered extensively in the wiki article "Storing Objects": - * https://github.com/yaptv/YapDatabase/wiki/Storing-Objects + * https://github.com/yapstudios/YapDatabase/wiki/Storing-Objects * * Here's the intro from the wiki article: * @@ -60,23 +60,46 @@ typedef NSData* (^YapDatabaseSerializer)(NSString *collection, NSString *key, id typedef id (^YapDatabaseDeserializer)(NSString *collection, NSString *key, NSData *data); /** - * Is it safe to store mutable objects in the database? + * The sanitizer block allows you to enforce desired behavior of the objects you put into the database. * - * That question is answered extensively in the wiki article "Thread Safety": - * https://github.com/yaptv/YapDatabase/wiki/Thread-Safety + * If set, the sanitizer block will be run on all items being input into the database via + * the setObject:forKey:inCollection: (and other setObject:XXX: methods). + * + * You have 2 different hooks for running a sanitizer block: * - * The sanitizer block can be run on all objects as they are being input into the database. - * That is, it will be run on all objects passed to setObject:forKey:inCollection: before - * being handed to the database internals. + * The PreSanitizer is run: + * - Before the object is serialized + * - Before the object is stored in the cache + * - Before the object is passed to extensions + * + * The PostSanitizer is run: + * - After the object has been serialized + * - After the object has been stored in the cache + * - After the object has been passed to extensions + * + * The PreSanitizer is generally used validate the objects going into the database, + * and/or to enforce immutability of those objects. + * + * Enforcing immutability is a topic covered in the "Object Policy" wiki article: + * https://github.com/yapstudios/YapDatabase/wiki/Object-Policy + * + * The PostSanitizer is generally used to "clear flags" that are used by extensions. + * For example, your objects might have a "changedProperties" property that tells extensions exactly + * what properties where changed on a modified object. And the extension uses that information + * in order to automatically sync the changes to the cloud. Thus the PostSanitizer would be used + * to clear the "changedProperties" after the extension has processed the modified object. + * + * An example of such a use for the PostSanitizer is discussed in the YapDatabaseCloudKit wiki article: + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseCloudKit **/ -typedef id (^YapDatabaseSanitizer)(NSString *collection, NSString *key, id object); - +typedef id (^YapDatabasePreSanitizer)(NSString *collection, NSString *key, id obj); +typedef void (^YapDatabasePostSanitizer)(NSString *collection, NSString *key, id obj); /** * This notification is posted following a readwrite transaction where the database was modified. * * It is documented in more detail in the wiki article "YapDatabaseModifiedNotification": - * https://github.com/yaptv/YapDatabase/wiki/YapDatabaseModifiedNotification + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseModifiedNotification * * The notification object will be the database instance itself. * That is, it will be an instance of YapDatabase. @@ -140,12 +163,15 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; /** * Opens or creates a sqlite database with the given path. - * The default serializer and deserializer are used. + * The defaults are used for everything. + * + * In particular, the defaultSerializer and defaultDeserializer are used. (NSCoding) * No sanitizer is used. * The default options are used. * * @see defaultSerializer * @see defaultDeserializer + * @see YapDatabaseOptions * * Example code: * @@ -166,6 +192,16 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; serializer:(YapDatabaseSerializer)serializer deserializer:(YapDatabaseDeserializer)deserializer; +/** + * Opens or creates a sqlite database with the given path. + * The given serializer and deserializer are used for both objects and metadata. + * The given options are used instead of the default options. +**/ +- (id)initWithPath:(NSString *)path + serializer:(YapDatabaseSerializer)serializer + deserializer:(YapDatabaseDeserializer)deserializer + options:(YapDatabaseOptions *)options; + /** * Opens or creates a sqlite database with the given path. * The given serializer and deserializer are used for both objects and metadata. @@ -174,7 +210,9 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; - (id)initWithPath:(NSString *)path serializer:(YapDatabaseSerializer)serializer deserializer:(YapDatabaseDeserializer)deserializer - sanitizer:(YapDatabaseSanitizer)sanitizer; + preSanitizer:(YapDatabasePreSanitizer)preSanitizer + postSanitizer:(YapDatabasePostSanitizer)postSanitizer + options:(YapDatabaseOptions *)options; /** * Opens or creates a sqlite database with the given path. @@ -195,8 +233,7 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; objectDeserializer:(YapDatabaseDeserializer)objectDeserializer metadataSerializer:(YapDatabaseSerializer)metadataSerializer metadataDeserializer:(YapDatabaseDeserializer)metadataDeserializer - objectSanitizer:(YapDatabaseSanitizer)objectSanitizer - metadataSanitizer:(YapDatabaseSanitizer)metadataSanitizer; + options:(YapDatabaseOptions *)options; /** * Opens or creates a sqlite database with the given path. @@ -207,8 +244,10 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; objectDeserializer:(YapDatabaseDeserializer)objectDeserializer metadataSerializer:(YapDatabaseSerializer)metadataSerializer metadataDeserializer:(YapDatabaseDeserializer)metadataDeserializer - objectSanitizer:(YapDatabaseSanitizer)objectSanitizer - metadataSanitizer:(YapDatabaseSanitizer)metadataSanitizer + objectPreSanitizer:(YapDatabasePreSanitizer)objectPreSanitizer + objectPostSanitizer:(YapDatabasePostSanitizer)objectPostSanitizer + metadataPreSanitizer:(YapDatabasePreSanitizer)metadataPreSanitizer + metadataPostSanitizer:(YapDatabasePostSanitizer)metadataPostSanitizer options:(YapDatabaseOptions *)options; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -223,8 +262,11 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; @property (nonatomic, strong, readonly) YapDatabaseSerializer metadataSerializer; @property (nonatomic, strong, readonly) YapDatabaseDeserializer metadataDeserializer; -@property (nonatomic, strong, readonly) YapDatabaseSanitizer objectSanitizer; -@property (nonatomic, strong, readonly) YapDatabaseSanitizer metadataSanitizer; +@property (nonatomic, strong, readonly) YapDatabasePreSanitizer objectPreSanitizer; +@property (nonatomic, strong, readonly) YapDatabasePostSanitizer objectPostSanitizer; + +@property (nonatomic, strong, readonly) YapDatabasePreSanitizer metadataPreSanitizer; +@property (nonatomic, strong, readonly) YapDatabasePostSanitizer metadataPostSanitizer; @property (nonatomic, copy, readonly) YapDatabaseOptions *options; @@ -289,6 +331,11 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; **/ @property (atomic, assign, readonly) uint64_t snapshot; +/** + * Returns the version of sqlite being used. +**/ +@property (atomic, strong, readonly) NSString *sqliteVersion; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Defaults //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -407,10 +454,19 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; * Registers the extension with the database using the given name. * After registration everything works automatically using just the extension name. * - * The registration process is equivalent to a readwrite transaction. + * The registration process is equivalent to a (synchronous) readwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * + * @param extension + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * * @return * YES if the extension was properly registered. * NO if an error occurred, such as the extensionName is already registered. @@ -421,17 +477,56 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; - (BOOL)registerExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName; /** - * Asynchronoulsy starts the extension registration process. + * Registers the extension with the database using the given name. * After registration everything works automatically using just the extension name. - * - * The registration process is equivalent to a readwrite transaction. + * + * The registration process is equivalent to a (synchronous) readwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * - * An optional completion block may be used. - * If the extension registration was successful then the ready parameter will be YES. + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. * - * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * This allows you to control things such as the cache size of the connection that performs + * the extension registration code (sometimes important for performance tuning.) + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @see asyncRegisterExtension:withName:completionBlock: + * @see asyncRegisterExtension:withName:completionQueue:completionBlock: +**/ +- (BOOL)registerExtension:(YapDatabaseExtension *)extension + withName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection; + +/** + * Asynchronoulsy starts the extension registration process. + * After registration everything works automatically using just the extension name. + * + * The registration process is equivalent to an asyncReadwrite transaction. + * It involves persisting various information about the extension to the database, + * as well as possibly populating the extension by enumerating existing rows in the database. + * + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. + * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). **/ - (void)asyncRegisterExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName @@ -441,21 +536,69 @@ extern NSString *const YapDatabaseAllKeysRemovedKey; * Asynchronoulsy starts the extension registration process. * After registration everything works automatically using just the extension name. * - * The registration process is equivalent to a readwrite transaction. + * The registration process is equivalent to an asyncReadwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * - * An optional completion block may be used. - * If the extension registration was successful then the ready parameter will be YES. - * - * Additionally the dispatch_queue to invoke the completion block may also be specified. - * If NULL, dispatch_get_main_queue() is automatically used. + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. **/ - (void)asyncRegisterExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName completionQueue:(dispatch_queue_t)completionQueue completionBlock:(void(^)(BOOL ready))completionBlock; +/** + * Asynchronoulsy starts the extension registration process. + * After registration everything works automatically using just the extension name. + * + * The registration process is equivalent to an asyncReadwrite transaction. + * It involves persisting various information about the extension to the database, + * as well as possibly populating the extension by enumerating existing rows in the database. + * + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * This allows you to control things such as the cache size of the connection that performs + * the extension registration code (sometimes important for performance tuning.) + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. +**/ +- (void)asyncRegisterExtension:(YapDatabaseExtension *)extension + withName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection + completionQueue:(dispatch_queue_t)completionQueue + completionBlock:(void(^)(BOOL ready))completionBlock; + /** * DEPRECATED in v2.5 * @@ -493,6 +636,13 @@ __attribute((deprecated("Use method asyncRegisterExtension:withName:completionQu * This method unregisters an extension with the given name. * The associated underlying tables will be dropped from the database. * + * The unregistration process is equivalent to a (synchronous) readwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * * Note 1: * You don't need to re-register an extension in order to unregister it. For example, * you've previously registered an extension (in previous app launches), but you no longer need the extension. @@ -506,7 +656,8 @@ __attribute((deprecated("Use method asyncRegisterExtension:withName:completionQu * In fact, you don't even have to worry about unregistering extensions that you no longer need. * That database system will automatically handle it for you. * That is, upon completion of the first readWrite transaction (that makes changes), the database system will - * check to see if there are any "orphaned" extensions. Previously registered extensions that are no longer in use. + * check to see if there are any "orphaned" extensions. That is, previously registered extensions that are + * no longer in use (and are now out-of-date because they didn't process the recent change(s) to the db). * And it will automatically unregister these orhpaned extensions for you. * * @see asyncUnregisterExtensionWithName:completionBlock: @@ -515,15 +666,35 @@ __attribute((deprecated("Use method asyncRegisterExtension:withName:completionQu - (void)unregisterExtensionWithName:(NSString *)extensionName; /** - * Asynchronoulsy starts the extension unregistration process. + * This method unregisters an extension with the given name. + * The associated underlying tables will be dropped from the database. * - * The unregistration process is equivalent to a readwrite transaction. + * The unregistration process is equivalent to a (synchronous) readwrite transaction. * It involves deleting various information about the extension from the database, * as well as possibly dropping related tables the extension may have been using. * - * An optional completion block may be used. + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. * - * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * If you pass nil, an internal databaseConnection will automatically be used. +**/ +- (void)unregisterExtensionWithName:(NSString *)extensionName connection:(YapDatabaseConnection *)connection; + +/** + * Asynchronoulsy starts the extension unregistration process. + * + * The unregistration process is equivalent to an asyncReadwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). **/ - (void)asyncUnregisterExtensionWithName:(NSString *)extensionName completionBlock:(dispatch_block_t)completionBlock; @@ -531,19 +702,52 @@ __attribute((deprecated("Use method asyncRegisterExtension:withName:completionQu /** * Asynchronoulsy starts the extension unregistration process. * - * The unregistration process is equivalent to a readwrite transaction. + * The unregistration process is equivalent to an asyncReadwrite transaction. * It involves deleting various information about the extension from the database, * as well as possibly dropping related tables the extension may have been using. * - * An optional completion block may be used. + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. * - * Additionally the dispatch_queue to invoke the completion block may also be specified. - * If NULL, dispatch_get_main_queue() is automatically used. + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. **/ - (void)asyncUnregisterExtensionWithName:(NSString *)extensionName completionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock; +/** + * Asynchronoulsy starts the extension unregistration process. + * + * The unregistration process is equivalent to an asyncReadwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. +**/ +- (void)asyncUnregisterExtensionWithName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection + completionQueue:(dispatch_queue_t)completionQueue + completionBlock:(dispatch_block_t)completionBlock; + /** * DEPRECATED in v2.5 * @@ -601,12 +805,28 @@ __attribute((deprecated("Use method asyncUnregisterExtensionWithName:completionQ **/ - (NSDictionary *)registeredExtensions; +/** + * Allows you to fetch the registered extension names from the last time the database was run. + * Typically this means from the last time the app was run. + * + * This may be used to assist in various tasks, such as cleanup or upgrade tasks. + * + * If you need this information, you should fetch it early on because YapDatabase only maintains this information + * until it sees you are done registering all your initial extensions. That is, after one initializes the database + * they then immediately register any needed initial extensions before they begin to use the database. Once a + * readWriteTransaction modifies the database, YapDatabase will take this opportunity to look for orphaned extensions. + * These are extensions that were registered at the end of the last database session, + * but which are no longer registered. YapDatabase will automatically cleanup these orphaned extensions, + * and also clear the previouslyRegisteredExtensionNames information at this point. +**/ +- (NSArray *)previouslyRegisteredExtensionNames; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Connection Pooling //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** - * As recommended in the "Performance Primer" ( https://github.com/yaptv/YapDatabase/wiki/Performance-Primer ) + * As recommended in the "Performance Primer" ( https://github.com/yapstudios/YapDatabase/wiki/Performance-Primer ) * * > You should consider connections to be relatively heavy weight objects. * > diff --git a/Pods/YapDatabase/YapDatabase/YapDatabase.m b/Pods/YapDatabase/YapDatabase/YapDatabase.m index df1c899..ff7215c 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabase.m +++ b/Pods/YapDatabase/YapDatabase/YapDatabase.m @@ -60,7 +60,37 @@ NSString *const YapDatabaseNotificationKey = @"notification"; #define DEFAULT_CONNECTION_POOL_LIFETIME 90.0 // seconds -@implementation YapDatabase +@implementation YapDatabase { +@private + + YapDatabaseOptions *options; + + sqlite3 *db; // Used for setup & checkpoints + + NSMutableArray *changesets; + uint64_t snapshot; + + dispatch_queue_t internalQueue; + dispatch_queue_t checkpointQueue; + + YapDatabaseConnectionDefaults *connectionDefaults; + + NSDictionary *registeredExtensions; + NSDictionary *registeredMemoryTables; + + NSArray *extensionsOrder; + NSDictionary *extensionDependencies; + + YapDatabaseConnection *registrationConnection; + + NSUInteger maxConnectionPoolCount; + NSTimeInterval connectionPoolLifetime; + dispatch_source_t connectionPoolTimer; + NSMutableArray *connectionPoolValues; + NSMutableArray *connectionPoolDates; + + NSString *sqliteVersion; +} /** * The default serializer & deserializer use NSCoding (NSKeyedArchiver & NSKeyedUnarchiver). @@ -166,18 +196,35 @@ NSString *const YapDatabaseNotificationKey = @"notification"; @synthesize objectSerializer = objectSerializer; @synthesize objectDeserializer = objectDeserializer; + @synthesize metadataSerializer = metadataSerializer; @synthesize metadataDeserializer = metadataDeserializer; -@synthesize objectSanitizer = objectSanitizer; -@synthesize metadataSanitizer = metadataSanitizer; + +@synthesize objectPreSanitizer = objectPreSanitizer; +@synthesize objectPostSanitizer = objectPostSanitizer; + +@synthesize metadataPreSanitizer = metadataPreSanitizer; +@synthesize metadataPostSanitizer = metadataPostSanitizer; @dynamic options; +@dynamic sqliteVersion; - (YapDatabaseOptions *)options { return [options copy]; } +- (NSString *)sqliteVersion +{ + __block NSString *result = nil; + + dispatch_sync(snapshotQueue, ^{ + result = sqliteVersion; + }); + + return result; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Init //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -189,8 +236,10 @@ NSString *const YapDatabaseNotificationKey = @"notification"; objectDeserializer:NULL metadataSerializer:NULL metadataDeserializer:NULL - objectSanitizer:NULL - metadataSanitizer:NULL + objectPreSanitizer:NULL + objectPostSanitizer:NULL + metadataPreSanitizer:NULL + metadataPostSanitizer:NULL options:nil]; } @@ -203,24 +252,47 @@ NSString *const YapDatabaseNotificationKey = @"notification"; objectDeserializer:inDeserializer metadataSerializer:inSerializer metadataDeserializer:inDeserializer - objectSanitizer:NULL - metadataSanitizer:NULL - options:nil]; + objectPreSanitizer:NULL + objectPostSanitizer:NULL + metadataPreSanitizer:NULL + metadataPostSanitizer:NULL + options:nil]; } - (id)initWithPath:(NSString *)inPath serializer:(YapDatabaseSerializer)inSerializer deserializer:(YapDatabaseDeserializer)inDeserializer - sanitizer:(YapDatabaseSanitizer)inSanitizer + options:(YapDatabaseOptions *)inOptions { return [self initWithPath:inPath objectSerializer:inSerializer objectDeserializer:inDeserializer metadataSerializer:inSerializer metadataDeserializer:inDeserializer - objectSanitizer:inSanitizer - metadataSanitizer:inSanitizer - options:nil]; + objectPreSanitizer:NULL + objectPostSanitizer:NULL + metadataPreSanitizer:NULL + metadataPostSanitizer:NULL + options:inOptions]; +} + +- (id)initWithPath:(NSString *)inPath + serializer:(YapDatabaseSerializer)inSerializer + deserializer:(YapDatabaseDeserializer)inDeserializer + preSanitizer:(YapDatabasePreSanitizer)inPreSanitizer + postSanitizer:(YapDatabasePostSanitizer)inPostSanitizer + options:(YapDatabaseOptions *)inOptions +{ + return [self initWithPath:inPath + objectSerializer:inSerializer + objectDeserializer:inDeserializer + metadataSerializer:inSerializer + metadataDeserializer:inDeserializer + objectPreSanitizer:inPreSanitizer + objectPostSanitizer:inPostSanitizer + metadataPreSanitizer:inPreSanitizer + metadataPostSanitizer:inPostSanitizer + options:inOptions]; } - (id)initWithPath:(NSString *)inPath objectSerializer:(YapDatabaseSerializer)inObjectSerializer @@ -233,8 +305,10 @@ NSString *const YapDatabaseNotificationKey = @"notification"; objectDeserializer:inObjectDeserializer metadataSerializer:inMetadataSerializer metadataDeserializer:inMetadataDeserializer - objectSanitizer:NULL - metadataSanitizer:NULL + objectPreSanitizer:NULL + objectPostSanitizer:NULL + metadataPreSanitizer:NULL + metadataPostSanitizer:NULL options:nil]; } @@ -242,16 +316,17 @@ NSString *const YapDatabaseNotificationKey = @"notification"; objectDeserializer:(YapDatabaseDeserializer)inObjectDeserializer metadataSerializer:(YapDatabaseSerializer)inMetadataSerializer metadataDeserializer:(YapDatabaseDeserializer)inMetadataDeserializer - objectSanitizer:(YapDatabaseSanitizer)inObjectSanitizer - metadataSanitizer:(YapDatabaseSanitizer)inMetadataSanitizer; + options:(YapDatabaseOptions *)inOptions { return [self initWithPath:inPath objectSerializer:inObjectSerializer objectDeserializer:inObjectDeserializer metadataSerializer:inMetadataSerializer metadataDeserializer:inMetadataDeserializer - objectSanitizer:inObjectSanitizer - metadataSanitizer:inMetadataSanitizer + objectPreSanitizer:NULL + objectPostSanitizer:NULL + metadataPreSanitizer:NULL + metadataPostSanitizer:NULL options:nil]; } @@ -259,8 +334,10 @@ NSString *const YapDatabaseNotificationKey = @"notification"; objectDeserializer:(YapDatabaseDeserializer)inObjectDeserializer metadataSerializer:(YapDatabaseSerializer)inMetadataSerializer metadataDeserializer:(YapDatabaseDeserializer)inMetadataDeserializer - objectSanitizer:(YapDatabaseSanitizer)inObjectSanitizer - metadataSanitizer:(YapDatabaseSanitizer)inMetadataSanitizer + objectPreSanitizer:(YapDatabasePreSanitizer)inObjectPreSanitizer + objectPostSanitizer:(YapDatabasePostSanitizer)inObjectPostSanitizer + metadataPreSanitizer:(YapDatabasePreSanitizer)inMetadataPreSanitizer + metadataPostSanitizer:(YapDatabasePostSanitizer)inMetadataPostSanitizer options:(YapDatabaseOptions *)inOptions { // First, standardize path. @@ -426,8 +503,11 @@ NSString *const YapDatabaseNotificationKey = @"notification"; metadataSerializer = inMetadataSerializer ? inMetadataSerializer : defaultSerializer; metadataDeserializer = inMetadataDeserializer ? inMetadataDeserializer : defaultDeserializer; - objectSanitizer = inObjectSanitizer; - metadataSanitizer = inMetadataSanitizer; + objectPreSanitizer = inObjectPreSanitizer; + objectPostSanitizer = inObjectPostSanitizer; + + metadataPreSanitizer = inMetadataPreSanitizer; + metadataPostSanitizer = inMetadataPostSanitizer; // Mark the queues so we can identify them. // There are several methods whose use is restricted to within a certain queue. @@ -607,21 +687,18 @@ NSString *const YapDatabaseNotificationKey = @"notification"; { int status; - NSAssert(options.passphraseBlock != nil, @"Passphrase block must not be nil when using SQLCipher!"); + NSAssert(options.cipherKeyBlock != NULL, @"YapDatabaseOptions.cipherKeyBlock must be set when using SQLCipher!"); - NSString *passphrase = options.passphraseBlock(); - - NSAssert(passphrase != nil, @"SQLCipher passphrase cannot be nil!"); - - const char *key = [passphrase UTF8String]; - NSUInteger keyLength = [passphrase lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - status = sqlite3_key(sqlite, key, (int)keyLength); - if (status != SQLITE_OK) + NSData *keyData = options.cipherKeyBlock(); + NSAssert(keyData != nil, @"SQLCipher key cannot be nil!"); + + status = sqlite3_key(sqlite, [keyData bytes], (int)[keyData length]); + if (status != SQLITE_OK) { - YDBLogError(@"Error setting up sqlcipher key: %d %s", status, sqlite3_errmsg(sqlite)); + YDBLogError(@"Error setting SQLCipher key: %d %s", status, sqlite3_errmsg(sqlite)); return NO; } - return YES; + return YES; } #endif @@ -683,14 +760,14 @@ NSString *const YapDatabaseNotificationKey = @"notification"; #pragma mark Utilities //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -+ (NSString *)sqliteVersionUsing:(sqlite3 *)db ++ (NSString *)sqliteVersionUsing:(sqlite3 *)aDb { sqlite3_stmt *statement; - int status = sqlite3_prepare_v2(db, "SELECT sqlite_version();", -1, &statement, NULL); + int status = sqlite3_prepare_v2(aDb, "SELECT sqlite_version();", -1, &statement, NULL); if (status != SQLITE_OK) { - YDBLogError(@"%@: Error creating statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); + YDBLogError(@"%@: Error creating statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(aDb)); return nil; } @@ -706,7 +783,7 @@ NSString *const YapDatabaseNotificationKey = @"notification"; } else { - YDBLogError(@"%@: Error executing statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); + YDBLogError(@"%@: Error executing statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(aDb)); } sqlite3_finalize(statement); @@ -715,21 +792,21 @@ NSString *const YapDatabaseNotificationKey = @"notification"; return version; } -+ (int)pragma:(NSString *)pragmaSetting using:(sqlite3 *)db ++ (int)pragma:(NSString *)pragmaSetting using:(sqlite3 *)aDb { - if (pragmaSetting == nil) return 0; + if (pragmaSetting == nil) return -1; sqlite3_stmt *statement; NSString *pragma = [NSString stringWithFormat:@"PRAGMA %@;", pragmaSetting]; - int status = sqlite3_prepare_v2(db, [pragma UTF8String], -1, &statement, NULL); + int status = sqlite3_prepare_v2(aDb, [pragma UTF8String], -1, &statement, NULL); if (status != SQLITE_OK) { - YDBLogError(@"%@: Error creating statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); + YDBLogError(@"%@: Error creating statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(aDb)); return NO; } - int result = 0; + int result = -1; status = sqlite3_step(statement); if (status == SQLITE_ROW) @@ -738,7 +815,7 @@ NSString *const YapDatabaseNotificationKey = @"notification"; } else if (status == SQLITE_ERROR) { - YDBLogError(@"%@: Error executing statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(db)); + YDBLogError(@"%@: Error executing statement! %d %s", THIS_METHOD, status, sqlite3_errmsg(aDb)); } sqlite3_finalize(statement); @@ -1084,9 +1161,6 @@ NSString *const YapDatabaseNotificationKey = @"notification"; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** - * Optional override hook. - * Don't forget to invoke [super prepare] so super can prepare too. - * * This method is run asynchronously on the snapshotQueue. **/ - (void)prepare @@ -1099,12 +1173,11 @@ NSString *const YapDatabaseNotificationKey = @"notification"; [self beginTransaction]; { - #if 0 - YDBLogVerbose(@"sqlite version = %@", [YapDatabase sqliteVersionUsing:db]); - #endif + sqliteVersion = [YapDatabase sqliteVersionUsing:db]; + YDBLogVerbose(@"sqlite version = %@", sqliteVersion); - [self writeSnapshot]; [self fetchPreviouslyRegisteredExtensionNames]; + [self writeSnapshot]; } [self commitTransaction]; } @@ -1455,10 +1528,19 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * Registers the extension with the database using the given name. * After registration everything works automatically using just the extension name. * - * The registration process is equivalent to a readwrite transaction. + * The registration process is equivalent to a (synchronous) readwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * + * @param extension + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * * @return * YES if the extension was properly registered. * NO if an error occurred, such as the extensionName is already registered. @@ -1467,12 +1549,44 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * @see asyncRegisterExtension:withName:completionQueue:completionBlock: **/ - (BOOL)registerExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName +{ + return [self registerExtension:extension withName:extensionName connection:nil]; +} + +/** + * Registers the extension with the database using the given name. + * After registration everything works automatically using just the extension name. + * + * The registration process is equivalent to a (synchronous) readwrite transaction. + * It involves persisting various information about the extension to the database, + * as well as possibly populating the extension by enumerating existing rows in the database. + * + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * This allows you to control things such as the cache size of the connection that performs + * the extension registration code (sometimes important for performance tuning.) + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @see asyncRegisterExtension:withName:completionBlock: + * @see asyncRegisterExtension:withName:completionQueue:completionBlock: +**/ +- (BOOL)registerExtension:(YapDatabaseExtension *)extension + withName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection { __block BOOL ready = NO; - dispatch_sync(writeQueue, ^{ @autoreleasepool { - ready = [self _registerExtension:extension withName:extensionName]; + ready = [self _registerExtension:extension withName:extensionName connection:connection]; }}); return ready; @@ -1482,14 +1596,23 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * Asynchronoulsy starts the extension registration process. * After registration everything works automatically using just the extension name. * - * The registration process is equivalent to a readwrite transaction. + * The registration process is equivalent to an asyncReadwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * - * An optional completion block may be used. - * If the extension registration was successful then the ready parameter will be YES. + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. * - * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. + * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). **/ - (void)asyncRegisterExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName @@ -1497,6 +1620,7 @@ NSString *const YapDatabaseNotificationKey = @"notification"; { [self asyncRegisterExtension:extension withName:extensionName + connection:nil completionQueue:NULL completionBlock:completionBlock]; } @@ -1505,27 +1629,82 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * Asynchronoulsy starts the extension registration process. * After registration everything works automatically using just the extension name. * - * The registration process is equivalent to a readwrite transaction. + * The registration process is equivalent to an asyncReadwrite transaction. * It involves persisting various information about the extension to the database, * as well as possibly populating the extension by enumerating existing rows in the database. * - * An optional completion block may be used. - * If the extension registration was successful then the ready parameter will be YES. - * - * Additionally the dispatch_queue to invoke the completion block may also be specified. - * If NULL, dispatch_get_main_queue() is automatically used. + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. **/ - (void)asyncRegisterExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName completionQueue:(dispatch_queue_t)completionQueue completionBlock:(void(^)(BOOL ready))completionBlock +{ + [self asyncRegisterExtension:extension + withName:extensionName + connection:nil + completionQueue:completionQueue + completionBlock:completionBlock]; +} + +/** + * Asynchronoulsy starts the extension registration process. + * After registration everything works automatically using just the extension name. + * + * The registration process is equivalent to an asyncReadwrite transaction. + * It involves persisting various information about the extension to the database, + * as well as possibly populating the extension by enumerating existing rows in the database. + * + * @param extension (required) + * The YapDatabaseExtension subclass instance you wish to register. + * For example, this might be a YapDatabaseView instance. + * + * @param extensionName (required) + * This is an arbitrary string you assign to the extension. + * Once registered, you will generally access the extension instance via this name. + * For example: [[transaction ext:@"myView"] numberOfGroups]; + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * This allows you to control things such as the cache size of the connection that performs + * the extension registration code (sometimes important for performance tuning.) + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. +**/ +- (void)asyncRegisterExtension:(YapDatabaseExtension *)extension + withName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection + completionQueue:(dispatch_queue_t)completionQueue + completionBlock:(void(^)(BOOL ready))completionBlock { if (completionQueue == NULL && completionBlock != NULL) completionQueue = dispatch_get_main_queue(); dispatch_async(writeQueue, ^{ @autoreleasepool { - BOOL ready = [self _registerExtension:extension withName:extensionName]; + BOOL ready = [self _registerExtension:extension withName:extensionName connection:connection]; if (completionBlock) { @@ -1578,6 +1757,13 @@ NSString *const YapDatabaseNotificationKey = @"notification"; /** * This method unregisters an extension with the given name. * The associated underlying tables will be dropped from the database. + * + * The unregistration process is equivalent to a (synchronous) readwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. * * Note 1: * You don't need to re-register an extension in order to unregister it. For example, @@ -1592,35 +1778,60 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * In fact, you don't even have to worry about unregistering extensions that you no longer need. * That database system will automatically handle it for you. * That is, upon completion of the first readWrite transaction (that makes changes), the database system will - * check to see if there are any "orphaned" extensions. Previously registered extensions that are no longer in use. + * check to see if there are any "orphaned" extensions. That is, previously registered extensions that are + * no longer in use (and are now out-of-date because they didn't process the recent change(s) to the db). * And it will automatically unregister these orhpaned extensions for you. - * + * * @see asyncUnregisterExtensionWithName:completionBlock: * @see asyncUnregisterExtensionWithName:completionQueue:completionBlock: **/ - (void)unregisterExtensionWithName:(NSString *)extensionName +{ + [self unregisterExtensionWithName:extensionName connection:nil]; +} + +/** + * This method unregisters an extension with the given name. + * The associated underlying tables will be dropped from the database. + * + * The unregistration process is equivalent to a (synchronous) readwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * If you pass nil, an internal databaseConnection will automatically be used. +**/ +- (void)unregisterExtensionWithName:(NSString *)extensionName connection:(YapDatabaseConnection *)connection { dispatch_sync(writeQueue, ^{ @autoreleasepool { - [self _unregisterExtensionWithName:extensionName]; + [self _unregisterExtensionWithName:extensionName connection:connection]; }}); } /** * Asynchronoulsy starts the extension unregistration process. * - * The unregistration process is equivalent to a readwrite transaction. + * The unregistration process is equivalent to an asyncReadwrite transaction. * It involves deleting various information about the extension from the database, * as well as possibly dropping related tables the extension may have been using. * - * An optional completion block may be used. + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. * - * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * @param completionBlock (optional) + * An optional completion block may be used. + * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). **/ - (void)asyncUnregisterExtensionWithName:(NSString *)extensionName completionBlock:(dispatch_block_t)completionBlock { [self asyncUnregisterExtensionWithName:extensionName + connection:nil completionQueue:NULL completionBlock:completionBlock]; } @@ -1628,25 +1839,64 @@ NSString *const YapDatabaseNotificationKey = @"notification"; /** * Asynchronoulsy starts the extension unregistration process. * - * The unregistration process is equivalent to a readwrite transaction. + * The unregistration process is equivalent to an asyncReadwrite transaction. * It involves deleting various information about the extension from the database, * as well as possibly dropping related tables the extension may have been using. * - * An optional completion block may be used. + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. * - * Additionally the dispatch_queue to invoke the completion block may also be specified. - * If NULL, dispatch_get_main_queue() is automatically used. + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. **/ - (void)asyncUnregisterExtensionWithName:(NSString *)extensionName completionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock +{ + [self asyncUnregisterExtensionWithName:extensionName + connection:nil + completionQueue:completionQueue + completionBlock:completionBlock]; +} + +/** + * Asynchronoulsy starts the extension unregistration process. + * + * The unregistration process is equivalent to an asyncReadwrite transaction. + * It involves deleting various information about the extension from the database, + * as well as possibly dropping related tables the extension may have been using. + * + * @param extensionName (required) + * This is the arbitrary string you assigned to the extension when you registered it. + * + * @param connection (optional) + * You may optionally pass your own databaseConnection for this method to use. + * If you pass nil, an internal databaseConnection will automatically be used. + * + * @param completionQueue (optional) + * The dispatch_queue to invoke the completion block may optionally be specified. + * If NULL, dispatch_get_main_queue() is automatically used. + * + * @param completionBlock (optional) + * An optional completion block may be used. + * If the extension registration was successful then the ready parameter will be YES. +**/ +- (void)asyncUnregisterExtensionWithName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection + completionQueue:(dispatch_queue_t)completionQueue + completionBlock:(dispatch_block_t)completionBlock { if (completionQueue == NULL && completionBlock != NULL) completionQueue = dispatch_get_main_queue(); dispatch_async(writeQueue, ^{ @autoreleasepool { - [self _unregisterExtensionWithName:extensionName]; + [self _unregisterExtensionWithName:extensionName connection:connection]; if (completionBlock) { @@ -1706,7 +1956,7 @@ NSString *const YapDatabaseNotificationKey = @"notification"; registrationConnection = [self newConnection]; registrationConnection.name = @"YapDatabase_extensionRegistrationConnection"; - NSTimeInterval delayInSeconds = 10.0; + NSTimeInterval delayInSeconds = 5.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, writeQueue, ^(void){ @@ -1721,7 +1971,9 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * Internal method that handles extension registration. * This method must be invoked on the writeQueue. **/ -- (BOOL)_registerExtension:(YapDatabaseExtension *)extension withName:(NSString *)extensionName +- (BOOL)_registerExtension:(YapDatabaseExtension *)extension + withName:(NSString *)extensionName + connection:(YapDatabaseConnection *)connection { NSAssert(dispatch_get_specific(IsOnWriteQueueKey), @"Must go through writeQueue."); @@ -1764,7 +2016,10 @@ NSString *const YapDatabaseNotificationKey = @"notification"; // Attempt registration - BOOL result = [[self registrationConnection] registerExtension:extension withName:extensionName]; + if (connection == nil) + connection = [self registrationConnection]; + + BOOL result = [connection registerExtension:extension withName:extensionName]; return result; } @@ -1772,17 +2027,24 @@ NSString *const YapDatabaseNotificationKey = @"notification"; * Internal method that handles extension unregistration. * This method must be invoked on the writeQueue. **/ -- (void)_unregisterExtensionWithName:(NSString *)extensionName +- (void)_unregisterExtensionWithName:(NSString *)extensionName connection:(YapDatabaseConnection *)connection { NSAssert(dispatch_get_specific(IsOnWriteQueueKey), @"Must go through writeQueue."); + // Validate parameters + if ([extensionName length] == 0) { YDBLogError(@"Error unregistering extension: extensionName parameter is nil or empty string"); return; } - [[self registrationConnection] unregisterExtensionWithName:extensionName]; + // Perform unregistration + + if (connection == nil) + connection = [self registrationConnection]; + + [connection unregisterExtensionWithName:extensionName]; } /** @@ -1888,6 +2150,37 @@ NSString *const YapDatabaseNotificationKey = @"notification"; return extensionDependencies; } +/** + * Allows you to fetch the registered extension names from the last time the database was run. + * Typically this means from the last time the app was run. + * + * This may be used to assist in various tasks, such as cleanup or upgrade tasks. + * + * If you need this information, you should fetch it early on because YapDatabase only maintains this information + * until it sees you are done registering all your initial extensions. That is, after one initializes the database + * they then immediately register any needed initial extensions before they begin to use the database. Once a + * readWriteTransaction modifies the database, YapDatabase will take this opportunity to look for orphaned extensions. + * These are extensions that were registered at the end of the last database session, + * but which are no longer registered. YapDatabase will automatically cleanup these orphaned extensions, + * and also clear the previouslyRegisteredExtensionNames information at this point. +**/ +- (NSArray *)previouslyRegisteredExtensionNames +{ + __block NSArray *result = nil; + + dispatch_block_t block = ^{ + + result = [previouslyRegisteredExtensionNames copy]; + }; + + if (dispatch_get_specific(IsOnSnapshotQueueKey)) + block(); + else + dispatch_sync(snapshotQueue, block); + + return result; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Pooling //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h b/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h index 0867f62..d706ccf 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h @@ -1,4 +1,5 @@ #import +#import "YapCollectionKey.h" @class YapDatabase; @class YapDatabaseReadTransaction; @@ -8,10 +9,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * From a single YapDatabase instance you can create multiple connections. * Each connection is thread-safe and may be used concurrently with other connections. @@ -29,6 +30,40 @@ * But for conncurrent access between multiple threads you must use multiple connections. **/ +typedef NS_ENUM(NSInteger, YapDatabasePolicy) { + YapDatabasePolicyContainment = 0, + YapDatabasePolicyShare = 1, + YapDatabasePolicyCopy = 2, +}; + +#ifndef YapDatabaseEnforcePermittedTransactions + #if DEBUG + #define YapDatabaseEnforcePermittedTransactions 1 + #else + #define YapDatabaseEnforcePermittedTransactions 0 + #endif +#endif +#if YapDatabaseEnforcePermittedTransactions +typedef NS_OPTIONS(NSUInteger, YapDatabasePermittedTransactions) { + + YDB_SyncReadTransaction = 1 << 0, // 000001 + YDB_AsyncReadTransaction = 1 << 1, // 000010 + + YDB_SyncReadWriteTransaction = 1 << 2, // 000100 + YDB_AsyncReadWriteTransaction = 1 << 3, // 001000 + + YDB_AnyReadTransaction = (YDB_SyncReadTransaction | YDB_AsyncReadTransaction), // 000011 + YDB_AnyReadWriteTransaction = (YDB_SyncReadWriteTransaction | YDB_AsyncReadWriteTransaction), // 001100 + + YDB_AnySyncTransaction = (YDB_SyncReadTransaction | YDB_SyncReadWriteTransaction), // 000101 + YDB_AnyAsyncTransaction = (YDB_AsyncReadTransaction | YDB_AsyncReadWriteTransaction), // 001010 + + YDB_AnyTransaction = (YDB_AnyReadTransaction | YDB_AnyReadWriteTransaction), // 001111 + + YDB_MainThreadOnly = 1 << 4, // 010000 +}; +#endif + typedef NS_OPTIONS(NSUInteger, YapDatabaseConnectionFlushMemoryFlags) { YapDatabaseConnectionFlushMemoryFlags_None = 0, YapDatabaseConnectionFlushMemoryFlags_Caches = 1 << 0, @@ -37,11 +72,7 @@ typedef NS_OPTIONS(NSUInteger, YapDatabaseConnectionFlushMemoryFlags) { YapDatabaseConnectionFlushMemoryFlags_Statements), }; -typedef NS_ENUM(NSInteger, YapDatabasePolicy) { - YapDatabasePolicyContainment = 0, - YapDatabasePolicyShare = 1, - YapDatabasePolicyCopy = 2, -}; + @interface YapDatabaseConnection : NSObject @@ -83,7 +114,7 @@ typedef NS_ENUM(NSInteger, YapDatabasePolicy) { * @see YapDatabase defaultObjectCacheLimit * * Also see the wiki for a bit more info: - * https://github.com/yaptv/YapDatabase/wiki/Cache + * https://github.com/yapstudios/YapDatabase/wiki/Cache **/ @property (atomic, assign, readwrite) BOOL objectCacheEnabled; @property (atomic, assign, readwrite) NSUInteger objectCacheLimit; @@ -108,7 +139,7 @@ typedef NS_ENUM(NSInteger, YapDatabasePolicy) { * @see YapDatabase defaultMetadataCacheLimit * * Also see the wiki for a bit more info: - * https://github.com/yaptv/YapDatabase/wiki/Cache + * https://github.com/yapstudios/YapDatabase/wiki/Cache **/ @property (atomic, assign, readwrite) BOOL metadataCacheEnabled; @property (atomic, assign, readwrite) NSUInteger metadataCacheLimit; @@ -127,11 +158,62 @@ typedef NS_ENUM(NSInteger, YapDatabasePolicy) { * The other policies require a little more work, and little deeper understanding. * * These optimizations are discussed extensively in the wiki article "Performance Pro": - * https://github.com/yaptv/YapDatabase/wiki/Performance-Pro + * https://github.com/yapstudios/YapDatabase/wiki/Performance-Pro **/ @property (atomic, assign, readwrite) YapDatabasePolicy objectPolicy; @property (atomic, assign, readwrite) YapDatabasePolicy metadataPolicy; +/** + * When architecting your application, you will likely create a few dedicated connections for particular uses. + * This property allows you to enforce only allowed transaction types for your dedicated connections. + * + * --- Example 1: --- + * + * You have a connection designed for use on the main thread which uses a longLivedReadTransaction. + * Ideally this connection has the following constraints: + * - May only be used on the main thread + * - Can only be used for synchronous read transactions + * + * The idea is to ensure that a read transaction on the main thread never blocks. + * Thus you don't want background threads potentially tying up the connection. + * Remember: transactions go through a serial per-connection queue. + * And similarly, you don't want asynchronous operations of any kind. As that would be the equivalent of + * using the connection on a background thread. + * + * To enforce this, you can do something like this within your app: + * + * uiDatabaseConnection.permittedTransactions = YDB_SyncReadTransaction | YDB_MainThreadOnly; + * [uiDatabaseConnection beginLongLivedReadTransaction]; + * + * --- Example 2: --- + * + * You have a dedicated connection designed for read-only operations in background tasks. + * And you want to make sure that no read-write transactions are accidentally invoked on this connection, + * as that would slow your background tasks (which are designed to asynchronous, but generally very fast). + * + * To enforce this, you can do something like this within your app: + * + * roDatabaseConnection.permittedTransactions = YDB_AnyReadTransaction; + * + * --- Example 3: --- + * + * You have an internal databaseConnection within some highly asynchronous manager class. + * You've designed just about every method to be asynchronous, + * and you want to make sure you always remember to use asynchronous transactions. + * + * So, for debugging purposes, you do something like this: + * + * #if DEBUG + * databaseConnection.permittedTransactions = YBD_AnyAsyncTransaction; + * #endif + * + * + * The default value is YDB_AnyTransaction. +**/ +#if YapDatabaseEnforcePermittedTransactions +@property (atomic, assign, readwrite) YapDatabasePermittedTransactions permittedTransactions; +#endif + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark State //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -373,7 +455,7 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * This is most often used for connections that service the main thread for UI data. * * For a complete discussion, please see the wiki page: - * https://github.com/yaptv/YapDatabase/wiki/LongLivedReadTransactions + * https://github.com/yapstudios/YapDatabase/wiki/LongLivedReadTransactions **/ - (NSArray *)beginLongLivedReadTransaction; - (NSArray *)endLongLivedReadTransaction; @@ -390,7 +472,7 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * So its better to have an early warning system to help you fix the bug before it occurs. * * For a complete discussion, please see the wiki page: - * https://github.com/yaptv/YapDatabase/wiki/LongLivedReadTransactions + * https://github.com/yapstudios/YapDatabase/wiki/LongLivedReadTransactions * * In debug mode (#if DEBUG), these exceptions are turned ON by default. * In non-debug mode (#if !DEBUG), these exceptions are turned OFF by default. @@ -411,7 +493,7 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * This is most often used in conjunction with longLivedReadTransactions. * * For more information on longLivedReadTransaction, see the following wiki article: - * https://github.com/yaptv/YapDatabase/wiki/LongLivedReadTransactions + * https://github.com/yapstudios/YapDatabase/wiki/LongLivedReadTransactions **/ // Query for any change to a collection @@ -448,6 +530,61 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp inCollection:(NSString *)collection inNotifications:(NSArray *)notifications; +// Advanced query techniques + +/** + * Returns YES if [transaction removeAllObjectsInCollection:] was invoked on the collection, + * or if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications. + * + * If this was the case then YapDatabase may not have tracked every single key within the collection. + * And thus a key that was removed via clearing the collection may not show up while enumerating changedKeys. + * + * This method is designed to be used in conjunction with the enumerateChangedKeys.... methods (below). + * The hasChange... methods (above) already take this into account. +**/ +- (BOOL)didClearCollection:(NSString *)collection inNotifications:(NSArray *)notifications; + +/** + * Returns YES if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications. + * + * If this was the case then YapDatabase may not have tracked every single key within every single collection. + * And thus a key that was removed via clearing the database may not show up while enumerating changedKeys. + * + * This method is designed to be used in conjunction with the enumerateChangedKeys.... methods (below). + * The hasChange... methods (above) already take this into account. +**/ +- (BOOL)didClearAllCollectionsInNotifications:(NSArray *)notifications; + +/** + * Allows you to enumerate all the changed keys in the given collection, for the given commits. + * + * Keep in mind that if [transaction removeAllObjectsInCollection:] was invoked on the given collection + * or [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications, + * then the key may not be included in the enumeration. + * You must use didClearCollection:inNotifications: if you need to handle that case. + * + * @see didClearCollection:inNotifications: +**/ +- (void)enumerateChangedKeysInCollection:(NSString *)collection + inNotifications:(NSArray *)notifications + usingBlock:(void (^)(NSString *key, BOOL *stop))block; + +/** + * Allows you to enumerate all the changed collection/key tuples for the given commits. + * + * Keep in mind that if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications, + * then the collection/key tuple may not be included in the enumeration. + * You must use didClearAllCollectionsInNotifications: if you need to handle that case. + * + * @see didClearAllCollectionsInNotifications: +**/ +- (void)enumerateChangedCollectionKeysInNotifications:(NSArray *)notifications + usingBlock:(void (^)(YapCollectionKey *ck, BOOL *stop))block; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Extensions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -488,7 +625,7 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * Flushes all pre-compiled sqlite statements. * * YapDatabaseConnectionFlushMemoryFlags_All: - * Full flush of all caches and pre-compiled sqlite statements. + * Full flush of all caches and pre-compiled sqlite statements. **/ - (void)flushMemoryWithFlags:(YapDatabaseConnectionFlushMemoryFlags)flags; @@ -508,6 +645,42 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp #pragma mark Vacuum //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Upgrade Notice: + * + * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. + * And thus if you have an app that was using YapDatabase prior to this version, + * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. + * This means the existing database file won't be properly truncated as you delete information from the db. + * That is, the data will be removed, but the pages will be moved to the freelist, + * and the file itself will remain the same size on disk. (I.e. the file size can grow, but not shrink.) + * To correct this problem, you should run the vacuum operation at least once. + * After it is run, the "auto_vacuum=FULL" mode will be set, + * and the database file size will automatically shrink in the future (as you delete data). + * + * @returns Result from "PRAGMA auto_vacuum;" command, as a readable string: + * - NONE + * - FULL + * - INCREMENTAL + * - UNKNOWN (future proofing) + * + * If the return value is NONE, then you should run the vacuum operation at some point + * in order to properly reconfigure the database. + * + * Concerning Method Invocation: + * + * You can invoke this method as a standalone method on the connection: + * + * NSString *value = [databaseConnection pragmaAutoVacuum] + * + * Or you can invoke this method within a transaction: + * + * [databaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction){ + * NSString *value = [databaseConnection pragmaAutoVacuum]; + * }]; +**/ +- (NSString *)pragmaAutoVacuum; + /** * Performs a VACUUM on the sqlite database. * @@ -519,16 +692,7 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). + * @see pragmaAutoVacuum **/ - (void)vacuum; @@ -542,20 +706,11 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * http://sqlite.org/lang_vacuum.html * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. - * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). * * An optional completion block may be used. * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * + * @see pragmaAutoVacuum **/ - (void)asyncVacuumWithCompletionBlock:(dispatch_block_t)completionBlock; @@ -570,20 +725,11 @@ __attribute((deprecated("Use method asyncReadWriteWithBlock:completionQueue:comp * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). - * * An optional completion block may be used. * Additionally the dispatch_queue to invoke the completion block may also be specified. * If NULL, dispatch_get_main_queue() is automatically used. + * + * @see pragmaAutoVacuum **/ - (void)asyncVacuumWithCompletionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock; diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m b/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m index d55f6a4..74dd72b 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m @@ -1,3 +1,4 @@ + #import "YapDatabaseConnection.h" #import "YapDatabaseConnectionState.h" #import "YapDatabasePrivate.h" @@ -15,6 +16,10 @@ #import #import +#if TARGET_OS_IPHONE +#import +#endif + #if ! __has_feature(objc_arc) #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). #endif @@ -34,10 +39,38 @@ static NSUInteger const MIN_KEY_CACHE_LIMIT = 500; static NSString *const ExtKey_class = @"class"; +typedef BOOL (*IMP_NSThread_isMainThread)(id, SEL); +static IMP_NSThread_isMainThread ydb_NSThread_isMainThread; +static Class ydb_NSThread_Class; + +NS_INLINE BOOL YDBIsMainThread() +{ + return ydb_NSThread_isMainThread(ydb_NSThread_Class, @selector(isMainThread)); +} @implementation YapDatabaseConnection { @private + uint64_t snapshot; + + id sharedKeySetForInternalChangeset; + id sharedKeySetForExternalChangeset; + + YapDatabaseReadTransaction *longLivedReadTransaction; + BOOL throwExceptionsForImplicitlyEndingLongLivedReadTransaction; + NSMutableArray *pendingChangesets; + NSMutableArray *processedChangesets; + + NSDictionary *registeredExtensions; + BOOL registeredExtensionsChanged; + + NSDictionary *registeredMemoryTables; + BOOL registeredMemoryTablesChanged; + + NSMutableDictionary *extensions; + BOOL extensionsReady; + id sharedKeySetForExtensions; + sqlite3_stmt *beginTransactionStatement; sqlite3_stmt *commitTransactionStatement; sqlite3_stmt *rollbackTransactionStatement; @@ -96,6 +129,14 @@ static NSString *const ExtKey_class = @"class"; method_setImplementation(extMethod, extensionIMP); loaded = YES; + + // Optimized invocation of [NSThread isMainThread]. + // Benchmarks seem to indicate: + // - ~30% performance improvement on the main thread + // - ~50% performance improvement on background thread(s) + + ydb_NSThread_isMainThread = (IMP_NSThread_isMainThread)[NSThread methodForSelector:@selector(isMainThread)]; + ydb_NSThread_Class = [NSThread class]; } } @@ -131,9 +172,9 @@ static NSString *const ExtKey_class = @"class"; if (defaults.objectCacheEnabled) { objectCacheLimit = defaults.objectCacheLimit; - objectCache = [[YapCache alloc] initWithKeyClass:[YapCollectionKey class] - keyCallbacks:[YapCollectionKey keyCallbacks] - countLimit:objectCacheLimit]; + objectCache = [[YapCache alloc] initWithCountLimit:objectCacheLimit + keyCallbacks:[YapCollectionKey keyCallbacks]]; + objectCache.allowedKeyClasses = [NSSet setWithObject:[YapCollectionKey class]]; if (keyCacheLimit != UNLIMITED_CACHE_LIMIT) { @@ -146,9 +187,9 @@ static NSString *const ExtKey_class = @"class"; if (defaults.metadataCacheEnabled) { metadataCacheLimit = defaults.metadataCacheLimit; - metadataCache = [[YapCache alloc] initWithKeyClass:[YapCollectionKey class] - keyCallbacks:[YapCollectionKey keyCallbacks] - countLimit:metadataCacheLimit]; + metadataCache = [[YapCache alloc] initWithCountLimit:metadataCacheLimit + keyCallbacks:[YapCollectionKey keyCallbacks]]; + metadataCache.allowedKeyClasses = [NSSet setWithObject:[YapCollectionKey class]]; if (keyCacheLimit != UNLIMITED_CACHE_LIMIT) { @@ -162,7 +203,13 @@ static NSString *const ExtKey_class = @"class"; objectPolicy = defaults.objectPolicy; metadataPolicy = defaults.metadataPolicy; - keyCache = [[YapCache alloc] initWithKeyClass:[NSNumber class] countLimit:keyCacheLimit]; + #if YapDatabaseEnforcePermittedTransactions + self.permittedTransactions = YDB_AnyTransaction; + #endif + + keyCache = [[YapCache alloc] initWithCountLimit:keyCacheLimit]; + keyCache.allowedKeyClasses = [NSSet setWithObject:[NSNumber class]]; + keyCache.allowedObjectClasses = [NSSet setWithObject:[YapCollectionKey class]]; #if TARGET_OS_IPHONE self.autoFlushMemoryFlags = defaults.autoFlushMemoryFlags; @@ -430,6 +477,10 @@ static NSString *const ExtKey_class = @"class"; @synthesize database = database; @synthesize name = _name; +#if YapDatabaseEnforcePermittedTransactions +@synthesize permittedTransactions = _mustUseAtomicProperty_permittedTransactions; +#endif + #if TARGET_OS_IPHONE @synthesize autoFlushMemoryFlags; #endif @@ -458,9 +509,9 @@ static NSString *const ExtKey_class = @"class"; { if (objectCache == nil) { - objectCache = [[YapCache alloc] initWithKeyClass:[YapCollectionKey class] - keyCallbacks:[YapCollectionKey keyCallbacks] - countLimit:objectCacheLimit]; + objectCache = [[YapCache alloc] initWithCountLimit:objectCacheLimit + keyCallbacks:[YapCollectionKey keyCallbacks]]; + objectCache.allowedKeyClasses = [NSSet setWithObject:[YapCollectionKey class]]; } } else // Disabled @@ -543,9 +594,9 @@ static NSString *const ExtKey_class = @"class"; { if (metadataCache == nil) { - metadataCache = [[YapCache alloc] initWithKeyClass:[YapCollectionKey class] - keyCallbacks:[YapCollectionKey keyCallbacks] - countLimit:metadataCacheLimit]; + metadataCache = [[YapCache alloc] initWithCountLimit:metadataCacheLimit + keyCallbacks:[YapCollectionKey keyCallbacks]]; + metadataCache.allowedKeyClasses = [NSSet setWithObject:[YapCollectionKey class]]; } } else // Disabled @@ -1399,6 +1450,18 @@ static NSString *const ExtKey_class = @"class"; **/ - (void)readWithBlock:(void (^)(YapDatabaseReadTransaction *))block { +#if YapDatabaseEnforcePermittedTransactions + YapDatabasePermittedTransactions flags = self.permittedTransactions; + if ((flags & YDB_MainThreadOnly) && !YDBIsMainThread()) + { + @throw [self nonMainThreadException]; + } + if (!(flags & YDB_SyncReadTransaction)) + { + @throw [self unpermittedTransactionException:YDB_SyncReadTransaction]; + } +#endif + dispatch_sync(connectionQueue, ^{ @autoreleasepool { if (longLivedReadTransaction) @@ -1426,6 +1489,18 @@ static NSString *const ExtKey_class = @"class"; **/ - (void)readWriteWithBlock:(void (^)(YapDatabaseReadWriteTransaction *transaction))block { +#if YapDatabaseEnforcePermittedTransactions + YapDatabasePermittedTransactions flags = self.permittedTransactions; + if ((flags & YDB_MainThreadOnly) && !YDBIsMainThread()) + { + @throw [self nonMainThreadException]; + } + if (!(flags & YDB_SyncReadWriteTransaction)) + { + @throw [self unpermittedTransactionException:YDB_SyncReadWriteTransaction]; + } +#endif + // Order matters. // First go through the serial connection queue. // Then go through serial write queue for the database. @@ -1510,6 +1585,18 @@ static NSString *const ExtKey_class = @"class"; completionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock { +#if YapDatabaseEnforcePermittedTransactions + YapDatabasePermittedTransactions flags = self.permittedTransactions; + if ((flags & YDB_MainThreadOnly) && !YDBIsMainThread()) + { + @throw [self nonMainThreadException]; + } + if (!(flags & YDB_AsyncReadTransaction)) + { + @throw [self unpermittedTransactionException:YDB_AsyncReadTransaction]; + } +#endif + if (completionQueue == NULL && completionBlock != NULL) completionQueue = dispatch_get_main_queue(); @@ -1613,6 +1700,18 @@ static NSString *const ExtKey_class = @"class"; completionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock { +#if YapDatabaseEnforcePermittedTransactions + YapDatabasePermittedTransactions flags = self.permittedTransactions; + if ((flags & YDB_MainThreadOnly) && !YDBIsMainThread()) + { + @throw [self nonMainThreadException]; + } + if (!(flags & YDB_AsyncReadWriteTransaction)) + { + @throw [self unpermittedTransactionException:YDB_AsyncReadWriteTransaction]; + } +#endif + if (completionQueue == NULL && completionBlock != NULL) completionQueue = dispatch_get_main_queue(); @@ -2188,7 +2287,9 @@ static NSString *const ExtKey_class = @"class"; // - At the end of a readwrite transaction that has made modifications to the database // - Only if the modifications weren't dedicated to registering/unregistring an extension - if (database->previouslyRegisteredExtensionNames && changeset && !registeredExtensionsChanged) + BOOL clearPreviouslyRegisteredExtensionNames = NO; + + if (changeset && !registeredExtensionsChanged && database->previouslyRegisteredExtensionNames) { for (NSString *prevExtensionName in database->previouslyRegisteredExtensionNames) { @@ -2198,7 +2299,7 @@ static NSString *const ExtKey_class = @"class"; } } - database->previouslyRegisteredExtensionNames = nil; + clearPreviouslyRegisteredExtensionNames = YES; } // Post-Write-Transaction: Step 4 of 11 @@ -2263,7 +2364,7 @@ static NSString *const ExtKey_class = @"class"; // // This two step process means we have an edge case, // where another connection could come around and begin its yap level transaction - // before this connections yap level commit, but after this connections sqlite level commit. + // before this connection's yap level commit, but after this connection's sqlite level commit. // // By registering the pending changeset in advance, // we provide a near seamless workaround for the edge case. @@ -2272,6 +2373,12 @@ static NSString *const ExtKey_class = @"class"; { [database notePendingChanges:changeset fromConnection:self]; } + + if (clearPreviouslyRegisteredExtensionNames) + { + // It's only safe to clear this ivar within the snapshot queue + database->previouslyRegisteredExtensionNames = nil; + } } }}); @@ -3742,6 +3849,187 @@ static NSString *const ExtKey_class = @"class"; metadataChanges:YES]; } +// Advanced query techniques + +/** + * Returns YES if [transaction removeAllObjectsInCollection:] was invoked on the collection, + * or if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications. + * + * If this was the case then YapDatabase may not have tracked every single key within the collection. + * And thus a key that was removed via clearing the collection may not show up while enumerating changedKeys. + * + * This method is designed to be used in conjunction with the enumerateChangedKeys.... methods (below). + * The hasChange... methods (above) already take this into account. +**/ +- (BOOL)didClearCollection:(NSString *)collection inNotifications:(NSArray *)notifications +{ + if (collection == nil) + collection = @""; + + for (NSNotification *notification in notifications) + { + if (![notification isKindOfClass:[NSNotification class]]) + { + YDBLogWarn(@"%@ - notifications parameter contains non-NSNotification object", THIS_METHOD); + continue; + } + + NSDictionary *changeset = notification.userInfo; + + YapSet *changeset_removedCollections = [changeset objectForKey:YapDatabaseRemovedCollectionsKey]; + if ([changeset_removedCollections containsObject:collection]) + return YES; + } + + return NO; +} + +/** + * Returns YES if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications. + * + * If this was the case then YapDatabase may not have tracked every single key within every single collection. + * And thus a key that was removed via clearing the database may not show up while enumerating changedKeys. + * + * This method is designed to be used in conjunction with the enumerateChangedKeys.... methods (below). + * The hasChange... methods (above) already take this into account. +**/ +- (BOOL)didClearAllCollectionsInNotifications:(NSArray *)notifications +{ + for (NSNotification *notification in notifications) + { + if (![notification isKindOfClass:[NSNotification class]]) + { + YDBLogWarn(@"%@ - notifications parameter contains non-NSNotification object", THIS_METHOD); + continue; + } + + NSDictionary *changeset = notification.userInfo; + + BOOL changeset_allKeysRemoved = [[changeset objectForKey:YapDatabaseAllKeysRemovedKey] boolValue]; + if (changeset_allKeysRemoved) + return YES; + } + + return NO; +} + +/** + * Allows you to enumerate all the changed keys in the given collection, for the given commits. + * + * Keep in mind that if [transaction removeAllObjectsInCollection:] was invoked on the given collection + * or [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications, + * then the key may not be included in the enumeration. + * You must use didClearCollection:inNotifications: if you need to handle that case. + * + * @see didClearCollection:inNotifications: +**/ +- (void)enumerateChangedKeysInCollection:(NSString *)collection + inNotifications:(NSArray *)notifications + usingBlock:(void (^)(NSString *key, BOOL *stop))block +{ + if (block == NULL) return; + if (collection == nil) + collection = @""; + + BOOL stop = NO; + NSMutableSet *keys = [NSMutableSet set]; + + for (NSNotification *notification in notifications) + { + if (![notification isKindOfClass:[NSNotification class]]) + { + YDBLogWarn(@"%@ - notifications parameter contains non-NSNotification object", THIS_METHOD); + continue; + } + + NSDictionary *changeset = notification.userInfo; + + YapSet *changeset_objectChanges = [changeset objectForKey:YapDatabaseObjectChangesKey]; + for (YapCollectionKey *ck in changeset_objectChanges) + { + if ([ck.collection isEqualToString:collection]) + { + if (![keys containsObject:ck.key]) + { + block(ck.key, &stop); + if (stop) return; + + [keys addObject:ck.key]; + } + } + } + + YapSet *changeset_metadataChanges = [changeset objectForKey:YapDatabaseMetadataChangesKey]; + for (YapCollectionKey *ck in changeset_metadataChanges) + { + if ([ck.collection isEqualToString:collection]) + { + if (![keys containsObject:ck.key]) + { + block(ck.key, &stop); + if (stop) return; + + [keys addObject:ck.key]; + } + } + } + } +} + +/** + * Allows you to enumerate all the changed collection/key tuples for the given commits. + * + * Keep in mind that if [transaction removeAllObjectsInAllCollections] was invoked + * during any of the commits represented by the given notifications, + * then the collection/key tuple may not be included in the enumeration. + * You must use didClearAllCollectionsInNotifications: if you need to handle that case. + * + * @see didClearAllCollectionsInNotifications: +**/ +- (void)enumerateChangedCollectionKeysInNotifications:(NSArray *)notifications + usingBlock:(void (^)(YapCollectionKey *ck, BOOL *stop))block +{ + if (block == NULL) return; + + BOOL stop = NO; + NSMutableSet *collectionKeys = [NSMutableSet set]; + + for (NSNotification *notification in notifications) + { + if (![notification isKindOfClass:[NSNotification class]]) + { + YDBLogWarn(@"%@ - notifications parameter contains non-NSNotification object", THIS_METHOD); + continue; + } + + NSDictionary *changeset = notification.userInfo; + + YapSet *changeset_objectChanges = [changeset objectForKey:YapDatabaseObjectChangesKey]; + for (YapCollectionKey *ck in changeset_objectChanges) + { + if (![collectionKeys containsObject:ck]) + { + block(ck, &stop); + if (stop) return; + + [collectionKeys addObject:ck]; + } + } + + YapSet *changeset_metadataChanges = [changeset objectForKey:YapDatabaseMetadataChangesKey]; + for (YapCollectionKey *ck in changeset_metadataChanges) + { + block(ck, &stop); + if (stop) return; + + [collectionKeys addObject:ck]; + } + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Extensions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4226,6 +4514,57 @@ static NSString *const ExtKey_class = @"class"; #pragma mark Vacuum //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Upgrade Notice: + * + * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. + * And thus if you have an app that was using YapDatabase prior to this version, + * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. + * This means the existing database file won't be properly truncated as you delete information from the db. + * That is, the data will be removed, but the pages will be moved to the freelist, + * and the file itself will remain the same size on disk. (I.e. the file size can grow, but not shrink.) + * To correct this problem, you should run the vacuum operation is at least once. + * After it is run, the "auto_vacuum=FULL" mode will be set, + * and the database file size will automatically shrink in the future (as you delete data). + * + * @returns Result from "PRAGMA auto_vacuum;" command, as a readable string: + * - NONE + * - FULL + * - INCREMENTAL + * - UNKNOWN (future proofing) + * + * If the return value is NONE, then you should run the vacuum operation at some point + * in order to properly reconfigure the database. + * + * Concerning Method Invocation: + * + * You can invoke this method as a standalone method on the connection: + * + * NSString *value = [databaseConnection pragmaAutoVacuum] + * + * Or you can invoke this method within a transaction: + * + * [databaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction){ + * NSString *value = [databaseConnection pragmaAutoVacuum]; + * }]; +**/ +- (NSString *)pragmaAutoVacuum +{ + __block int value = -1; + + dispatch_block_t block = ^{ @autoreleasepool { + + value = [YapDatabase pragma:@"auto_vacuum" using:db]; + }}; + + if (dispatch_get_specific(IsOnConnectionQueueKey)) + block(); + else + dispatch_sync(connectionQueue, block); + + return [YapDatabase pragmaValueForAutoVacuum:value]; +} + /** * Performs a VACUUM on the sqlite database. * @@ -4237,16 +4576,7 @@ static NSString *const ExtKey_class = @"class"; * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). + * @see pragmaAutoVacuum **/ - (void)vacuum { @@ -4308,19 +4638,10 @@ static NSString *const ExtKey_class = @"class"; * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). - * * An optional completion block may be used. * The completionBlock will be invoked on the main thread (dispatch_get_main_queue()). + * + * @see pragmaAutoVacuum **/ - (void)asyncVacuumWithCompletionBlock:(dispatch_block_t)completionBlock { @@ -4338,20 +4659,11 @@ static NSString *const ExtKey_class = @"class"; * * Remember that YapDatabase operates in WAL mode, with "auto_vacuum=FULL" set. * - * Upgrade Notice: - * The "auto_vacuum=FULL" was not properly set until YapDatabase v2.5. - * And thus if you have an app that was using YapDatabase prior to this version, - * then the existing database file will continue to operate in "auto_vacuum=NONE" mode. - * This means the existing database file won't be properly truncated as you delete information from the db. - * That is, the data will be removed, but the pages will be moved to the freelist, - * and the file itself will remain the same size on disk. - * To correct this problem, you should run the vacuum operation is at least once. - * After it is run, the "auto_vacuum=FULL" mode will be set, - * and the database file size will automatically shrink in the future (as you delete data). - * * An optional completion block may be used. * Additionally the dispatch_queue to invoke the completion block may also be specified. * If NULL, dispatch_get_main_queue() is automatically used. + * + * @see pragmaAutoVacuum **/ - (void)asyncVacuumWithCompletionQueue:(dispatch_queue_t)completionQueue completionBlock:(dispatch_block_t)completionBlock @@ -4547,6 +4859,67 @@ NS_INLINE void __postWriteQueue(YapDatabaseConnection *connection) #pragma mark Exceptions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +- (NSException *)nonMainThreadException +{ + NSString *connectionName = self.name; + NSString *nameInfo = ([connectionName length] > 0) ? [NSString stringWithFormat:@" <%@>", connectionName] : @""; + + NSString *reason = [NSString stringWithFormat: + @"YapDatabaseConnection[%p]%@ - unpermitted attempt to execute transaction on nom-main thread", + self, nameInfo]; + + NSDictionary *userInfo = @{ NSLocalizedRecoverySuggestionErrorKey: + @"This connection was configured (via the permittedTransactions property) to only allow transactions" + @" to be executed from the main-thread. Presumably this connection is dedicated to UI tasks, and thus" + @" its use on background threads is being discouraged in order to guarantee the connection never blocks." + @" Perhaps you're using the wrong dedicated connection." + @" Or you need to create a temporary connection via [database newConnection]."}; + + return [NSException exceptionWithName:@"YapDatabaseException" reason:reason userInfo:userInfo]; +} + +#if YapDatabaseEnforcePermittedTransactions +- (NSException *)unpermittedTransactionException:(NSUInteger)transactionFlag +{ + NSUInteger flags = self.permittedTransactions; + + NSString *connectionName = self.name; + NSString *nameInfo = ([connectionName length] > 0) ? [NSString stringWithFormat:@" <%@>", connectionName] : @""; + + NSString *unpermittedTransaction = @"unknownTransaction"; + if (transactionFlag == YDB_SyncReadTransaction) + unpermittedTransaction = @"(sync)readTransaction"; + if (transactionFlag == YDB_AsyncReadTransaction) + unpermittedTransaction = @"asyncReadTransaction"; + if (transactionFlag == YDB_SyncReadWriteTransaction) + unpermittedTransaction = @"(sync)readWriteTransaction"; + if (transactionFlag == YDB_AsyncReadWriteTransaction) + unpermittedTransaction = @"asyncReadWriteTransaction"; + + NSString *reason = [NSString stringWithFormat: + @"YapDatabaseConnection[%p]%@ - unpermitted attempt to execute %@", self, nameInfo, unpermittedTransaction]; + + NSMutableArray *permittedComponents = [NSMutableArray arrayWithCapacity:4]; + if (flags & YDB_SyncReadTransaction) + [permittedComponents addObject:@"(sync)readTransaction"]; + if (flags & YDB_AsyncReadTransaction) + [permittedComponents addObject:@"asyncReadTransaction"]; + if (flags & YDB_SyncReadWriteTransaction) + [permittedComponents addObject:@"(sync)readWriteTransaction"]; + if (flags & YDB_AsyncReadWriteTransaction) + [permittedComponents addObject:@"asyncReadWriteTransaction"]; + + NSString *suggestion = [NSString stringWithFormat: + @"This connection was configured (via the permittedTransactions property) to only allow" + @" certain types of transactions. The permittedTransactions are: %@", + [permittedComponents componentsJoinedByString:@", "]]; + + NSDictionary *userInfo = @{ NSLocalizedRecoverySuggestionErrorKey: suggestion }; + + return [NSException exceptionWithName:@"YapDatabaseException" reason:reason userInfo:userInfo]; +} +#endif + - (NSException *)implicitlyEndingLongLivedReadTransactionException { NSString *reason = [NSString stringWithFormat: diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.h b/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.h index 98a0376..6f061ef 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.h +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.h @@ -4,10 +4,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * This class provides extra configuration options that may be passed to YapDatabase. * The configuration options provided by this class are advanced (beyond the basic setup options). @@ -26,7 +26,7 @@ typedef NS_ENUM(NSInteger, YapDatabasePragmaSynchronous) { }; #ifdef SQLITE_HAS_CODEC -typedef NSString* (^YapDatabaseOptionsPassphraseBlock)(void); +typedef NSData* (^YapDatabaseCipherKeyBlock)(void); #endif @interface YapDatabaseOptions : NSObject @@ -78,15 +78,18 @@ typedef NSString* (^YapDatabaseOptionsPassphraseBlock)(void); #ifdef SQLITE_HAS_CODEC /** - * Set a block here that returns the passphrase for the SQLCipher - * database. This way you can fetch the passphrase from the keychain - * (or elsewhere) only when you need it, instead of persisting - * it in memory. + * Set a block here that returns the key for the SQLCipher database. + * + * This is the key that will be passed to SQLCipher via the sqlite3_key method: + * https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlite3_key + * + * This block allows you can fetch the passphrase from the keychain (or elsewhere) + * only when you need it, instead of persisting it in memory. * * You must use the 'YapDatabase/SQLCipher' subspec * in your Podfile for this option to take effect. **/ -@property (nonatomic, copy) YapDatabaseOptionsPassphraseBlock passphraseBlock; +@property (nonatomic, copy) YapDatabaseCipherKeyBlock cipherKeyBlock; #endif @end diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.m b/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.m index d8dbbdb..df08230 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.m +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseOptions.m @@ -4,10 +4,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * This class provides extra configuration options that may be passed to YapDatabase. * The configuration options provided by this class are advanced (beyond the basic setup options). @@ -17,6 +17,9 @@ @synthesize corruptAction = corruptAction; @synthesize pragmaSynchronous = pragmaSynchronous; @synthesize pragmaJournalSizeLimit = pragmaJournalSizeLimit; +#ifdef SQLITE_HAS_CODEC +@synthesize cipherKeyBlock = cipherKeyBlock; +#endif - (id)init { @@ -36,7 +39,7 @@ copy->pragmaSynchronous = pragmaSynchronous; copy->pragmaJournalSizeLimit = pragmaJournalSizeLimit; #ifdef SQLITE_HAS_CODEC - copy.passphraseBlock = _passphraseBlock; + copy.cipherKeyBlock = cipherKeyBlock; #endif return copy; } diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h b/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h index e4771dd..54e811e 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h @@ -6,10 +6,10 @@ * Welcome to YapDatabase! * * The project page has a wealth of documentation if you have any questions. - * https://github.com/yaptv/YapDatabase + * https://github.com/yapstudios/YapDatabase * * If you're new to the project you may want to visit the wiki. - * https://github.com/yaptv/YapDatabase/wiki + * https://github.com/yapstudios/YapDatabase/wiki * * Transactions represent atomic access to a database. * There are two types of transactions: @@ -62,6 +62,15 @@ **/ @property (nonatomic, unsafe_unretained, readonly) YapDatabaseConnection *connection; +/** + * The userInfo property allows arbitrary info to be associated with the transaction. + * This propery is not used by YapDatabaseTransaction in any way. + * + * Keep in mind that transactions are short lived objects. + * Each transaction is a new/different transaction object. +**/ +@property (nonatomic, strong, readwrite) id userInfo; + #pragma mark Count /** @@ -93,24 +102,6 @@ **/ - (NSArray *)allKeysInCollection:(NSString *)collection; -#pragma mark Primitive - -/** - * Primitive access. - * - * These are available for in-case you store irregular data - * that shouldn't go through configured serializer/deserializer. - * - * @see objectForKey:inCollection: - * @see metadataForKey:inCollection: -**/ -- (NSData *)primitiveDataForKey:(NSString *)key inCollection:(NSString *)collection; -- (NSData *)primitiveMetadataForKey:(NSString *)key inCollection:(NSString *)collection; -- (BOOL)getPrimitiveData:(NSData **)dataPtr - primitiveMetadata:(NSData **)primitiveMetadataPtr - forKey:(NSString *)key - inCollection:(NSString *)collection; - #pragma mark Object & Metadata /** @@ -137,6 +128,44 @@ **/ - (id)metadataForKey:(NSString *)key inCollection:(NSString *)collection; +#pragma mark Primitive + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serializedObject from the database. + * + * This method is slower than objectForKey:inCollection:, since that method makes use of the objectCache. + * In contrast, this method always fetches the raw data from disk. + * + * @see objectForKey:inCollection: +**/ +- (NSData *)serializedObjectForKey:(NSString *)key inCollection:(NSString *)collection; + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serializedMetadata from the database. + * + * This method is slower than metadataForKey:inCollection:, since that method makes use of the metadataCache. + * In contrast, this method always fetches the raw data from disk. + * + * @see metadataForKey:inCollection: +**/ +- (NSData *)serializedMetadataForKey:(NSString *)key inCollection:(NSString *)collection; + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serialized forms from the database. + * + * This method is slower than getObject:metadata:forKey:inCollection:, since that method makes use of the caches. + * In contrast, this method always fetches the raw data from disk. + * + * @see getObject:metadata:forKey:inCollection: +**/ +- (BOOL)getSerializedObject:(NSData **)serializedObjectPtr + serializedMetadata:(NSData **)serializedMetadataPtr + forKey:(NSString *)key + inCollection:(NSString *)collection; + #pragma mark Enumerate /** @@ -438,145 +467,232 @@ * as opposed to broadcasting your own separate notification. * * For more information, and code samples, please see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/YapDatabaseModifiedNotification + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseModifiedNotification **/ @property (nonatomic, strong, readwrite) id yapDatabaseModifiedNotificationCustomObject; -#pragma mark Primitive - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of setObject:forKey:inCollection:. - * For more information see the documentation for setObject:forKey:inCollection:. - * - * @see setObject:forKey:inCollection: - * @see primitiveDataForKey:inCollection: -**/ -- (void)setPrimitiveData:(NSData *)primitiveData forKey:(NSString *)key inCollection:(NSString *)collection; - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of setObject:forKey:inCollection:withMetadata:. - * For more information see the documentation for setObject:forKey:inCollection:withMetadata:. - * - * @see setObject:forKey:inCollection:withMetadata: - * @see primitiveDataForKey:inCollection: - * @see primitiveMetadataForKey:inCollection: -**/ -- (void)setPrimitiveData:(NSData *)primitiveData - forKey:(NSString *)key - inCollection:(NSString *)collection - withPrimitiveMetadata:(NSData *)primitiveMetadata; - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of replaceObject:forKey:inCollection:. - * For more information see the documentation for replaceObject:forKey:inCollection:. - * - * @see replaceObject:forKey:inCollection: - * @see primitiveDataForKey:inCollection: -**/ -- (void)replacePrimitiveData:(NSData *)primitiveData forKey:(NSString *)key inCollection:(NSString *)collection; - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveMetadataForKey:inCollection:). If you attempt to access it via the object accessor - * (metadataForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of replaceMetadata:forKey:inCollection:. - * For more information see the documentation for replaceMetadata:forKey:inCollection:. - * - * @see replaceMetadata:forKey:inCollection: - * @see primitiveMetadataForKey:inCollection: -**/ -- (void)replacePrimitiveMetadata:(NSData *)primitiveMetadata forKey:(NSString *)key inCollection:(NSString *)collection; - #pragma mark Object & Metadata /** * Sets the object for the given key/collection. * The object is automatically serialized using the database's configured objectSerializer. - * - * If you pass nil for the object, then this method will remove the row from the database (if it exists). * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). * This method implicitly sets the associated metadata to nil. + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). **/ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection; /** * Sets the object & metadata for the given key/collection. - * - * The object is automatically serialized using the database's configured objectSerializer. - * The metadata is automatically serialized using the database's configured metadataSerializer. - * - * The metadata is optional. You can pass nil for the metadata is unneeded. - * If non-nil then the metadata is also written to the database (metadata is also persistent). * * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * The metadata is optional. You can pass nil for the metadata is unneeded. + * If non-nil then the metadata is also written to the database (metadata is also persistent). **/ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection withMetadata:(id)metadata; /** - * If a row with the given key/collection exists, then replaces the object for that row with the new value. - * It only replaces the object. The metadata for the row doesn't change. + * Sets the object & metadata for the given key/collection. * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw serialized NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * The metadata is optional. You can pass nil for the metadata is unneeded. + * If non-nil then the metadata is also written to the database (metadata is also persistent). + * + * @param preSerializedObject + * This value is optional. + * If non-nil then the object serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedObject is equal to what we would get if we ran the object through + * the database's configured objectSerializer. + * + * @param preSerializedMetadata + * This value is optional. + * If non-nil then the metadata serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedMetadata is equal to what we would get if we ran the metadata through + * the database's configured metadataSerializer. + * + * The preSerializedObject is only used if object is non-nil. + * The preSerializedMetadata is only used if metadata is non-nil. +**/ +- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection + withMetadata:(id)metadata + serializedObject:(NSData *)preSerializedObject + serializedMetadata:(NSData *)preSerializedMetadata; + +/** + * If a row with the given key/collection exists, then replaces the object for that row with the new value. + * + * It only replaces the object. The metadata for the row doesn't change. * If there is no row in the database for the given key/collection then this method does nothing. * - * If you pass nil for the object, then this method will remove + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). **/ - (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection; /** - * If a row with the given key/collection exists, then replaces the metadata for that row with the new value. - * It only replaces the metadata. The object for the row doesn't change. + * If a row with the given key/collection exists, then replaces the object for that row with the new value. * + * It only replaces the object. The metadata for the row doesn't change. + * If there is no row in the database for the given key/collection then this method does nothing. + * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw serialized NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param preSerializedObject + * This value is optional. + * If non-nil then the object serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedObject is equal to what we would get if we ran the object through + * the database's configured objectSerializer. +**/ +- (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection + withSerializedObject:(NSData *)preSerializedObject; + +/** + * If a row with the given key/collection exists, then replaces the metadata for that row with the new value. + * + * It only replaces the metadata. The object for the row doesn't change. * If there is no row in the database for the given key/collection then this method does nothing. * * If you pass nil for the metadata, any metadata previously associated with the key/collection is removed. + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). **/ - (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection; +/** + * If a row with the given key/collection exists, then replaces the metadata for that row with the new value. + * + * It only replaces the metadata. The object for the row doesn't change. + * If there is no row in the database for the given key/collection then this method does nothing. + * + * If you pass nil for the metadata, any metadata previously associated with the key/collection is removed. + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw serialized NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param preSerializedMetadata + * This value is optional. + * If non-nil then the metadata serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedMetadata is equal to what we would get if we ran the metadata through + * the database's configured metadataSerializer. +**/ +- (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection + withSerializedMetadata:(NSData *)preSerializedMetadata; + #pragma mark Touch /** @@ -618,8 +734,9 @@ /** * Deletes the database row with the given key/collection. + * * This method is automatically called if you invoke - * setObject:forKey:collection: or setPrimitiveData:forKey:collection: and pass nil object/data. + * setObject:forKey:collection: and pass a nil object. **/ - (void)removeObjectForKey:(NSString *)key inCollection:(NSString *)collection; diff --git a/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m b/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m index 5363f2e..f1564fb 100644 --- a/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +++ b/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m @@ -55,6 +55,7 @@ } @synthesize connection = connection; +@synthesize userInfo = _external_userInfo; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Transaction States @@ -82,7 +83,7 @@ // // Allow extensions to flush changes to the main database table. // This is different from flushing changes to their own private tables. - // We're referring here to the main collection/key/value table that's public. + // We're referring here to the main collection/key/value table (database2) that's public. __block BOOL restart; __block BOOL prevExtModifiesMainDatabaseTable; @@ -123,27 +124,19 @@ // Step 2: // - // Allow extensions to perform any "cleanup" code needed before the changesets are requested, - // and before the commit is executed. + // Allow extensions to flush changes to their own tables, + // and perform any needed "cleanup" code needed before the changeset is requested. [extensions enumerateKeysAndObjectsUsingBlock:^(id extNameObj, id extTransactionObj, BOOL *stop) { - [(YapDatabaseExtensionTransaction *)extTransactionObj prepareChangeset]; + [(YapDatabaseExtensionTransaction *)extTransactionObj flushPendingChangesToExtensionTables]; }]; + + [yapMemoryTableTransaction commit]; } - (void)commitTransaction { - if (isReadWriteTransaction) - { - [extensions enumerateKeysAndObjectsUsingBlock:^(id extNameObj, id extTransactionObj, BOOL *stop) { - - [(YapDatabaseExtensionTransaction *)extTransactionObj commitTransaction]; - }]; - - [yapMemoryTableTransaction commit]; - } - sqlite3_stmt *statement = [connection commitTransactionStatement]; if (statement) { @@ -157,17 +150,18 @@ sqlite3_reset(statement); } + + if (isReadWriteTransaction) + { + [extensions enumerateKeysAndObjectsUsingBlock:^(id extNameObj, id extTransactionObj, BOOL *stop) { + + [(YapDatabaseExtensionTransaction *)extTransactionObj didCommitTransaction]; + }]; + } } - (void)rollbackTransaction { - [extensions enumerateKeysAndObjectsUsingBlock:^(id extNameObj, id extTransactionObj, BOOL *stop) { - - [(YapDatabaseExtensionTransaction *)extTransactionObj rollbackTransaction]; - }]; - - [yapMemoryTableTransaction rollback]; - sqlite3_stmt *statement = [connection rollbackTransactionStatement]; if (statement) { @@ -181,6 +175,13 @@ sqlite3_reset(statement); } + + [extensions enumerateKeysAndObjectsUsingBlock:^(id extNameObj, id extTransactionObj, BOOL *stop) { + + [(YapDatabaseExtensionTransaction *)extTransactionObj didRollbackTransaction]; + }]; + + [yapMemoryTableTransaction rollback]; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -707,169 +708,6 @@ return YES; } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Primitive -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (NSData *)primitiveDataForKey:(NSString *)key inCollection:(NSString *)collection -{ - if (key == nil) return nil; - if (collection == nil) collection = @""; - - sqlite3_stmt *statement = [connection getDataForKeyStatement]; - if (statement == NULL) return nil; - - NSData *result = nil; - - // SELECT "data" FROM "database2" WHERE "collection" = ? AND "key" = ?; - - YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); - sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); - - YapDatabaseString _key; MakeYapDatabaseString(&_key, key); - sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - - int status = sqlite3_step(statement); - if (status == SQLITE_ROW) - { - if (connection->needsMarkSqlLevelSharedReadLock) - [connection markSqlLevelSharedReadLockAcquired]; - - const void *blob = sqlite3_column_blob(statement, 0); - int blobSize = sqlite3_column_bytes(statement, 0); - - result = [[NSData alloc] initWithBytes:blob length:blobSize]; - } - else if (status == SQLITE_ERROR) - { - YDBLogError(@"Error executing 'getDataForKeyStatement': %d %s, key(%@)", - status, sqlite3_errmsg(connection->db), key); - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - - return result; -} - -- (NSData *)primitiveMetadataForKey:(NSString *)key inCollection:(NSString *)collection -{ - if (key == nil) return nil; - if (collection == nil) collection = @""; - - sqlite3_stmt *statement = [connection getMetadataForKeyStatement]; - if (statement == NULL) return nil; - - // SELECT "metadata" FROM "database2" WHERE "collection" = ? AND "key" = ? ; - - YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); - sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); - - YapDatabaseString _key; MakeYapDatabaseString(&_key, key); - sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - - NSData *result = nil; - - int status = sqlite3_step(statement); - if (status == SQLITE_ROW) - { - if (connection->needsMarkSqlLevelSharedReadLock) - [connection markSqlLevelSharedReadLockAcquired]; - - const void *blob = sqlite3_column_blob(statement, 0); - int blobSize = sqlite3_column_bytes(statement, 0); - - result = [[NSData alloc] initWithBytes:blob length:blobSize]; - } - else if (status == SQLITE_ERROR) - { - YDBLogError(@"Error executing 'getDataForKeyStatement': %d %s, key(%@)", - status, sqlite3_errmsg(connection->db), key); - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - - return result; -} - -- (BOOL)getPrimitiveData:(NSData **)dataPtr - primitiveMetadata:(NSData **)metadataPtr - forKey:(NSString *)key - inCollection:(NSString *)collection -{ - if (key == nil) { - if (dataPtr) *dataPtr = nil; - if (metadataPtr) *metadataPtr = nil; - return NO; - } - if (collection == nil) collection = @""; - - sqlite3_stmt *statement = [connection getAllForKeyStatement]; - if (statement == NULL) { - if (dataPtr) *dataPtr = nil; - if (metadataPtr) *metadataPtr = nil; - return NO; - } - - NSData *data = nil; - NSData *metadata = nil; - - BOOL found = NO; - - // SELECT "data", "metadata" FROM "database2" WHERE "collection" = ? AND "key" = ? ; - - YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); - sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); - - YapDatabaseString _key; MakeYapDatabaseString(&_key, key); - sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - - int status = sqlite3_step(statement); - if (status == SQLITE_ROW) - { - if (connection->needsMarkSqlLevelSharedReadLock) - [connection markSqlLevelSharedReadLockAcquired]; - - const void *oBlob = sqlite3_column_blob(statement, 0); - int oBlobSize = sqlite3_column_bytes(statement, 0); - - const void *mBlob = sqlite3_column_blob(statement, 1); - int mBlobSize = sqlite3_column_bytes(statement, 1); - - if (dataPtr) - { - data = [NSData dataWithBytes:(void *)oBlob length:oBlobSize]; - } - - if (metadataPtr) - { - metadata = [NSData dataWithBytes:(void *)mBlob length:mBlobSize]; - } - - found = YES; - } - else if (status == SQLITE_ERROR) - { - YDBLogError(@"Error executing 'getAllForKeyStatement': %d %s", - status, sqlite3_errmsg(connection->db)); - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - - if (dataPtr) *dataPtr = data; - if (metadataPtr) *metadataPtr = metadata; - - return found; -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Object & Metadata //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1141,6 +979,194 @@ return metadata; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Primitive +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serializedObject from the database. + * + * This method is slower than objectForKey:inCollection:, since that method makes use of the objectCache. + * In contrast, this method always fetches the raw data from disk. + * + * @see objectForKey:inCollection: +**/ +- (NSData *)serializedObjectForKey:(NSString *)key inCollection:(NSString *)collection; +{ + if (key == nil) return nil; + if (collection == nil) collection = @""; + + sqlite3_stmt *statement = [connection getDataForKeyStatement]; + if (statement == NULL) return nil; + + NSData *result = nil; + + // SELECT "data" FROM "database2" WHERE "collection" = ? AND "key" = ?; + + YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); + sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); + + YapDatabaseString _key; MakeYapDatabaseString(&_key, key); + sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + if (connection->needsMarkSqlLevelSharedReadLock) + [connection markSqlLevelSharedReadLockAcquired]; + + const void *blob = sqlite3_column_blob(statement, 0); + int blobSize = sqlite3_column_bytes(statement, 0); + + result = [[NSData alloc] initWithBytes:blob length:blobSize]; + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'getDataForKeyStatement': %d %s, key(%@)", + status, sqlite3_errmsg(connection->db), key); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_collection); + FreeYapDatabaseString(&_key); + + return result; +} + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serializedMetadata from the database. + * + * This method is slower than metadataForKey:inCollection:, since that method makes use of the metadataCache. + * In contrast, this method always fetches the raw data from disk. + * + * @see metadataForKey:inCollection: +**/ +- (NSData *)serializedMetadataForKey:(NSString *)key inCollection:(NSString *)collection +{ + if (key == nil) return nil; + if (collection == nil) collection = @""; + + sqlite3_stmt *statement = [connection getMetadataForKeyStatement]; + if (statement == NULL) return nil; + + // SELECT "metadata" FROM "database2" WHERE "collection" = ? AND "key" = ? ; + + YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); + sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); + + YapDatabaseString _key; MakeYapDatabaseString(&_key, key); + sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); + + NSData *result = nil; + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + if (connection->needsMarkSqlLevelSharedReadLock) + [connection markSqlLevelSharedReadLockAcquired]; + + const void *blob = sqlite3_column_blob(statement, 0); + int blobSize = sqlite3_column_bytes(statement, 0); + + result = [[NSData alloc] initWithBytes:blob length:blobSize]; + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'getDataForKeyStatement': %d %s, key(%@)", + status, sqlite3_errmsg(connection->db), key); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_collection); + FreeYapDatabaseString(&_key); + + return result; +} + +/** + * Primitive access. + * This method is available in-case you have a need to fetch the raw serialized forms from the database. + * + * This method is slower than getObject:metadata:forKey:inCollection:, since that method makes use of the caches. + * In contrast, this method always fetches the raw data from disk. + * + * @see getObject:metadata:forKey:inCollection: +**/ +- (BOOL)getSerializedObject:(NSData **)serializedObjectPtr + serializedMetadata:(NSData **)serializedMetadataPtr + forKey:(NSString *)key + inCollection:(NSString *)collection +{ + if (key == nil) { + if (serializedObjectPtr) *serializedObjectPtr = nil; + if (serializedMetadataPtr) *serializedMetadataPtr = nil; + return NO; + } + if (collection == nil) collection = @""; + + sqlite3_stmt *statement = [connection getAllForKeyStatement]; + if (statement == NULL) { + if (serializedObjectPtr) *serializedObjectPtr = nil; + if (serializedMetadataPtr) *serializedMetadataPtr = nil; + return NO; + } + + NSData *serializedObject = nil; + NSData *serializedMetadata = nil; + + BOOL found = NO; + + // SELECT "data", "metadata" FROM "database2" WHERE "collection" = ? AND "key" = ? ; + + YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); + sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); + + YapDatabaseString _key; MakeYapDatabaseString(&_key, key); + sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); + + int status = sqlite3_step(statement); + if (status == SQLITE_ROW) + { + if (connection->needsMarkSqlLevelSharedReadLock) + [connection markSqlLevelSharedReadLockAcquired]; + + const void *oBlob = sqlite3_column_blob(statement, 0); + int oBlobSize = sqlite3_column_bytes(statement, 0); + + const void *mBlob = sqlite3_column_blob(statement, 1); + int mBlobSize = sqlite3_column_bytes(statement, 1); + + if (serializedObjectPtr) { + serializedObject = [NSData dataWithBytes:(void *)oBlob length:oBlobSize]; + } + + if (serializedMetadataPtr) { + serializedMetadata = [NSData dataWithBytes:(void *)mBlob length:mBlobSize]; + } + + found = YES; + } + else if (status == SQLITE_ERROR) + { + YDBLogError(@"Error executing 'getAllForKeyStatement': %d %s", + status, sqlite3_errmsg(connection->db)); + } + + sqlite3_clear_bindings(statement); + sqlite3_reset(statement); + FreeYapDatabaseString(&_collection); + FreeYapDatabaseString(&_key); + + if (serializedObjectPtr) *serializedObjectPtr = serializedObject; + if (serializedMetadataPtr) *serializedMetadataPtr = serializedMetadata; + + return found; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Enumerate //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4032,333 +4058,123 @@ * as opposed to broadcasting your own separate notification. * * For more information, and code samples, please see the wiki article: - * https://github.com/yaptv/YapDatabase/wiki/YapDatabaseModifiedNotification + * https://github.com/yapstudios/YapDatabase/wiki/YapDatabaseModifiedNotification **/ @synthesize yapDatabaseModifiedNotificationCustomObject = customObjectForNotification; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Primitive -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of setObject:forKey:inCollection:. - * For more information see the documentation for setObject:forKey:inCollection:. - * - * @see setObject:forKey:inCollection: - * @see primitiveDataForKey:inCollection: -**/ -- (void)setPrimitiveData:(NSData *)primitiveData forKey:(NSString *)key inCollection:(NSString *)collection -{ - [self setPrimitiveData:primitiveData forKey:key inCollection:collection withPrimitiveMetadata:nil]; -} - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of setObject:forKey:inCollection:withMetadata:. - * For more information see the documentation for setObject:forKey:inCollection:withMetadata:. - * - * @see setObject:forKey:inCollection:withMetadata: - * @see primitiveDataForKey:inCollection: - * @see primitiveMetadataForKey:inCollection: -**/ -- (void)setPrimitiveData:(NSData *)primitiveData - forKey:(NSString *)key - inCollection:(NSString *)collection - withPrimitiveMetadata:(NSData *)primitiveMetadata -{ - if (primitiveData == nil) - { - [self removeObjectForKey:key inCollection:collection]; - return; - } - - if (key == nil) return; - if (collection == nil) collection = @""; - - BOOL found = NO; - int64_t rowid = 0; - - YapDatabaseString _collection; MakeYapDatabaseString(&_collection, collection); - YapDatabaseString _key; MakeYapDatabaseString(&_key, key); - - if (YES) // fetch rowid for key - { - sqlite3_stmt *statement = [connection getRowidForKeyStatement]; - if (statement == NULL) { - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - return; - } - - // SELECT "rowid" FROM "database2" WHERE "collection" = ? AND "key" = ?; - - sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); - sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - - int status = sqlite3_step(statement); - if (status == SQLITE_ROW) - { - rowid = sqlite3_column_int64(statement, 0); - found = YES; - } - else if (status == SQLITE_ERROR) - { - YDBLogError(@"Error executing 'getRowidForKeyStatement': %d %s, key(%@)", - status, sqlite3_errmsg(connection->db), key); - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - } - - BOOL set = YES; - - if (found) // update data for key - { - sqlite3_stmt *statement = [connection updateAllForRowidStatement]; - if (statement == NULL) { - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - return; - } - - // UPDATE "database2" SET "data" = ?, "metadata" = ? WHERE "rowid" = ?; - - sqlite3_bind_blob(statement, 1, primitiveData.bytes, (int)primitiveData.length, SQLITE_STATIC); - sqlite3_bind_blob(statement, 2, primitiveMetadata.bytes, (int)primitiveMetadata.length, SQLITE_STATIC); - - sqlite3_bind_int64(statement, 3, rowid); - - int status = sqlite3_step(statement); - if (status != SQLITE_DONE) - { - YDBLogError(@"Error executing 'updateAllForRowidStatement': %d %s", status, sqlite3_errmsg(connection->db)); - set = NO; - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - } - else // insert data for key - { - sqlite3_stmt *statement = [connection insertForRowidStatement]; - if (statement == NULL) { - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - return; - } - - // INSERT INTO "database2" ("collection", "key", "data", "metadata") VALUES (?, ?, ?, ?); - - sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); - sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - - sqlite3_bind_blob(statement, 3, primitiveData.bytes, (int)primitiveData.length, SQLITE_STATIC); - sqlite3_bind_blob(statement, 4, primitiveMetadata.bytes, (int)primitiveMetadata.length, SQLITE_STATIC); - - int status = sqlite3_step(statement); - if (status == SQLITE_DONE) - { - rowid = sqlite3_last_insert_rowid(connection->db); - } - else - { - YDBLogError(@"Error executing 'insertForRowidStatement': %d %s", status, sqlite3_errmsg(connection->db)); - set = NO; - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - } - - FreeYapDatabaseString(&_collection); - FreeYapDatabaseString(&_key); - - if (!set) return; - - connection->hasDiskChanges = YES; - isMutated = YES; // mutation during enumeration protection - - if (found) - { - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; - - [connection->objectCache removeObjectForKey:cacheKey]; - [connection->objectChanges setObject:[YapNull null] forKey:cacheKey]; - - [connection->metadataCache removeObjectForKey:cacheKey]; - [connection->metadataChanges setObject:[YapNull null] forKey:cacheKey]; - - for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) - { - [extTransaction handleRemoveObjectForCollectionKey:cacheKey withRowid:rowid]; - } - } -} - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveDataForKey:inCollection:). If you attempt to access it via the object accessor - * (objectForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of replaceObject:forKey:inCollection:. - * For more information see the documentation for replaceObject:forKey:inCollection:. - * - * @see replaceObject:forKey:inCollection: - * @see primitiveDataForKey:inCollection: -**/ -- (void)replacePrimitiveData:(NSData *)primitiveData forKey:(NSString *)key inCollection:(NSString *)collection -{ - if (primitiveData == nil) - { - [self removeObjectForKey:key inCollection:collection]; - return; - } - - if (collection == nil) collection = @""; - - int64_t rowid = 0; - if (![self getRowid:&rowid forKey:key inCollection:collection]) return; - - sqlite3_stmt *statement = [connection updateObjectForRowidStatement]; - if (statement == NULL) return; - - // UPDATE "database2" SET "data" = ? WHERE "rowid" = ?; - - sqlite3_bind_blob(statement, 1, primitiveData.bytes, (int)primitiveData.length, SQLITE_STATIC); - sqlite3_bind_int64(statement, 2, rowid); - - BOOL updated = YES; - - int status = sqlite3_step(statement); - if (status != SQLITE_DONE) - { - YDBLogError(@"Error executing 'updateObjectForRowidStatement': %d %s", - status, sqlite3_errmsg(connection->db)); - updated = NO; - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - - if (!updated) return; - - connection->hasDiskChanges = YES; - isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; - - [connection->objectCache removeObjectForKey:cacheKey]; - [connection->objectChanges setObject:[YapNull null] forKey:cacheKey]; - - for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) - { - [extTransaction handleRemoveObjectForCollectionKey:cacheKey withRowid:rowid]; - } -} - -/** - * Primitive access. - * This method is available in case you need to store irregular data that - * shouldn't go through the configured serializer/deserializer. - * - * Primitive data is stored into the database, but doesn't get routed through any of the extensions. - * - * Remember that if you place primitive data into the database via this method, - * you are responsible for accessing it via the appropriate primitive accessor (such as - * primitiveMetadataForKey:inCollection:). If you attempt to access it via the object accessor - * (metadataForKey:inCollection), then the system will attempt to deserialize the primitive data via the - * configured deserializer, which may or may not work depending on the primitive data you're storing. - * - * This method is the primitive version of replaceMetadata:forKey:inCollection:. - * For more information see the documentation for replaceMetadata:forKey:inCollection:. - * - * @see replaceMetadata:forKey:inCollection: - * @see primitiveMetadataForKey:inCollection: -**/ -- (void)replacePrimitiveMetadata:(NSData *)primitiveMetadata forKey:(NSString *)key inCollection:(NSString *)collection -{ - if (collection == nil) collection = @""; - - int64_t rowid = 0; - if (![self getRowid:&rowid forKey:key inCollection:collection]) return; - - sqlite3_stmt *statement = [connection updateMetadataForRowidStatement]; - if (statement == NULL) return; - - // UPDATE "database2" SET "metadata" = ? WHERE "rowid" = ?; - - sqlite3_bind_blob(statement, 1, primitiveMetadata.bytes, (int)primitiveMetadata.length, SQLITE_STATIC); - sqlite3_bind_int64(statement, 2, rowid); - - BOOL updated = YES; - - int status = sqlite3_step(statement); - if (status != SQLITE_DONE) - { - YDBLogError(@"Error executing 'updateMetadataForRowidStatement': %d %s", - status, sqlite3_errmsg(connection->db)); - updated = NO; - } - - sqlite3_clear_bindings(statement); - sqlite3_reset(statement); - - if (!updated) return; - - connection->hasDiskChanges = YES; - isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; - - [connection->metadataCache removeObjectForKey:cacheKey]; - [connection->metadataChanges setObject:[YapNull null] forKey:cacheKey]; - - for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) - { - [extTransaction handleReplaceMetadata:nil forCollectionKey:cacheKey withRowid:rowid]; - } -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Object & Metadata //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Sets the object for the given key/collection. + * The object is automatically serialized using the database's configured objectSerializer. + * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * This method implicitly sets the associated metadata to nil. + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). +**/ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection { - [self setObject:object forKey:key inCollection:collection withMetadata:nil]; + [self setObject:object forKey:key inCollection:collection withMetadata:nil + serializedObject:nil + serializedMetadata:nil]; } +/** + * Sets the object & metadata for the given key/collection. + * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * The metadata is optional. You can pass nil for the metadata is unneeded. + * If non-nil then the metadata is also written to the database (metadata is also persistent). +**/ - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection withMetadata:(id)metadata +{ + [self setObject:object forKey:key inCollection:collection withMetadata:metadata + serializedObject:nil + serializedMetadata:nil]; +} + +/** + * Sets the object & metadata for the given key/collection. + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * The metadata is optional. You can pass nil for the metadata is unneeded. + * If non-nil then the metadata is also written to the database (metadata is also persistent). + * + * @param preSerializedObject + * This value is optional. + * If non-nil then the object serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedObject is equal to what we would get if we ran the object through + * the database's configured objectSerializer. + * + * @param preSerializedMetadata + * This value is optional. + * If non-nil then the metadata serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedMetadata is equal to what we would get if we ran the metadata through + * the database's configured metadataSerializer. + * + * The preSerializedObject is only used if object is non-nil. + * The preSerializedMetadata is only used if metadata is non-nil. +**/ +- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection + withMetadata:(id)metadata + serializedObject:(NSData *)preSerializedObject + serializedMetadata:(NSData *)preSerializedMetadata { if (object == nil) { @@ -4369,26 +4185,45 @@ if (key == nil) return; if (collection == nil) collection = @""; - if (connection->database->objectSanitizer) + if (connection->database->objectPreSanitizer) { - object = connection->database->objectSanitizer(collection, key, object); + object = connection->database->objectPreSanitizer(collection, key, object); if (object == nil) { - YDBLogWarn(@"Object sanitizer returned nil for key(%@) object: %@", key, object); + YDBLogWarn(@"The objectPreSanitizer returned nil for collection(%@) key(%@)", collection, key); [self removeObjectForKey:key inCollection:collection]; return; } } - if (metadata && connection->database->metadataSanitizer) + if (metadata && connection->database->metadataPreSanitizer) { - metadata = connection->database->metadataSanitizer(collection, key, metadata); + metadata = connection->database->metadataPreSanitizer(collection, key, metadata); if (metadata == nil) { - YDBLogWarn(@"Metadata sanitizer returned nil for key(%@) metadata: %@", key, metadata); + YDBLogWarn(@"The metadataPresanitizer returned nil for collection(%@) key(%@)", collection, key); } } + // To use SQLITE_STATIC on our data, we use the objc_precise_lifetime attribute. + // This ensures the data isn't released until it goes out of scope. + + __attribute__((objc_precise_lifetime)) NSData *serializedObject = nil; + if (preSerializedObject) + serializedObject = preSerializedObject; + else + serializedObject = connection->database->objectSerializer(collection, key, object); + + __attribute__((objc_precise_lifetime)) NSData *serializedMetadata = nil; + if (metadata) + { + if (preSerializedMetadata) + serializedMetadata = preSerializedMetadata; + else + serializedMetadata = connection->database->metadataSerializer(collection, key, metadata); + } + + BOOL found = NO; int64_t rowid = 0; @@ -4426,6 +4261,22 @@ } BOOL set = YES; + YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; + + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + if (found) + [extTransaction handleWillUpdateObject:object + forCollectionKey:cacheKey + withMetadata:metadata + rowid:rowid]; + else + [extTransaction handleWillInsertObject:object + forCollectionKey:cacheKey + withMetadata:metadata]; + } + + if (found) // update data for key { @@ -4437,17 +4288,9 @@ } // UPDATE "database2" SET "data" = ?, "metadata" = ? WHERE "rowid" = ?; - // - // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. - // This ensures the data isn't released until it goes out of scope. - __attribute__((objc_precise_lifetime)) NSData *rawData = - connection->database->objectSerializer(collection, key, object); - sqlite3_bind_blob(statement, 1, rawData.bytes, (int)rawData.length, SQLITE_STATIC); - - __attribute__((objc_precise_lifetime)) NSData *rawMeta = - metadata ? connection->database->metadataSerializer(collection, key, metadata) : nil; - sqlite3_bind_blob(statement, 2, rawMeta.bytes, (int)rawMeta.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 1, serializedObject.bytes, (int)serializedObject.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 2, serializedMetadata.bytes, (int)serializedMetadata.length, SQLITE_STATIC); sqlite3_bind_int64(statement, 3, rowid); @@ -4471,20 +4314,12 @@ } // INSERT INTO "database2" ("collection", "key", "data", "metadata") VALUES (?, ?, ?, ?); - // - // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. - // This ensures the data isn't released until it goes out of scope. sqlite3_bind_text(statement, 1, _collection.str, _collection.length, SQLITE_STATIC); sqlite3_bind_text(statement, 2, _key.str, _key.length, SQLITE_STATIC); - __attribute__((objc_precise_lifetime)) NSData *rawData = - connection->database->objectSerializer(collection, key, object); - sqlite3_bind_blob(statement, 3, rawData.bytes, (int)rawData.length, SQLITE_STATIC); - - __attribute__((objc_precise_lifetime)) NSData *rawMeta = - metadata ? connection->database->metadataSerializer(collection, key, metadata) : nil; - sqlite3_bind_blob(statement, 4, rawMeta.bytes, (int)rawMeta.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 3, serializedObject.bytes, (int)serializedObject.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 4, serializedMetadata.bytes, (int)serializedMetadata.length, SQLITE_STATIC); int status = sqlite3_step(statement); if (status == SQLITE_DONE) @@ -4508,7 +4343,6 @@ connection->hasDiskChanges = YES; isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; [connection->keyCache setObject:cacheKey forKey:@(rowid)]; @@ -4569,60 +4403,144 @@ withMetadata:metadata rowid:rowid]; } + + if (connection->database->objectPostSanitizer) + { + connection->database->objectPostSanitizer(collection, key, object); + } + if (metadata && connection->database->metadataPreSanitizer) + { + connection->database->metadataPostSanitizer(collection, key, metadata); + } } /** * If a row with the given key/collection exists, then replaces the object for that row with the new value. - * It only replaces the object. The metadata for the row doesn't change. * + * It only replaces the object. The metadata for the row doesn't change. * If there is no row in the database for the given key/collection then this method does nothing. * - * If you pass nil for the object, then this method will remove + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). **/ - (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection { int64_t rowid = 0; if ([self getRowid:&rowid forKey:key inCollection:collection]) { - [self replaceObject:object forKey:key inCollection:collection withRowid:rowid]; + [self replaceObject:object forKey:key inCollection:collection withRowid:rowid serializedObject:nil]; } } -- (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid +/** + * If a row with the given key/collection exists, then replaces the object for that row with the new value. + * + * It only replaces the object. The metadata for the row doesn't change. + * If there is no row in the database for the given key/collection then this method does nothing. + * + * If you pass nil for the object, then this method will remove the row from the database (if it exists). + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw serialized NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * @param object + * The object to store in the database. + * This object is automatically serialized using the database's configured objectSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param preSerializedObject + * This value is optional. + * If non-nil then the object serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedObject is equal to what we would get if we ran the object through + * the database's configured objectSerializer. +**/ +- (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection + withSerializedObject:(NSData *)preSerializedObject +{ + int64_t rowid = 0; + if ([self getRowid:&rowid forKey:key inCollection:collection]) + { + [self replaceObject:object + forKey:key + inCollection:collection + withRowid:rowid + serializedObject:preSerializedObject]; + } +} + +/** + * Internal replaceObject method that takes a rowid. +**/ +- (void)replaceObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection + withRowid:(int64_t)rowid + serializedObject:(NSData *)preSerializedObject { if (object == nil) { - [self removeObjectForKey:key inCollection:collection]; + [self removeObjectForKey:key inCollection:collection withRowid:rowid]; return; } NSAssert(key != nil, @"Internal error"); if (collection == nil) collection = @""; - if (connection->database->objectSanitizer) + if (connection->database->objectPreSanitizer) { - object = connection->database->objectSanitizer(collection, key, object); + object = connection->database->objectPreSanitizer(collection, key, object); if (object == nil) { - YDBLogWarn(@"Object sanitizer returned nil for key(%@) object: %@", key, object); + YDBLogWarn(@"The objectPreSanitizer returned nil for collection(%@) key(%@)", collection, key); [self removeObjectForKey:key inCollection:collection withRowid:rowid]; return; } } + YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillReplaceObject:object forCollectionKey:cacheKey withRowid:rowid]; + } + + // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. + // This ensures the data isn't released until it goes out of scope. + + __attribute__((objc_precise_lifetime)) NSData *serializedObject = nil; + if (preSerializedObject) + serializedObject = preSerializedObject; + else + serializedObject = connection->database->objectSerializer(collection, key, object); + sqlite3_stmt *statement = [connection updateObjectForRowidStatement]; if (statement == NULL) return; // UPDATE "database2" SET "data" = ? WHERE "rowid" = ?; - // - // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. - // This ensures the data isn't released until it goes out of scope. - - __attribute__((objc_precise_lifetime)) NSData *rawData = - connection->database->objectSerializer(collection, key, object); - sqlite3_bind_blob(statement, 1, rawData.bytes, (int)rawData.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 1, serializedObject.bytes, (int)serializedObject.length, SQLITE_STATIC); sqlite3_bind_int64(statement, 2, rowid); BOOL updated = YES; @@ -4630,7 +4548,7 @@ int status = sqlite3_step(statement); if (status != SQLITE_DONE) { - YDBLogError(@"Error executing 'updateDataForRowidStatement': %d %s", + YDBLogError(@"Error executing 'updateObjectForRowidStatement': %d %s", status, sqlite3_errmsg(connection->db)); updated = NO; } @@ -4642,7 +4560,6 @@ connection->hasDiskChanges = YES; isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; id _object = nil; if (connection->objectPolicy == YapDatabasePolicyContainment) { @@ -4666,58 +4583,140 @@ { [extTransaction handleReplaceObject:object forCollectionKey:cacheKey withRowid:rowid]; } + + if (connection->database->objectPostSanitizer) + { + connection->database->objectPostSanitizer(collection, key, object); + } } /** * If a row with the given key/collection exists, then replaces the metadata for that row with the new value. - * It only replaces the metadata. The object for the row doesn't change. * + * It only replaces the metadata. The object for the row doesn't change. * If there is no row in the database for the given key/collection then this method does nothing. * * If you pass nil for the metadata, any metadata previously associated with the key/collection is removed. + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). **/ - (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection { int64_t rowid = 0; if ([self getRowid:&rowid forKey:key inCollection:collection]) { - [self replaceMetadata:metadata forKey:key inCollection:collection withRowid:rowid]; + [self replaceMetadata:metadata forKey:key inCollection:collection withRowid:rowid serializedMetadata:nil]; } } +/** + * If a row with the given key/collection exists, then replaces the metadata for that row with the new value. + * + * It only replaces the metadata. The object for the row doesn't change. + * If there is no row in the database for the given key/collection then this method does nothing. + * + * If you pass nil for the metadata, any metadata previously associated with the key/collection is removed. + * + * This method allows for a bit of optimization if you happen to already have a serialized version of + * the object and/or metadata. For example, if you downloaded an object in serialized form, + * and you still have the raw serialized NSData, then you can use this method to skip the serialization step + * when storing the object to the database. + * + * @param metadata + * The metadata to store in the database. + * This metadata is automatically serialized using the database's configured metadataSerializer. + * + * @param key + * The lookup key. + * The tuple is used to uniquely identify the row in the database. + * This value should not be nil. If a nil key is passed, then this method does nothing. + * + * @param collection + * The lookup collection. + * The tuple is used to uniquely identify the row in the database. + * If a nil collection is passed, then the collection is implicitly the empty string (@""). + * + * @param preSerializedMetadata + * This value is optional. + * If non-nil then the metadata serialization step is skipped, and this value is used instead. + * It is assumed that preSerializedMetadata is equal to what we would get if we ran the metadata through + * the database's configured metadataSerializer. +**/ +- (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection + withSerializedMetadata:(NSData *)preSerializedMetadata +{ + int64_t rowid = 0; + if ([self getRowid:&rowid forKey:key inCollection:collection]) + { + [self replaceMetadata:metadata + forKey:key + inCollection:collection + withRowid:rowid + serializedMetadata:preSerializedMetadata]; + } +} + +/** + * Internal replaceMetadata method that takes a rowid. +**/ - (void)replaceMetadata:(id)metadata forKey:(NSString *)key inCollection:(NSString *)collection withRowid:(int64_t)rowid + serializedMetadata:(NSData *)preSerializedMetadata { NSAssert(key != nil, @"Internal error"); if (collection == nil) collection = @""; - if (metadata && connection->database->metadataSanitizer) + if (metadata && connection->database->metadataPreSanitizer) { - metadata = connection->database->metadataSanitizer(collection, key, metadata); + metadata = connection->database->metadataPreSanitizer(collection, key, metadata); if (metadata == nil) { - YDBLogWarn(@"Metadata sanitizer returned nil for key: %@", key); + YDBLogWarn(@"The metadataPreSanitizer returned nil for collection(%@) key(%@)", collection, key); } } + // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. + // This ensures the data isn't released until it goes out of scope. + + __attribute__((objc_precise_lifetime)) NSData *serializedMetadata = nil; + if (metadata) + { + if (preSerializedMetadata) + serializedMetadata = preSerializedMetadata; + else + serializedMetadata = connection->database->metadataSerializer(collection, key, metadata); + } + sqlite3_stmt *statement = [connection updateMetadataForRowidStatement]; if (statement == NULL) return; // UPDATE "database2" SET "metadata" = ? WHERE "rowid" = ?; - // - // To use SQLITE_STATIC on our data blob, we use the objc_precise_lifetime attribute. - // This ensures the data isn't released until it goes out of scope. - - __attribute__((objc_precise_lifetime)) NSData *rawMeta = - metadata ? connection->database->metadataSerializer(collection, key, metadata) : nil; - sqlite3_bind_blob(statement, 1, rawMeta.bytes, (int)rawMeta.length, SQLITE_STATIC); + sqlite3_bind_blob(statement, 1, serializedMetadata.bytes, (int)serializedMetadata.length, SQLITE_STATIC); sqlite3_bind_int64(statement, 2, rowid); BOOL updated = YES; + YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillReplaceMetadata:metadata forCollectionKey:cacheKey withRowid:rowid]; + } + int status = sqlite3_step(statement); if (status != SQLITE_DONE) { @@ -4733,7 +4732,6 @@ connection->hasDiskChanges = YES; isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; if (metadata) { @@ -4765,6 +4763,11 @@ { [extTransaction handleReplaceMetadata:metadata forCollectionKey:cacheKey withRowid:rowid]; } + + if (metadata && connection->database->metadataPostSanitizer) + { + connection->database->metadataPostSanitizer(collection, key, metadata); + } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4828,6 +4831,12 @@ BOOL removed = YES; + YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillRemoveObjectForCollectionKey:cacheKey withRowid:rowid]; + } + int status = sqlite3_step(statement); if (status != SQLITE_DONE) { @@ -4843,7 +4852,6 @@ connection->hasDiskChanges = YES; isMutated = YES; // mutation during enumeration protection - YapCollectionKey *cacheKey = [[YapCollectionKey alloc] initWithCollection:collection key:key]; NSNumber *rowidNumber = @(rowid); [connection->keyCache removeObjectForKey:rowidNumber]; @@ -5020,6 +5028,13 @@ sqlite3_bind_int64(statement, (int)(i + 1), rowid); } + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillRemoveObjectsForKeys:foundKeys + inCollection:collection + withRowids:foundRowids]; + } + status = sqlite3_step(statement); if (status != SQLITE_DONE) { @@ -5298,6 +5313,13 @@ sqlite3_bind_int64(statement, (int)(i + 1), rowid); } + + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillRemoveObjectsForKeys:foundKeys + inCollection:collection + withRowids:foundRowids]; + } status = sqlite3_step(statement); if (status != SQLITE_DONE) @@ -5336,6 +5358,11 @@ { sqlite3_stmt *statement = [connection removeAllStatement]; if (statement == NULL) return; + + for (YapDatabaseExtensionTransaction *extTransaction in [self orderedExtensions]) + { + [extTransaction handleWillRemoveAllObjectsInAllCollections]; + } int status = sqlite3_step(statement); if (status != SQLITE_DONE) @@ -5348,6 +5375,7 @@ connection->hasDiskChanges = YES; isMutated = YES; // mutation during enumeration protection + [connection->keyCache removeAllObjects]; [connection->objectCache removeAllObjects]; [connection->metadataCache removeAllObjects]; diff --git a/Pods/libextobjc/LICENSE.md b/Pods/libextobjc/LICENSE.md index 4af8a41..255c6f2 100644 --- a/Pods/libextobjc/LICENSE.md +++ b/Pods/libextobjc/LICENSE.md @@ -1,4 +1,4 @@ -**Copyright (c) 2012 - 2013 Justin Spahr-Summers** +**Copyright (c) 2012 - 2014 Justin Spahr-Summers** 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 diff --git a/Pods/libextobjc/extobjc/EXTKeyPathCoding.h b/Pods/libextobjc/extobjc/EXTKeyPathCoding.h index f34dc4a..2f38187 100644 --- a/Pods/libextobjc/extobjc/EXTKeyPathCoding.h +++ b/Pods/libextobjc/extobjc/EXTKeyPathCoding.h @@ -36,7 +36,10 @@ NSString *lowercaseStringPath = @keypath(NSString.new, lowercaseString); * uses of \@keypath. */ #define keypath(...) \ - metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__)) + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Warc-repeated-use-of-weak\"") \ + metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__)) \ + _Pragma("clang diagnostic pop") \ #define keypath1(PATH) \ (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1)) diff --git a/Pods/libextobjc/extobjc/EXTRuntimeExtensions.m b/Pods/libextobjc/extobjc/EXTRuntimeExtensions.m index 7317ed3..ea76646 100644 --- a/Pods/libextobjc/extobjc/EXTRuntimeExtensions.m +++ b/Pods/libextobjc/extobjc/EXTRuntimeExtensions.m @@ -707,7 +707,7 @@ BOOL ext_getPropertyAccessorsForClass (objc_property_t property, Class aClass, M SEL setterName = attributes->setter; free(attributes); - attributes = NO; + attributes = NULL; /* * set up an autorelease pool in case this sends aClass its first message diff --git a/Pods/libextobjc/extobjc/EXTScope.h b/Pods/libextobjc/extobjc/EXTScope.h index bfaf689..cdc549b 100644 --- a/Pods/libextobjc/extobjc/EXTScope.h +++ b/Pods/libextobjc/extobjc/EXTScope.h @@ -29,7 +29,7 @@ * a useless construct in such a case anyways. */ #define onExit \ - autoreleasepool {} \ + ext_keywordify \ __strong ext_cleanupBlock_t metamacro_concat(ext_exitBlock_, __LINE__) __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^ /** @@ -43,7 +43,7 @@ * See #strongify for an example of usage. */ #define weakify(...) \ - autoreleasepool {} \ + ext_keywordify \ metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__) /** @@ -51,7 +51,7 @@ * classes that do not support weak references. */ #define unsafeify(...) \ - autoreleasepool {} \ + ext_keywordify \ metamacro_foreach_cxt(ext_weakify_,, __unsafe_unretained, __VA_ARGS__) /** @@ -81,7 +81,7 @@ * @endcode */ #define strongify(...) \ - autoreleasepool {} \ + ext_keywordify \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wshadow\"") \ metamacro_foreach(ext_strongify_,, __VA_ARGS__) \ @@ -97,3 +97,20 @@ void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block); #define ext_strongify_(INDEX, VAR) \ __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_); + +// Details about the choice of backing keyword: +// +// The use of @try/@catch/@finally can cause the compiler to suppress +// return-type warnings. +// The use of @autoreleasepool {} is not optimized away by the compiler, +// resulting in superfluous creation of autorelease pools. +// +// Since neither option is perfect, and with no other alternatives, the +// compromise is to use @autorelease in DEBUG builds to maintain compiler +// analysis, and to use @try/@catch otherwise to avoid insertion of unnecessary +// autorelease pools. +#if DEBUG +#define ext_keywordify autoreleasepool {} +#else +#define ext_keywordify try {} @catch (...) {} +#endif