motion-yapper 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +63 -0
- data/README.md +16 -0
- data/Rakefile +20 -0
- data/app/app_delegate.rb +5 -0
- data/lib/yapper.rb +30 -0
- data/lib/yapper/attachment.rb +48 -0
- data/lib/yapper/bson.rb +20 -0
- data/lib/yapper/config.rb +18 -0
- data/lib/yapper/db.rb +151 -0
- data/lib/yapper/document.rb +54 -0
- data/lib/yapper/document/attachment.rb +26 -0
- data/lib/yapper/document/callbacks.rb +86 -0
- data/lib/yapper/document/persistance.rb +171 -0
- data/lib/yapper/document/relation.rb +84 -0
- data/lib/yapper/document/selection.rb +100 -0
- data/lib/yapper/extensions.rb +80 -0
- data/lib/yapper/log.rb +5 -0
- data/lib/yapper/sync.rb +134 -0
- data/lib/yapper/sync/data.rb +12 -0
- data/lib/yapper/sync/event.rb +194 -0
- data/lib/yapper/sync/queue.rb +164 -0
- data/lib/yapper/timestamps.rb +16 -0
- data/lib/yapper/version.rb +3 -0
- data/lib/yapper/yapper.rb +2 -0
- data/spec/helpers/time_helper.rb +3 -0
- data/spec/integration/all_spec.rb +40 -0
- data/spec/integration/callback_spec.rb +87 -0
- data/spec/integration/db_spec.rb +40 -0
- data/spec/integration/find_spec.rb +51 -0
- data/spec/integration/persistance_spec.rb +118 -0
- data/spec/integration/relation_spec.rb +174 -0
- data/spec/integration/sync_spec.rb +42 -0
- data/spec/integration/timestamps_spec.rb +34 -0
- data/spec/integration/types_spec.rb +23 -0
- data/spec/integration/when_spec.rb +29 -0
- data/spec/integration/where_spec.rb +132 -0
- data/vendor/Podfile.lock +24 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.h +641 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.m +1396 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +133 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m +327 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.h +113 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.m +321 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.h +71 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.m +150 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.m +157 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworking.h +43 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.h +68 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.m +143 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h +370 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m +848 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.h +89 -0
- data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.m +167 -0
- data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.h +78 -0
- data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.m +191 -0
- data/vendor/Pods/AFNetworking/LICENSE +19 -0
- data/vendor/Pods/AFNetworking/README.md +208 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPClient.h +641 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPRequestOperation.h +133 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFImageRequestOperation.h +113 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFJSONRequestOperation.h +71 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworking.h +43 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFPropertyListRequestOperation.h +68 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFURLConnectionOperation.h +370 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/AFXMLRequestOperation.h +89 -0
- data/vendor/Pods/BuildHeaders/AFNetworking/UIImageView+AFNetworking.h +78 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +41 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +334 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +601 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +167 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
- data/vendor/Pods/BuildHeaders/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
- data/vendor/Pods/BuildHeaders/Reachability/Reachability.h +109 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +90 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +20 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +547 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +447 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnectionState.h +29 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +37 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtension.h +15 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +108 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseLogging.h +158 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseManager.h +17 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +424 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseQuery.h +42 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseStatement.h +13 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseString.h +121 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +541 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +186 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +272 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +115 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +825 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +56 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPage.h +36 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +153 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +447 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapMemoryTable.h +74 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapNull.h +17 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapSet.h +41 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapTouch.h +15 -0
- data/vendor/Pods/CocoaLumberjack/LICENSE.txt +18 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +41 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +99 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +102 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +727 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +334 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +1353 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +601 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +1083 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +167 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +1479 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +7 -0
- data/vendor/Pods/CocoaLumberjack/README.markdown +37 -0
- data/vendor/Pods/Headers/AFNetworking/AFHTTPClient.h +641 -0
- data/vendor/Pods/Headers/AFNetworking/AFHTTPRequestOperation.h +133 -0
- data/vendor/Pods/Headers/AFNetworking/AFImageRequestOperation.h +113 -0
- data/vendor/Pods/Headers/AFNetworking/AFJSONRequestOperation.h +71 -0
- data/vendor/Pods/Headers/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
- data/vendor/Pods/Headers/AFNetworking/AFNetworking.h +43 -0
- data/vendor/Pods/Headers/AFNetworking/AFPropertyListRequestOperation.h +68 -0
- data/vendor/Pods/Headers/AFNetworking/AFURLConnectionOperation.h +370 -0
- data/vendor/Pods/Headers/AFNetworking/AFXMLRequestOperation.h +89 -0
- data/vendor/Pods/Headers/AFNetworking/UIImageView+AFNetworking.h +78 -0
- data/vendor/Pods/Headers/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +41 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +334 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +601 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +167 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
- data/vendor/Pods/Headers/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
- data/vendor/Pods/Headers/Reachability/Reachability.h +109 -0
- data/vendor/Pods/Headers/YapDatabase/YapCache.h +90 -0
- data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +20 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +547 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +447 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnectionState.h +29 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseDefaults.h +37 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtension.h +15 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +108 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseLogging.h +158 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseManager.h +17 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabasePrivate.h +424 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseQuery.h +42 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseStatement.h +13 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseString.h +121 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +541 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +186 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +272 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +115 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +825 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +56 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPage.h +36 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPrivate.h +153 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +447 -0
- data/vendor/Pods/Headers/YapDatabase/YapMemoryTable.h +74 -0
- data/vendor/Pods/Headers/YapDatabase/YapNull.h +17 -0
- data/vendor/Pods/Headers/YapDatabase/YapSet.h +41 -0
- data/vendor/Pods/Headers/YapDatabase/YapTouch.h +15 -0
- data/vendor/Pods/Headers/____Pods-AFNetworking-prefix.h +17 -0
- data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +5 -0
- data/vendor/Pods/Headers/____Pods-NSData+MD5Digest-prefix.h +5 -0
- data/vendor/Pods/Headers/____Pods-Reachability-prefix.h +5 -0
- data/vendor/Pods/Headers/____Pods-YapDatabase-prefix.h +5 -0
- data/vendor/Pods/Headers/____Pods-environment.h +38 -0
- data/vendor/Pods/Manifest.lock +24 -0
- data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
- data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.m +39 -0
- data/vendor/Pods/NSData+MD5Digest/README.md +11 -0
- data/vendor/Pods/Pods-AFNetworking-Private.xcconfig +5 -0
- data/vendor/Pods/Pods-AFNetworking-dummy.m +5 -0
- data/vendor/Pods/Pods-AFNetworking-prefix.pch +17 -0
- data/vendor/Pods/Pods-AFNetworking.xcconfig +1 -0
- data/vendor/Pods/Pods-Acknowledgements.markdown +96 -0
- data/vendor/Pods/Pods-Acknowledgements.plist +142 -0
- data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +5 -0
- data/vendor/Pods/Pods-CocoaLumberjack-dummy.m +5 -0
- data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +5 -0
- data/vendor/Pods/Pods-CocoaLumberjack.xcconfig +0 -0
- data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +5 -0
- data/vendor/Pods/Pods-NSData+MD5Digest-dummy.m +5 -0
- data/vendor/Pods/Pods-NSData+MD5Digest-prefix.pch +5 -0
- data/vendor/Pods/Pods-NSData+MD5Digest.xcconfig +0 -0
- data/vendor/Pods/Pods-Reachability-Private.xcconfig +5 -0
- data/vendor/Pods/Pods-Reachability-dummy.m +5 -0
- data/vendor/Pods/Pods-Reachability-prefix.pch +5 -0
- data/vendor/Pods/Pods-Reachability.xcconfig +1 -0
- data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +5 -0
- data/vendor/Pods/Pods-YapDatabase-dummy.m +5 -0
- data/vendor/Pods/Pods-YapDatabase-prefix.pch +5 -0
- data/vendor/Pods/Pods-YapDatabase.xcconfig +1 -0
- data/vendor/Pods/Pods-dummy.m +5 -0
- data/vendor/Pods/Pods-environment.h +38 -0
- data/vendor/Pods/Pods-resources.sh +68 -0
- data/vendor/Pods/Pods.bridgesupport +5096 -0
- data/vendor/Pods/Pods.xcconfig +5 -0
- data/vendor/Pods/Pods.xcodeproj/project.pbxproj +5536 -0
- data/vendor/Pods/Reachability/LICENCE.txt +24 -0
- data/vendor/Pods/Reachability/README.md +65 -0
- data/vendor/Pods/Reachability/Reachability.h +109 -0
- data/vendor/Pods/Reachability/Reachability.m +527 -0
- data/vendor/Pods/YapDatabase/LICENSE.txt +18 -0
- data/vendor/Pods/YapDatabase/README.md +30 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +19 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +108 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +175 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h +12 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m +41 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +39 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +966 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +69 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +89 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +146 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +32 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +298 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m +95 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +68 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +1352 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +440 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.h +15 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +58 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +11 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +46 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +11 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +180 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +73 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +100 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +149 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h +33 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +330 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h +33 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +184 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h +58 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +1166 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h +94 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h +72 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h +36 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm +296 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h +27 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m +28 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +153 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h +17 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +272 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +2494 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +825 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +1567 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h +330 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m +141 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +186 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +191 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +115 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +897 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +56 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +27 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +447 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +4505 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +90 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +453 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.h +29 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.m +48 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +37 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +83 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.h +158 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.m +73 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.h +17 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.m +56 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +424 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.h +13 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.m +26 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseString.h +121 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.h +74 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.m +603 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.h +17 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +31 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.h +15 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.m +31 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +20 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +194 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +42 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +96 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +41 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.m +82 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +547 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +2022 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +447 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +3874 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +541 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +5282 -0
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +16 -0
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +13 -0
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +20 -0
- data/yapper.gemspec +24 -0
- metadata +458 -0
|
@@ -0,0 +1,1567 @@
|
|
|
1
|
+
#import "YapDatabaseViewMappingsPrivate.h"
|
|
2
|
+
#import "YapDatabaseViewRangeOptionsPrivate.h"
|
|
3
|
+
#import "YapDatabaseViewTransaction.h"
|
|
4
|
+
|
|
5
|
+
#import "YapDatabasePrivate.h"
|
|
6
|
+
|
|
7
|
+
#import "YapDatabaseLogging.h"
|
|
8
|
+
|
|
9
|
+
#if ! __has_feature(objc_arc)
|
|
10
|
+
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Define log level for this file: OFF, ERROR, WARN, INFO, VERBOSE
|
|
15
|
+
* See YapDatabaseLogging.h for more information.
|
|
16
|
+
**/
|
|
17
|
+
#if DEBUG
|
|
18
|
+
static const int ydbLogLevel = YDB_LOG_LEVEL_WARN;
|
|
19
|
+
#else
|
|
20
|
+
static const int ydbLogLevel = YDB_LOG_LEVEL_WARN;
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@implementation YapDatabaseViewMappings
|
|
25
|
+
{
|
|
26
|
+
// Immutable init parameters
|
|
27
|
+
NSArray *allGroups;
|
|
28
|
+
NSString *registeredViewName;
|
|
29
|
+
|
|
30
|
+
// Mappings and cached counts
|
|
31
|
+
NSMutableArray *visibleGroups;
|
|
32
|
+
NSMutableDictionary *counts;
|
|
33
|
+
BOOL isUsingConsolidatedGroup;
|
|
34
|
+
BOOL autoConsolidationDisabled;
|
|
35
|
+
|
|
36
|
+
// Configuration
|
|
37
|
+
NSMutableSet *dynamicSections;
|
|
38
|
+
NSMutableSet *reverse;
|
|
39
|
+
NSMutableDictionary *rangeOptions;
|
|
40
|
+
NSMutableDictionary *dependencies;
|
|
41
|
+
NSUInteger autoConsolidateGroupsThreshold;
|
|
42
|
+
NSString *consolidatedGroupName;
|
|
43
|
+
|
|
44
|
+
// Snapshot (used for error detection)
|
|
45
|
+
uint64_t snapshotOfLastUpdate;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@synthesize allGroups = allGroups;
|
|
49
|
+
@synthesize view = registeredViewName;
|
|
50
|
+
|
|
51
|
+
@synthesize snapshotOfLastUpdate = snapshotOfLastUpdate;
|
|
52
|
+
|
|
53
|
+
+ (instancetype)mappingsWithGroups:(NSArray *)inGroups view:(NSString *)inRegisteredViewName
|
|
54
|
+
{
|
|
55
|
+
return [[YapDatabaseViewMappings alloc] initWithGroups:inGroups view:inRegisteredViewName];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (id)initWithGroups:(NSArray *)inGroups
|
|
59
|
+
view:(NSString *)inRegisteredViewName
|
|
60
|
+
{
|
|
61
|
+
if ((self = [super init]))
|
|
62
|
+
{
|
|
63
|
+
allGroups = [[NSArray alloc] initWithArray:inGroups copyItems:YES];
|
|
64
|
+
registeredViewName = [inRegisteredViewName copy];
|
|
65
|
+
|
|
66
|
+
NSUInteger allGroupsCount = [allGroups count];
|
|
67
|
+
|
|
68
|
+
visibleGroups = [[NSMutableArray alloc] initWithCapacity:allGroupsCount];
|
|
69
|
+
|
|
70
|
+
dynamicSections = [[NSMutableSet alloc] initWithCapacity:allGroupsCount];
|
|
71
|
+
reverse = [[NSMutableSet alloc] initWithCapacity:allGroupsCount];
|
|
72
|
+
|
|
73
|
+
id sharedKeySet = [NSDictionary sharedKeySetForKeys:allGroups];
|
|
74
|
+
|
|
75
|
+
counts = [NSMutableDictionary dictionaryWithSharedKeySet:sharedKeySet];
|
|
76
|
+
rangeOptions = [NSMutableDictionary dictionaryWithSharedKeySet:sharedKeySet];
|
|
77
|
+
dependencies = [NSMutableDictionary dictionaryWithSharedKeySet:sharedKeySet];
|
|
78
|
+
|
|
79
|
+
snapshotOfLastUpdate = UINT64_MAX;
|
|
80
|
+
}
|
|
81
|
+
return self;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
- (id)copyWithZone:(NSZone *)zone
|
|
85
|
+
{
|
|
86
|
+
YapDatabaseViewMappings *copy = [[YapDatabaseViewMappings alloc] init];
|
|
87
|
+
copy->allGroups = allGroups;
|
|
88
|
+
copy->registeredViewName = registeredViewName;
|
|
89
|
+
|
|
90
|
+
copy->visibleGroups = [visibleGroups mutableCopy];
|
|
91
|
+
copy->counts = [counts mutableCopy];
|
|
92
|
+
copy->isUsingConsolidatedGroup = isUsingConsolidatedGroup;
|
|
93
|
+
copy->autoConsolidationDisabled = autoConsolidationDisabled;
|
|
94
|
+
|
|
95
|
+
copy->dynamicSections = [dynamicSections mutableCopy];
|
|
96
|
+
copy->reverse = [reverse mutableCopy];
|
|
97
|
+
copy->rangeOptions = [rangeOptions mutableCopy];
|
|
98
|
+
copy->dependencies = [dependencies mutableCopy];
|
|
99
|
+
copy->autoConsolidateGroupsThreshold = autoConsolidateGroupsThreshold;
|
|
100
|
+
copy->consolidatedGroupName = consolidatedGroupName;
|
|
101
|
+
|
|
102
|
+
copy->snapshotOfLastUpdate = snapshotOfLastUpdate;
|
|
103
|
+
|
|
104
|
+
return copy;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
108
|
+
#pragma mark Configuration
|
|
109
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
110
|
+
|
|
111
|
+
- (void)setIsDynamicSectionForAllGroups:(BOOL)isDynamic
|
|
112
|
+
{
|
|
113
|
+
if (isDynamic)
|
|
114
|
+
[dynamicSections addObjectsFromArray:allGroups];
|
|
115
|
+
else
|
|
116
|
+
[dynamicSections removeAllObjects];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (BOOL)isDynamicSectionForAllGroups
|
|
120
|
+
{
|
|
121
|
+
return ([dynamicSections count] == [allGroups count]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
- (void)setIsDynamicSection:(BOOL)isDynamic forGroup:(NSString *)group
|
|
125
|
+
{
|
|
126
|
+
if (![allGroups containsObject:group]) {
|
|
127
|
+
YDBLogWarn(@"%@ - mappings doesn't contain group(%@), only: %@", THIS_METHOD, group, allGroups);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isDynamic)
|
|
132
|
+
[dynamicSections addObject:group];
|
|
133
|
+
else
|
|
134
|
+
[dynamicSections removeObject:group];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
- (BOOL)isDynamicSectionForGroup:(NSString *)group
|
|
138
|
+
{
|
|
139
|
+
return [dynamicSections containsObject:group];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
- (void)setRangeOptions:(YapDatabaseViewRangeOptions *)rangeOpts forGroup:(NSString *)group
|
|
143
|
+
{
|
|
144
|
+
if (rangeOpts == nil) {
|
|
145
|
+
[self removeRangeOptionsForGroup:group];
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (![allGroups containsObject:group]) {
|
|
150
|
+
YDBLogWarn(@"%@ - mappings doesn't contain group(%@), only: %@", THIS_METHOD, group, allGroups);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Store private immutable copy
|
|
155
|
+
if ([reverse containsObject:group])
|
|
156
|
+
rangeOpts = [rangeOpts copyAndReverse];
|
|
157
|
+
else
|
|
158
|
+
rangeOpts = [rangeOpts copy];
|
|
159
|
+
|
|
160
|
+
if (snapshotOfLastUpdate == UINT64_MAX)
|
|
161
|
+
{
|
|
162
|
+
// We don't have the counts yet, so we can't set rangeOpts.length yet.
|
|
163
|
+
|
|
164
|
+
[rangeOptions setObject:rangeOpts forKey:group];
|
|
165
|
+
}
|
|
166
|
+
else
|
|
167
|
+
{
|
|
168
|
+
// Normal setter logic
|
|
169
|
+
|
|
170
|
+
[self updateRangeOptions:rangeOpts forGroup:group];
|
|
171
|
+
[self updateVisibility];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
- (YapDatabaseViewRangeOptions *)rangeOptionsForGroup:(NSString *)group
|
|
176
|
+
{
|
|
177
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
178
|
+
|
|
179
|
+
// Return copy. Our internal version must remain immutable.
|
|
180
|
+
|
|
181
|
+
if ([reverse containsObject:group])
|
|
182
|
+
return [rangeOpts copyAndReverse];
|
|
183
|
+
else
|
|
184
|
+
return [rangeOpts copy];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
- (void)removeRangeOptionsForGroup:(NSString *)group
|
|
188
|
+
{
|
|
189
|
+
[rangeOptions removeObjectForKey:group];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
- (void)setCellDrawingDependencyForNeighboringCellWithOffset:(NSInteger)offset forGroup:(NSString *)group
|
|
193
|
+
{
|
|
194
|
+
[self setCellDrawingDependencyOffsets:[NSSet setWithObject:@(offset)] forGroup:group];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
- (void)setCellDrawingDependencyOffsets:(NSSet *)offsets forGroup:(NSString *)group
|
|
198
|
+
{
|
|
199
|
+
if (![allGroups containsObject:group]) {
|
|
200
|
+
YDBLogWarn(@"%@ - mappings doesn't contain group(%@), only: %@", THIS_METHOD, group, allGroups);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
NSMutableSet *validOffsets = [NSMutableSet setWithCapacity:[offsets count]];
|
|
205
|
+
BOOL needsReverse = [reverse containsObject:group];
|
|
206
|
+
|
|
207
|
+
for (id obj in offsets)
|
|
208
|
+
{
|
|
209
|
+
if ([obj isKindOfClass:[NSNumber class]])
|
|
210
|
+
{
|
|
211
|
+
NSInteger offset = [obj integerValue];
|
|
212
|
+
if (offset != 0)
|
|
213
|
+
{
|
|
214
|
+
if (needsReverse)
|
|
215
|
+
[validOffsets addObject:@(offset * -1)];
|
|
216
|
+
else
|
|
217
|
+
[validOffsets addObject:obj];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
{
|
|
222
|
+
YDBLogWarn(@"%@ - Non-NSNumber passed in offsets: %@", THIS_METHOD, obj);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
[dependencies setObject:[validOffsets copy] forKey:group];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
- (NSSet *)cellDrawingDependencyOffsetsForGroup:(NSString *)group
|
|
230
|
+
{
|
|
231
|
+
NSSet *offsets = [dependencies objectForKey:group];
|
|
232
|
+
|
|
233
|
+
if ([reverse containsObject:group])
|
|
234
|
+
{
|
|
235
|
+
NSMutableSet *reverseOffsets = [NSMutableSet setWithCapacity:[offsets count]];
|
|
236
|
+
for (NSNumber *obj in offsets)
|
|
237
|
+
{
|
|
238
|
+
NSUInteger offset = [obj integerValue];
|
|
239
|
+
[reverseOffsets addObject:@(offset * -1)];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return [reverseOffsets copy];
|
|
243
|
+
}
|
|
244
|
+
else
|
|
245
|
+
{
|
|
246
|
+
return offsets;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
- (void)setIsReversed:(BOOL)isReversed forGroup:(NSString *)group
|
|
251
|
+
{
|
|
252
|
+
if (![allGroups containsObject:group]) {
|
|
253
|
+
YDBLogWarn(@"%@ - mappings doesn't contain group(%@), only: %@", THIS_METHOD, group, allGroups);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (isReversed)
|
|
258
|
+
[reverse addObject:group];
|
|
259
|
+
else
|
|
260
|
+
[reverse removeObject:group];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
- (BOOL)isReversedForGroup:(NSString *)group
|
|
264
|
+
{
|
|
265
|
+
return [reverse containsObject:group];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
- (void)setAutoConsolidateGroupsThreshold:(NSUInteger)threshold withName:(NSString *)inConsolidatedGroupName
|
|
269
|
+
{
|
|
270
|
+
if ([allGroups containsObject:inConsolidatedGroupName])
|
|
271
|
+
{
|
|
272
|
+
YDBLogWarn(@"%@ - consolidatedGroupName cannot match existing groupName", THIS_METHOD);
|
|
273
|
+
|
|
274
|
+
autoConsolidateGroupsThreshold = 0;
|
|
275
|
+
consolidatedGroupName = nil;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (inConsolidatedGroupName == nil || threshold == 0)
|
|
279
|
+
{
|
|
280
|
+
autoConsolidateGroupsThreshold = 0;
|
|
281
|
+
consolidatedGroupName = nil;
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
{
|
|
285
|
+
autoConsolidateGroupsThreshold = threshold;
|
|
286
|
+
consolidatedGroupName = [inConsolidatedGroupName copy];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
- (NSUInteger)autoConsolidateGroupsThreshold
|
|
291
|
+
{
|
|
292
|
+
return autoConsolidateGroupsThreshold;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
- (NSString *)consolidatedGroupName
|
|
296
|
+
{
|
|
297
|
+
return consolidatedGroupName;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
301
|
+
#pragma mark Initialization & Updates
|
|
302
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
303
|
+
|
|
304
|
+
- (void)updateWithTransaction:(YapDatabaseReadTransaction *)transaction
|
|
305
|
+
{
|
|
306
|
+
if (![transaction->connection isInLongLivedReadTransaction])
|
|
307
|
+
{
|
|
308
|
+
NSString *reason = @"YapDatabaseViewMappings requires the connection to be in a longLivedReadTransaction.";
|
|
309
|
+
|
|
310
|
+
NSString *failureReason =
|
|
311
|
+
@"The architecture surrounding mappings is designed to move from one longLivedReadTransaction to another."
|
|
312
|
+
@" This allows you to freeze the data-source (databaseConnection) of your UI on a particular commit."
|
|
313
|
+
@" And then atomically move the data-source from an older commit to a newer commit in response to"
|
|
314
|
+
@" YapDatabaseModifiedNotifications. This ensures that the data-source for your UI remains in a steady"
|
|
315
|
+
@" state at all times, and that updates are properly handled using the appropriate update mechanisms"
|
|
316
|
+
@" (and properly animated if desired)."
|
|
317
|
+
@" For example code, please see the wiki: https://github.com/yaptv/YapDatabase/wiki/Views";
|
|
318
|
+
|
|
319
|
+
NSString *suggestion =
|
|
320
|
+
@"You must invoke [databaseConnection beginLongLivedReadTransaction] before you initialize the mappings";
|
|
321
|
+
|
|
322
|
+
NSDictionary *userInfo = @{
|
|
323
|
+
NSLocalizedFailureReasonErrorKey: failureReason,
|
|
324
|
+
NSLocalizedRecoverySuggestionErrorKey: suggestion };
|
|
325
|
+
|
|
326
|
+
// Here's what you SHOULD be doing: (correct)
|
|
327
|
+
//
|
|
328
|
+
// [databaseConnection beginLongLivedReadConnection];
|
|
329
|
+
// [databaseConnection readWithBlock:^(YapDatabaseConnectionReadTransaction *transaction){
|
|
330
|
+
// [mappings updateWithTransaction:transaction];
|
|
331
|
+
// }];
|
|
332
|
+
//
|
|
333
|
+
// Here's what you ARE doing: (wrong)
|
|
334
|
+
//
|
|
335
|
+
// [databaseConnection readWithBlock:^(YapDatabaseConnectionReadTransaction *transaction){
|
|
336
|
+
// [mappings updateWithTransaction:transaction];
|
|
337
|
+
// }];
|
|
338
|
+
// [databaseConnection beginLongLivedReadConnection];
|
|
339
|
+
//
|
|
340
|
+
//
|
|
341
|
+
// Warning: Do NOT, under any circumstance, comment out this exception.
|
|
342
|
+
|
|
343
|
+
@throw [NSException exceptionWithName:@"YapDatabaseException" reason:reason userInfo:userInfo];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
for (NSString *group in allGroups)
|
|
347
|
+
{
|
|
348
|
+
NSUInteger count = [[transaction ext:registeredViewName] numberOfKeysInGroup:group];
|
|
349
|
+
|
|
350
|
+
[counts setObject:@(count) forKey:group];
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
BOOL firstUpdate = (snapshotOfLastUpdate == UINT64_MAX);
|
|
354
|
+
snapshotOfLastUpdate = [transaction->connection snapshot];
|
|
355
|
+
|
|
356
|
+
if (firstUpdate)
|
|
357
|
+
[self initializeRangeOptsLength];
|
|
358
|
+
|
|
359
|
+
[self updateVisibility];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* This method is internal.
|
|
364
|
+
* It is only for use by the unit tests in TestViewChangeLogic.
|
|
365
|
+
**/
|
|
366
|
+
- (void)updateWithCounts:(NSDictionary *)newCounts
|
|
367
|
+
{
|
|
368
|
+
for (NSString *group in allGroups)
|
|
369
|
+
{
|
|
370
|
+
NSUInteger count = [[newCounts objectForKey:group] unsignedIntegerValue];
|
|
371
|
+
|
|
372
|
+
[counts setObject:@(count) forKey:group];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
BOOL firstUpdate = (snapshotOfLastUpdate == UINT64_MAX);
|
|
376
|
+
snapshotOfLastUpdate = 0;
|
|
377
|
+
|
|
378
|
+
if (firstUpdate)
|
|
379
|
+
[self initializeRangeOptsLength];
|
|
380
|
+
|
|
381
|
+
[self updateVisibility];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
- (void)initializeRangeOptsLength
|
|
385
|
+
{
|
|
386
|
+
NSAssert(snapshotOfLastUpdate != UINT64_MAX, @"The counts are needed to set rangeOpts.length");
|
|
387
|
+
|
|
388
|
+
for (NSString *group in [rangeOptions allKeys])
|
|
389
|
+
{
|
|
390
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
391
|
+
|
|
392
|
+
// Go through the internal setter again so all the logic is in the same place.
|
|
393
|
+
[self updateRangeOptions:rangeOpts forGroup:group];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
- (void)updateRangeOptions:(YapDatabaseViewRangeOptions *)rangeOpts forGroup:(NSString *)group
|
|
398
|
+
{
|
|
399
|
+
// Set a valid rangeOpts.length using the known group count
|
|
400
|
+
|
|
401
|
+
NSUInteger count = [[counts objectForKey:group] unsignedIntegerValue];
|
|
402
|
+
|
|
403
|
+
NSUInteger desiredLength = rangeOpts.length;
|
|
404
|
+
NSUInteger offset = rangeOpts.offset;
|
|
405
|
+
|
|
406
|
+
NSUInteger maxLength = (offset >= count) ? 0 : count - offset;
|
|
407
|
+
NSUInteger length = MIN(desiredLength, maxLength);
|
|
408
|
+
|
|
409
|
+
// Store private immutable copy
|
|
410
|
+
rangeOpts = [rangeOpts copyWithNewLength:length];
|
|
411
|
+
[rangeOptions setObject:rangeOpts forKey:group];
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* This method is used by YapDatabaseViewChange.
|
|
416
|
+
*
|
|
417
|
+
* After processing changeset(s), the length and/or offset may change.
|
|
418
|
+
* The new length and/or offsets are properly calculated,
|
|
419
|
+
* and then this method is used to avoid duplicating the calculations.
|
|
420
|
+
**/
|
|
421
|
+
- (void)updateRangeOptionsForGroup:(NSString *)group withNewLength:(NSUInteger)newLength newOffset:(NSUInteger)newOffset
|
|
422
|
+
{
|
|
423
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
424
|
+
rangeOpts = [rangeOpts copyWithNewLength:newLength newOffset:newOffset];
|
|
425
|
+
|
|
426
|
+
[rangeOptions setObject:rangeOpts forKey:group];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
- (void)updateVisibility
|
|
430
|
+
{
|
|
431
|
+
[visibleGroups removeAllObjects];
|
|
432
|
+
NSUInteger totalCount = 0;
|
|
433
|
+
|
|
434
|
+
for (NSString *group in allGroups)
|
|
435
|
+
{
|
|
436
|
+
NSUInteger count;
|
|
437
|
+
|
|
438
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
439
|
+
if (rangeOpts)
|
|
440
|
+
count = rangeOpts.length;
|
|
441
|
+
else
|
|
442
|
+
count = [[counts objectForKey:group] unsignedIntegerValue];
|
|
443
|
+
|
|
444
|
+
if (count > 0 || ![dynamicSections containsObject:group]) {
|
|
445
|
+
[visibleGroups addObject:group];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
totalCount += count;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (totalCount < autoConsolidateGroupsThreshold)
|
|
452
|
+
isUsingConsolidatedGroup = YES;
|
|
453
|
+
else
|
|
454
|
+
isUsingConsolidatedGroup = NO;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
458
|
+
#pragma mark Internal
|
|
459
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
460
|
+
|
|
461
|
+
- (NSMutableDictionary *)counts
|
|
462
|
+
{
|
|
463
|
+
return [counts mutableCopy];
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
- (NSUInteger)fullCountForGroup:(NSString *)group
|
|
467
|
+
{
|
|
468
|
+
return [[counts objectForKey:group] unsignedIntegerValue];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
- (NSUInteger)visibleCountForGroup:(NSString *)group
|
|
472
|
+
{
|
|
473
|
+
return [self numberOfItemsInGroup:group];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
- (NSDictionary *)rangeOptions
|
|
477
|
+
{
|
|
478
|
+
return [rangeOptions copy];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
- (NSDictionary *)dependencies
|
|
482
|
+
{
|
|
483
|
+
return [dependencies copy];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
- (NSSet *)reverse
|
|
487
|
+
{
|
|
488
|
+
return [reverse copy];
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
- (void)setAutoConsolidatingDisabled:(BOOL)disabled
|
|
492
|
+
{
|
|
493
|
+
autoConsolidationDisabled = disabled;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
497
|
+
#pragma mark Getters
|
|
498
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Returns the actual number of visible sections.
|
|
502
|
+
*
|
|
503
|
+
* This number may be less than the original count of groups passed in the init method.
|
|
504
|
+
* That is, if dynamic sections are enabled for one or more groups, and some of these groups have zero items,
|
|
505
|
+
* then those groups will be removed from the visible list of groups. And thus the section count may be less.
|
|
506
|
+
**/
|
|
507
|
+
- (NSUInteger)numberOfSections
|
|
508
|
+
{
|
|
509
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
510
|
+
return 1;
|
|
511
|
+
else
|
|
512
|
+
return [visibleGroups count];
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Returns the number of items in the given section.
|
|
517
|
+
* @see groupForSection
|
|
518
|
+
**/
|
|
519
|
+
- (NSUInteger)numberOfItemsInSection:(NSUInteger)section
|
|
520
|
+
{
|
|
521
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
522
|
+
return [self numberOfItemsInAllGroups];
|
|
523
|
+
else
|
|
524
|
+
return [self numberOfItemsInGroup:[self groupForSection:section]];
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Returns the number of items in the given group.
|
|
529
|
+
*
|
|
530
|
+
* This is the cached value from the last time one of the following methods was invoked:
|
|
531
|
+
* - updateWithTransaction:
|
|
532
|
+
* - changesForNotifications:withMappings:
|
|
533
|
+
**/
|
|
534
|
+
- (NSUInteger)numberOfItemsInGroup:(NSString *)group
|
|
535
|
+
{
|
|
536
|
+
if (group == nil) return 0;
|
|
537
|
+
if (snapshotOfLastUpdate == UINT64_MAX) return 0;
|
|
538
|
+
|
|
539
|
+
if (isUsingConsolidatedGroup && [consolidatedGroupName isEqualToString:group])
|
|
540
|
+
{
|
|
541
|
+
return [self numberOfItemsInAllGroups];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
545
|
+
if (rangeOpts)
|
|
546
|
+
{
|
|
547
|
+
return rangeOpts.length;
|
|
548
|
+
}
|
|
549
|
+
else
|
|
550
|
+
{
|
|
551
|
+
return [[counts objectForKey:group] unsignedIntegerValue];
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* The visibleGroups property returns the current sections setup.
|
|
557
|
+
* That is, it only contains the visible groups that are being represented as sections in the view.
|
|
558
|
+
*
|
|
559
|
+
* If all sections are static, then visibleGroups will always be the same as allGroups.
|
|
560
|
+
* However, if one or more sections are dynamic, then the visible groups may be a subset of allGroups.
|
|
561
|
+
*
|
|
562
|
+
* Dynamic groups/sections automatically "disappear" if/when they become empty.
|
|
563
|
+
**/
|
|
564
|
+
- (NSArray *)visibleGroups
|
|
565
|
+
{
|
|
566
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
567
|
+
return [NSArray arrayWithObjects:consolidatedGroupName, nil];
|
|
568
|
+
else
|
|
569
|
+
return [visibleGroups copy];
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Returns YES if there are zero items in all sections/groups.
|
|
574
|
+
**/
|
|
575
|
+
- (BOOL)isEmpty
|
|
576
|
+
{
|
|
577
|
+
if (snapshotOfLastUpdate == UINT64_MAX) return YES;
|
|
578
|
+
|
|
579
|
+
for (NSString *group in visibleGroups) // NOT [self visibleGroups]
|
|
580
|
+
{
|
|
581
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
582
|
+
if (rangeOpts)
|
|
583
|
+
{
|
|
584
|
+
if (rangeOpts.length > 0)
|
|
585
|
+
return NO;
|
|
586
|
+
}
|
|
587
|
+
else
|
|
588
|
+
{
|
|
589
|
+
if ([[counts objectForKey:group] unsignedIntegerValue] > 0)
|
|
590
|
+
return NO;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return YES;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
598
|
+
#pragma mark Mapping UI -> View
|
|
599
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Maps from a section (in the UI) to a group (in the View).
|
|
603
|
+
*
|
|
604
|
+
* Returns the group for the given section.
|
|
605
|
+
* This method properly takes into account dynamic groups.
|
|
606
|
+
*
|
|
607
|
+
* If the section is out-of-bounds, returns nil.
|
|
608
|
+
**/
|
|
609
|
+
- (NSString *)groupForSection:(NSUInteger)section
|
|
610
|
+
{
|
|
611
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
612
|
+
{
|
|
613
|
+
if (section == 0)
|
|
614
|
+
return consolidatedGroupName;
|
|
615
|
+
else
|
|
616
|
+
return nil;
|
|
617
|
+
}
|
|
618
|
+
else
|
|
619
|
+
{
|
|
620
|
+
if (section < [visibleGroups count])
|
|
621
|
+
return [visibleGroups objectAtIndex:section];
|
|
622
|
+
else
|
|
623
|
+
return nil;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Maps from an indexPath (in the UI) to a group & index (within the View).
|
|
629
|
+
*
|
|
630
|
+
* When using rangeOptions, the rows in your tableView/collectionView may not
|
|
631
|
+
* directly match the index in the corresponding view & group.
|
|
632
|
+
*
|
|
633
|
+
* For example, say a view has a group named "elders" and contains 100 items.
|
|
634
|
+
* A fixed range is used to display only the last 20 items in the "elders" group (the 20 oldest elders).
|
|
635
|
+
* Thus row zero in the tableView is actually index 80 in the "elders" group.
|
|
636
|
+
*
|
|
637
|
+
* This method maps from an indexPath in the UI to the corresponding indexes and groups in the view.
|
|
638
|
+
*
|
|
639
|
+
* That is, you pass in an indexPath or row & section from the UI perspective,
|
|
640
|
+
* and it spits out the corresponding index within the view's group.
|
|
641
|
+
*
|
|
642
|
+
* For example:
|
|
643
|
+
*
|
|
644
|
+
* - (UITableViewCell *)tableView:(UITableView *)sender cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
645
|
+
* {
|
|
646
|
+
* NSString *group = nil;
|
|
647
|
+
* NSUInteger groupIndex = 0;
|
|
648
|
+
*
|
|
649
|
+
* [mappings getGroup:&group index:&groupIndex forIndexPath:indexPath];
|
|
650
|
+
*
|
|
651
|
+
* __block Elder *elder = nil;
|
|
652
|
+
* [databaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
653
|
+
*
|
|
654
|
+
* elder = [[transaction extension:@"elders"] objectAtIndex:groupIndex inGroup:group];
|
|
655
|
+
* }];
|
|
656
|
+
*
|
|
657
|
+
* // configure and return cell...
|
|
658
|
+
* }
|
|
659
|
+
**/
|
|
660
|
+
- (BOOL)getGroup:(NSString **)groupPtr index:(NSUInteger *)indexPtr forIndexPath:(NSIndexPath *)indexPath
|
|
661
|
+
{
|
|
662
|
+
if (indexPath == nil)
|
|
663
|
+
{
|
|
664
|
+
if (groupPtr) *groupPtr = nil;
|
|
665
|
+
if (indexPtr) *indexPtr = NSNotFound;
|
|
666
|
+
|
|
667
|
+
return NO;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
#if TARGET_OS_IPHONE
|
|
671
|
+
NSUInteger section = indexPath.section;
|
|
672
|
+
NSUInteger row = indexPath.row;
|
|
673
|
+
#else
|
|
674
|
+
NSUInteger section = [indexPath indexAtPosition:0];
|
|
675
|
+
NSUInteger row = [indexPath indexAtPosition:1];
|
|
676
|
+
#endif
|
|
677
|
+
|
|
678
|
+
return [self getGroup:groupPtr index:indexPtr forRow:row inSection:section];
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Maps from an indexPath (in the UI) to a group & index (within the View).
|
|
683
|
+
*
|
|
684
|
+
* When your UI doesn't exactly match up with the View in the database, this method does all the math for you.
|
|
685
|
+
*
|
|
686
|
+
* For example, if using rangeOptions, the rows in your tableView/collectionView may not
|
|
687
|
+
* directly match the index in the corresponding view & group (in the database).
|
|
688
|
+
*
|
|
689
|
+
* For example, say a view in the database has a group named "elders" and contains 100 items.
|
|
690
|
+
* A fixed range is used to display only the last 20 items in the "elders" group (the 20 oldest elders).
|
|
691
|
+
* Thus row zero in the tableView is actually index 80 in the "elders" group.
|
|
692
|
+
*
|
|
693
|
+
* So you pass in an indexPath or row & section from the UI perspective,
|
|
694
|
+
* and it spits out the corresponding index within the database view's group.
|
|
695
|
+
*
|
|
696
|
+
* Code sample:
|
|
697
|
+
*
|
|
698
|
+
* - (UITableViewCell *)tableView:(UITableView *)sender cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
699
|
+
* {
|
|
700
|
+
* NSString *group = nil;
|
|
701
|
+
* NSUInteger groupIndex = 0;
|
|
702
|
+
*
|
|
703
|
+
* [mappings getGroup:&group index:&groupIndex forIndexPath:indexPath];
|
|
704
|
+
*
|
|
705
|
+
* __block Elder *elder = nil;
|
|
706
|
+
* [databaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
707
|
+
*
|
|
708
|
+
* elder = [[transaction extension:@"elders"] objectAtIndex:groupIndex inGroup:group];
|
|
709
|
+
* }];
|
|
710
|
+
*
|
|
711
|
+
* // configure and return cell...
|
|
712
|
+
* }
|
|
713
|
+
**/
|
|
714
|
+
- (BOOL)getGroup:(NSString **)groupPtr
|
|
715
|
+
index:(NSUInteger *)indexPtr
|
|
716
|
+
forRow:(NSUInteger)row
|
|
717
|
+
inSection:(NSUInteger)section
|
|
718
|
+
{
|
|
719
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
720
|
+
{
|
|
721
|
+
if (section == 0)
|
|
722
|
+
{
|
|
723
|
+
return [self getGroup:groupPtr index:indexPtr forConsolidatedRow:row];
|
|
724
|
+
}
|
|
725
|
+
else
|
|
726
|
+
{
|
|
727
|
+
if (groupPtr) *groupPtr = nil;
|
|
728
|
+
if (indexPtr) *indexPtr = NSNotFound;
|
|
729
|
+
|
|
730
|
+
return NO;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
else
|
|
734
|
+
{
|
|
735
|
+
NSString *group = [self groupForSection:section];
|
|
736
|
+
if (group == nil)
|
|
737
|
+
{
|
|
738
|
+
if (groupPtr) *groupPtr = nil;
|
|
739
|
+
if (indexPtr) *indexPtr = NSNotFound;
|
|
740
|
+
|
|
741
|
+
return NO;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
NSUInteger index = [self indexForRow:row inGroup:group];
|
|
745
|
+
|
|
746
|
+
if (groupPtr) *groupPtr = group;
|
|
747
|
+
if (indexPtr) *indexPtr = index;
|
|
748
|
+
|
|
749
|
+
return (index != NSNotFound);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Maps from a row & section (in the UI) to an index (within the View).
|
|
755
|
+
*
|
|
756
|
+
* This method is shorthand for getGroup:index:forIndexPath: when you already know the group.
|
|
757
|
+
* @see getGroup:index:forIndexPath:
|
|
758
|
+
**/
|
|
759
|
+
- (NSUInteger)indexForRow:(NSUInteger)row inSection:(NSUInteger)section
|
|
760
|
+
{
|
|
761
|
+
return [self indexForRow:row inGroup:[self groupForSection:section]];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Maps from a row & section (in the UI) to an index (within the View).
|
|
766
|
+
*
|
|
767
|
+
* This method is shorthand for getGroup:index:forIndexPath: when you already know the group.
|
|
768
|
+
* @see getGroup:index:forIndexPath:
|
|
769
|
+
**/
|
|
770
|
+
- (NSUInteger)indexForRow:(NSUInteger)row inGroup:(NSString *)group
|
|
771
|
+
{
|
|
772
|
+
if (group == nil) return NSNotFound;
|
|
773
|
+
|
|
774
|
+
if (isUsingConsolidatedGroup && [group isEqualToString:consolidatedGroupName])
|
|
775
|
+
{
|
|
776
|
+
NSUInteger index = 0;
|
|
777
|
+
if ([self getGroup:NULL index:&index forConsolidatedRow:row])
|
|
778
|
+
return index;
|
|
779
|
+
else
|
|
780
|
+
return NSNotFound;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
NSUInteger visibleCount = [self visibleCountForGroup:group];
|
|
784
|
+
if (row >= visibleCount)
|
|
785
|
+
return NSNotFound;
|
|
786
|
+
|
|
787
|
+
BOOL needsReverse = [reverse containsObject:group];
|
|
788
|
+
|
|
789
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
790
|
+
if (rangeOpts)
|
|
791
|
+
{
|
|
792
|
+
if (rangeOpts.pin == YapDatabaseViewBeginning)
|
|
793
|
+
{
|
|
794
|
+
// rangeOpts.offset is from beginning (index zero)
|
|
795
|
+
|
|
796
|
+
if (needsReverse)
|
|
797
|
+
{
|
|
798
|
+
NSUInteger upperBound = rangeOpts.offset + rangeOpts.length - 1;
|
|
799
|
+
return upperBound - row;
|
|
800
|
+
}
|
|
801
|
+
else
|
|
802
|
+
{
|
|
803
|
+
return rangeOpts.offset + row;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
else // if (rangeOpts.pin == YapDatabaseViewEnd)
|
|
807
|
+
{
|
|
808
|
+
// rangeOpts.offset is from end (index last)
|
|
809
|
+
|
|
810
|
+
NSUInteger fullCount = [self fullCountForGroup:group];
|
|
811
|
+
|
|
812
|
+
if (needsReverse)
|
|
813
|
+
{
|
|
814
|
+
NSUInteger upperBound = fullCount - rangeOpts.offset - 1;
|
|
815
|
+
return upperBound - row;
|
|
816
|
+
}
|
|
817
|
+
else
|
|
818
|
+
{
|
|
819
|
+
NSUInteger lowerBound = fullCount - rangeOpts.offset - rangeOpts.length;
|
|
820
|
+
return lowerBound + row;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
else
|
|
825
|
+
{
|
|
826
|
+
if (needsReverse)
|
|
827
|
+
{
|
|
828
|
+
NSUInteger fullCount = [self fullCountForGroup:group];
|
|
829
|
+
return fullCount - row - 1;
|
|
830
|
+
}
|
|
831
|
+
else
|
|
832
|
+
{
|
|
833
|
+
return row;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Use this method to extract the true group & index from a row in the consolidatedGroup.
|
|
840
|
+
*
|
|
841
|
+
* view = @{
|
|
842
|
+
* @"A" = @[ @"Alice" ]
|
|
843
|
+
* @"B" = @[ @"Barney", @"Bob" ]
|
|
844
|
+
* @"C" = @[ @"Chris" ]
|
|
845
|
+
* }
|
|
846
|
+
* mappings.isUsingConsolidateGroup == YES
|
|
847
|
+
*
|
|
848
|
+
* NSString *group = nil;
|
|
849
|
+
* NSUInteger index = 0;
|
|
850
|
+
*
|
|
851
|
+
* [mappings getGroup:&group index:&index forConsolidatedRow:2];
|
|
852
|
+
*
|
|
853
|
+
* // group = @"B"
|
|
854
|
+
* // index = 1 (Bob)
|
|
855
|
+
*
|
|
856
|
+
* [mappings getGroup:&group index:&index forConsolidatedRow:3];
|
|
857
|
+
*
|
|
858
|
+
* // group = @"C"
|
|
859
|
+
* // index = 0 (Chris)
|
|
860
|
+
**/
|
|
861
|
+
- (BOOL)getGroup:(NSString **)groupPtr index:(NSUInteger *)indexPtr forConsolidatedRow:(NSUInteger)row
|
|
862
|
+
{
|
|
863
|
+
NSUInteger offset = 0;
|
|
864
|
+
|
|
865
|
+
for (NSString *group in visibleGroups) // NOT [self visibleGroups]
|
|
866
|
+
{
|
|
867
|
+
NSUInteger count = [self visibleCountForGroup:group];
|
|
868
|
+
|
|
869
|
+
if ((row < (offset + count)) && (count > 0))
|
|
870
|
+
{
|
|
871
|
+
NSUInteger index = [self indexForRow:(row - offset) inGroup:group];
|
|
872
|
+
|
|
873
|
+
if (groupPtr) *groupPtr = group;
|
|
874
|
+
if (indexPtr) *indexPtr = index;
|
|
875
|
+
|
|
876
|
+
return YES;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
offset += count;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (groupPtr) *groupPtr = nil;
|
|
883
|
+
if (indexPtr) *indexPtr = 0;
|
|
884
|
+
return NO;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
888
|
+
#pragma mark Mapping View -> UI
|
|
889
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Maps from a group (in the View) to the corresponding section (in the UI).
|
|
893
|
+
*
|
|
894
|
+
* Returns the visible section number for the visible group.
|
|
895
|
+
* If the group is NOT visible, returns NSNotFound.
|
|
896
|
+
* If the group is NOT valid, returns NSNotFound.
|
|
897
|
+
**/
|
|
898
|
+
- (NSUInteger)sectionForGroup:(NSString *)group
|
|
899
|
+
{
|
|
900
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
901
|
+
{
|
|
902
|
+
if ([consolidatedGroupName isEqualToString:group])
|
|
903
|
+
return 0;
|
|
904
|
+
|
|
905
|
+
// The thought process here is that the group may be technically visible.
|
|
906
|
+
// It's just that its consolidated into a bigger group.
|
|
907
|
+
|
|
908
|
+
for (NSString *visibleGroup in visibleGroups)
|
|
909
|
+
{
|
|
910
|
+
if ([visibleGroup isEqualToString:group])
|
|
911
|
+
{
|
|
912
|
+
return 0;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
return NSNotFound;
|
|
917
|
+
}
|
|
918
|
+
else
|
|
919
|
+
{
|
|
920
|
+
NSUInteger section = 0;
|
|
921
|
+
for (NSString *visibleGroup in visibleGroups)
|
|
922
|
+
{
|
|
923
|
+
if ([visibleGroup isEqualToString:group])
|
|
924
|
+
{
|
|
925
|
+
return section;
|
|
926
|
+
}
|
|
927
|
+
section++;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
return NSNotFound;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Maps from an index & group (in the View) to the corresponding row & section (in the UI).
|
|
936
|
+
*
|
|
937
|
+
* Returns YES if the proper row & section were found.
|
|
938
|
+
* Returns NO if the given index is NOT visible (or out-of-bounds).
|
|
939
|
+
* Returns NO if the given group is NOT visible (or invalid).
|
|
940
|
+
**/
|
|
941
|
+
- (BOOL)getRow:(NSUInteger *)rowPtr
|
|
942
|
+
section:(NSUInteger *)sectionPtr
|
|
943
|
+
forIndex:(NSUInteger)index
|
|
944
|
+
inGroup:(NSString *)group
|
|
945
|
+
{
|
|
946
|
+
if (isUsingConsolidatedGroup && !autoConsolidationDisabled)
|
|
947
|
+
{
|
|
948
|
+
NSUInteger row = 0;
|
|
949
|
+
if ([self getConsolidatedRow:&row forIndex:index inGroup:group])
|
|
950
|
+
{
|
|
951
|
+
if (rowPtr) *rowPtr = row;
|
|
952
|
+
if (sectionPtr) *sectionPtr = 0;
|
|
953
|
+
|
|
954
|
+
return YES;
|
|
955
|
+
}
|
|
956
|
+
else
|
|
957
|
+
{
|
|
958
|
+
if (rowPtr) *rowPtr = 0;
|
|
959
|
+
if (sectionPtr) *sectionPtr = 0;
|
|
960
|
+
|
|
961
|
+
return NO;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
else
|
|
965
|
+
{
|
|
966
|
+
NSUInteger section = [self sectionForGroup:group];
|
|
967
|
+
if (section == NSNotFound)
|
|
968
|
+
{
|
|
969
|
+
if (rowPtr) *rowPtr = 0;
|
|
970
|
+
if (sectionPtr) *sectionPtr = 0;
|
|
971
|
+
|
|
972
|
+
return NO;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
NSUInteger row = [self rowForIndex:index inGroup:group];
|
|
976
|
+
if (row == NSNotFound)
|
|
977
|
+
{
|
|
978
|
+
if (rowPtr) *rowPtr = 0;
|
|
979
|
+
if (sectionPtr) *sectionPtr = 0;
|
|
980
|
+
|
|
981
|
+
return NO;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
if (rowPtr) *rowPtr = row;
|
|
985
|
+
if (sectionPtr) *sectionPtr = section;
|
|
986
|
+
|
|
987
|
+
return YES;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Maps from an index & group (in the View) to the corresponding indexPath (in the UI).
|
|
993
|
+
*
|
|
994
|
+
* Returns the indexPath with the proper section and row.
|
|
995
|
+
* Returns nil if the group is NOT visible (or invalid).
|
|
996
|
+
* Returns nil if the index is NOT visible (or out-of-bounds).
|
|
997
|
+
**/
|
|
998
|
+
- (NSIndexPath *)indexPathForIndex:(NSUInteger)index inGroup:(NSString *)group
|
|
999
|
+
{
|
|
1000
|
+
NSUInteger row = 0;
|
|
1001
|
+
NSUInteger section = 0;
|
|
1002
|
+
|
|
1003
|
+
if ([self getRow:&row section:§ion forIndex:index inGroup:group])
|
|
1004
|
+
{
|
|
1005
|
+
#if TARGET_OS_IPHONE
|
|
1006
|
+
return [NSIndexPath indexPathForRow:row inSection:section];
|
|
1007
|
+
#else
|
|
1008
|
+
NSUInteger indexes[] = {section, row};
|
|
1009
|
+
return [NSIndexPath indexPathWithIndexes:indexes length:2];
|
|
1010
|
+
#endif
|
|
1011
|
+
}
|
|
1012
|
+
else
|
|
1013
|
+
{
|
|
1014
|
+
return nil;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Maps from an index & group (in the View) to the corresponding row (in the UI).
|
|
1020
|
+
*
|
|
1021
|
+
* This method is shorthand for getRow:section:forIndex:inGroup: when you already know the section.
|
|
1022
|
+
* @see getRow:section:forIndex:inGroup:
|
|
1023
|
+
**/
|
|
1024
|
+
- (NSUInteger)rowForIndex:(NSUInteger)index inGroup:(NSString *)group
|
|
1025
|
+
{
|
|
1026
|
+
if (group == nil) return NSNotFound;
|
|
1027
|
+
|
|
1028
|
+
if (isUsingConsolidatedGroup && [consolidatedGroupName isEqualToString:group])
|
|
1029
|
+
{
|
|
1030
|
+
NSUInteger row = 0;
|
|
1031
|
+
if ([self getConsolidatedRow:&row forIndex:index inGroup:group])
|
|
1032
|
+
return row;
|
|
1033
|
+
else
|
|
1034
|
+
return NSNotFound;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
NSUInteger fullCount = [self fullCountForGroup:group];
|
|
1038
|
+
if (index >= fullCount)
|
|
1039
|
+
return NSNotFound;
|
|
1040
|
+
|
|
1041
|
+
BOOL needsReverse = [reverse containsObject:group];
|
|
1042
|
+
|
|
1043
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
1044
|
+
if (rangeOpts)
|
|
1045
|
+
{
|
|
1046
|
+
if (rangeOpts.pin == YapDatabaseViewBeginning)
|
|
1047
|
+
{
|
|
1048
|
+
// rangeOpts.offset is from beginning (index zero)
|
|
1049
|
+
|
|
1050
|
+
if (index < rangeOpts.offset)
|
|
1051
|
+
return NSNotFound;
|
|
1052
|
+
|
|
1053
|
+
NSUInteger row = index - rangeOpts.offset;
|
|
1054
|
+
|
|
1055
|
+
NSUInteger visibleCount = [self visibleCountForGroup:group];
|
|
1056
|
+
if (row >= visibleCount)
|
|
1057
|
+
return NSNotFound;
|
|
1058
|
+
|
|
1059
|
+
if (needsReverse)
|
|
1060
|
+
return visibleCount - row - 1;
|
|
1061
|
+
else
|
|
1062
|
+
return row;
|
|
1063
|
+
}
|
|
1064
|
+
else // if (rangeOpts.pin == YapDatabaseViewEnd)
|
|
1065
|
+
{
|
|
1066
|
+
// rangeOpts.offset is from end (index last)
|
|
1067
|
+
|
|
1068
|
+
NSUInteger visibleCount = [self visibleCountForGroup:group];
|
|
1069
|
+
|
|
1070
|
+
NSUInteger upperBound = fullCount - rangeOpts.offset - 1;
|
|
1071
|
+
if (index > upperBound)
|
|
1072
|
+
return NSNotFound;
|
|
1073
|
+
|
|
1074
|
+
NSUInteger lowerBound = upperBound - visibleCount + 1;
|
|
1075
|
+
if (index < lowerBound)
|
|
1076
|
+
return NSNotFound;
|
|
1077
|
+
|
|
1078
|
+
if (needsReverse)
|
|
1079
|
+
return upperBound - index;
|
|
1080
|
+
else
|
|
1081
|
+
return index - lowerBound;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
else
|
|
1085
|
+
{
|
|
1086
|
+
if (needsReverse)
|
|
1087
|
+
return fullCount - index - 1; // we know fullCount > 0
|
|
1088
|
+
else
|
|
1089
|
+
return index;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* Use this method to extract the true row (in the consolidatedGroup) for a given group & index in the database.
|
|
1095
|
+
**/
|
|
1096
|
+
- (BOOL)getConsolidatedRow:(NSUInteger *)rowPtr forIndex:(NSUInteger)index inGroup:(NSString *)group
|
|
1097
|
+
{
|
|
1098
|
+
NSUInteger groupOffset = 0;
|
|
1099
|
+
|
|
1100
|
+
for (NSString *visibleGroup in visibleGroups)
|
|
1101
|
+
{
|
|
1102
|
+
if ([visibleGroup isEqualToString:group])
|
|
1103
|
+
{
|
|
1104
|
+
NSUInteger row = [self rowForIndex:index inGroup:group];
|
|
1105
|
+
|
|
1106
|
+
if (row == NSNotFound)
|
|
1107
|
+
{
|
|
1108
|
+
if (rowPtr) *rowPtr = 0;
|
|
1109
|
+
return NO;
|
|
1110
|
+
}
|
|
1111
|
+
else
|
|
1112
|
+
{
|
|
1113
|
+
if (rowPtr) *rowPtr = (groupOffset + row);
|
|
1114
|
+
return YES;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
else
|
|
1118
|
+
{
|
|
1119
|
+
groupOffset += [self visibleCountForGroup:visibleGroup];
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
if (rowPtr) *rowPtr = 0;
|
|
1124
|
+
return NO;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1128
|
+
#pragma mark Getters + RangeOptions
|
|
1129
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* The YapDatabaseViewRangePosition struct represents the range window within the full group.
|
|
1133
|
+
* For example:
|
|
1134
|
+
*
|
|
1135
|
+
* You have a section in your tableView which represents a group that contains 100 items.
|
|
1136
|
+
* However, you've setup rangeOptions to only display the first 20 items:
|
|
1137
|
+
*
|
|
1138
|
+
* YapDatabaseViewRangeOptions *rangeOptions =
|
|
1139
|
+
* [YapDatabaseViewRangeOptions fixedRangeWithLength:20 offset:0 from:YapDatabaseViewBeginning];
|
|
1140
|
+
* [mappings setRangeOptions:rangeOptions forGroup:@"sales"];
|
|
1141
|
+
*
|
|
1142
|
+
* The corresponding rangePosition would be: (YapDatabaseViewRangePosition){
|
|
1143
|
+
* .offsetFromBeginning = 0,
|
|
1144
|
+
* .offsetFromEnd = 80,
|
|
1145
|
+
* .length = 20
|
|
1146
|
+
* }
|
|
1147
|
+
**/
|
|
1148
|
+
- (YapDatabaseViewRangePosition)rangePositionForGroup:(NSString *)group
|
|
1149
|
+
{
|
|
1150
|
+
if (group == nil || [consolidatedGroupName isEqualToString:group])
|
|
1151
|
+
{
|
|
1152
|
+
return (YapDatabaseViewRangePosition){
|
|
1153
|
+
.offsetFromBeginning = 0,
|
|
1154
|
+
.offsetFromEnd = 0,
|
|
1155
|
+
.length = 0
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
NSUInteger groupCount = [[counts objectForKey:group] unsignedIntegerValue];
|
|
1160
|
+
|
|
1161
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
1162
|
+
YapDatabaseViewRangePosition rangePosition;
|
|
1163
|
+
|
|
1164
|
+
if (rangeOpts)
|
|
1165
|
+
{
|
|
1166
|
+
NSUInteger rangeOffset = rangeOpts.offset;
|
|
1167
|
+
NSUInteger rangeLength = rangeOpts.length;
|
|
1168
|
+
|
|
1169
|
+
if (rangeOpts.pin == YapDatabaseViewBeginning)
|
|
1170
|
+
{
|
|
1171
|
+
// Offset is from beginning (index zero)
|
|
1172
|
+
|
|
1173
|
+
NSUInteger reverseOffset = rangeOffset + rangeLength;
|
|
1174
|
+
|
|
1175
|
+
if (reverseOffset <= groupCount)
|
|
1176
|
+
{
|
|
1177
|
+
// Valid range
|
|
1178
|
+
|
|
1179
|
+
rangePosition = (YapDatabaseViewRangePosition){
|
|
1180
|
+
.offsetFromBeginning = rangeOffset,
|
|
1181
|
+
.offsetFromEnd = groupCount - reverseOffset,
|
|
1182
|
+
.length = rangeLength
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
else
|
|
1186
|
+
{
|
|
1187
|
+
// Range fell off the backside
|
|
1188
|
+
|
|
1189
|
+
rangePosition = (YapDatabaseViewRangePosition){
|
|
1190
|
+
.offsetFromBeginning = rangeOffset,
|
|
1191
|
+
.offsetFromEnd = 0,
|
|
1192
|
+
.length = 0
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
else
|
|
1197
|
+
{
|
|
1198
|
+
// Offset is from end (index last)
|
|
1199
|
+
|
|
1200
|
+
NSUInteger reverseOffset = rangeOffset + rangeLength;
|
|
1201
|
+
|
|
1202
|
+
if (reverseOffset <= groupCount)
|
|
1203
|
+
{
|
|
1204
|
+
// Valid range
|
|
1205
|
+
|
|
1206
|
+
rangePosition = (YapDatabaseViewRangePosition){
|
|
1207
|
+
.offsetFromBeginning = groupCount - reverseOffset,
|
|
1208
|
+
.offsetFromEnd = rangeOffset,
|
|
1209
|
+
.length = rangeLength
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
else
|
|
1213
|
+
{
|
|
1214
|
+
// Range fell off the backside
|
|
1215
|
+
|
|
1216
|
+
rangePosition = (YapDatabaseViewRangePosition){
|
|
1217
|
+
.offsetFromBeginning = 0,
|
|
1218
|
+
.offsetFromEnd = rangeOffset,
|
|
1219
|
+
.length = 0,
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
else
|
|
1225
|
+
{
|
|
1226
|
+
rangePosition = (YapDatabaseViewRangePosition){
|
|
1227
|
+
.offsetFromBeginning = 0,
|
|
1228
|
+
.offsetFromEnd = 0,
|
|
1229
|
+
.length = groupCount
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
if ([reverse containsObject:group])
|
|
1234
|
+
{
|
|
1235
|
+
NSUInteger swap = rangePosition.offsetFromEnd;
|
|
1236
|
+
rangePosition.offsetFromEnd = rangePosition.offsetFromBeginning;
|
|
1237
|
+
rangePosition.offsetFromBeginning = swap;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
return rangePosition;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1244
|
+
#pragma mark Getters + Consolidation
|
|
1245
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1246
|
+
|
|
1247
|
+
- (BOOL)isUsingConsolidatedGroup
|
|
1248
|
+
{
|
|
1249
|
+
return isUsingConsolidatedGroup;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Returns the total number of items by summing up the totals across all groups.
|
|
1254
|
+
**/
|
|
1255
|
+
- (NSUInteger)numberOfItemsInAllGroups
|
|
1256
|
+
{
|
|
1257
|
+
if (snapshotOfLastUpdate == UINT64_MAX) return 0;
|
|
1258
|
+
|
|
1259
|
+
NSUInteger total = 0;
|
|
1260
|
+
|
|
1261
|
+
for (NSString *group in visibleGroups) // NOT [self visibleGroups]
|
|
1262
|
+
{
|
|
1263
|
+
YapDatabaseViewRangeOptions *rangeOpts = [rangeOptions objectForKey:group];
|
|
1264
|
+
if (rangeOpts)
|
|
1265
|
+
{
|
|
1266
|
+
total += rangeOpts.length;
|
|
1267
|
+
}
|
|
1268
|
+
else
|
|
1269
|
+
{
|
|
1270
|
+
total += [[counts objectForKey:group] unsignedIntegerValue];
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
return total;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1278
|
+
#pragma mark Getters + Utilities
|
|
1279
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* This is a helper method to assist in maintaining the selection while updating the tableView/collectionView.
|
|
1283
|
+
* In general the idea is this:
|
|
1284
|
+
* - yapDatabaseModified is invoked on the main thread
|
|
1285
|
+
* - at the beginning of the method, you grab some information about the current selection
|
|
1286
|
+
* - you update the database connection, and then start the animation for the changes to the table
|
|
1287
|
+
* - you reselect whatever was previously selected
|
|
1288
|
+
* - if that's not possible (row was deleted) then you select the closest row to the previous selection
|
|
1289
|
+
*
|
|
1290
|
+
* The last step isn't always what you want to do. Maybe you don't want to select anything at that point.
|
|
1291
|
+
* But if you do, then this method can simplify the task for you.
|
|
1292
|
+
* It figures out what the closest row is, even if it's in a different section.
|
|
1293
|
+
*
|
|
1294
|
+
* Code example:
|
|
1295
|
+
*
|
|
1296
|
+
* - (void)yapDatabaseModified:(NSNotification *)notification {
|
|
1297
|
+
*
|
|
1298
|
+
* // Grab info about current selection
|
|
1299
|
+
*
|
|
1300
|
+
* NSString *selectedGroup = nil;
|
|
1301
|
+
* NSUInteger selectedRow = 0;
|
|
1302
|
+
* __block NSString *selectedWidgetId = nil;
|
|
1303
|
+
*
|
|
1304
|
+
* NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
|
|
1305
|
+
* if (selectedIndexPath) {
|
|
1306
|
+
* selectedGroup = [mappings groupForSection:selectedIndexPath.section];
|
|
1307
|
+
* selectedRow = selectedIndexPath.row;
|
|
1308
|
+
*
|
|
1309
|
+
* [databaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
1310
|
+
* selectedWidgetId = [[transaction ext:@"widgets"] keyAtIndex:selectedRow inGroup:selectedGroup];
|
|
1311
|
+
* }];
|
|
1312
|
+
* }
|
|
1313
|
+
*
|
|
1314
|
+
* // Update the database connection (move it to the latest commit)
|
|
1315
|
+
*
|
|
1316
|
+
* NSArray *notifications = [databaseConnection beginLongLivedReadTransaction];
|
|
1317
|
+
*
|
|
1318
|
+
* // Process the notification(s),
|
|
1319
|
+
* // and get the changeset as it applies to me, based on my view and my mappings setup.
|
|
1320
|
+
*
|
|
1321
|
+
* NSArray *sectionChanges = nil;
|
|
1322
|
+
* NSArray *rowChanges = nil;
|
|
1323
|
+
*
|
|
1324
|
+
* [[databaseConnection ext:@"order"] getSectionChanges:§ionChanges
|
|
1325
|
+
* rowChanges:&rowChanges
|
|
1326
|
+
* forNotifications:notifications
|
|
1327
|
+
* withMappings:mappings];
|
|
1328
|
+
*
|
|
1329
|
+
* if ([sectionChanges count] == 0 & [rowChanges count] == 0)
|
|
1330
|
+
* {
|
|
1331
|
+
* // Nothing has changed that affects our tableView
|
|
1332
|
+
* return;
|
|
1333
|
+
* }
|
|
1334
|
+
*
|
|
1335
|
+
* // Update the table (animating the changes)
|
|
1336
|
+
*
|
|
1337
|
+
* [self.tableView beginUpdates];
|
|
1338
|
+
*
|
|
1339
|
+
* for (YapDatabaseViewSectionChange *sectionChange in sectionChanges)
|
|
1340
|
+
* {
|
|
1341
|
+
* // ... (see https://github.com/yaptv/YapDatabase/wiki/Views )
|
|
1342
|
+
* }
|
|
1343
|
+
*
|
|
1344
|
+
* for (YapDatabaseViewRowChange *rowChange in rowChanges)
|
|
1345
|
+
* {
|
|
1346
|
+
* // ... (see https://github.com/yaptv/YapDatabase/wiki/Views )
|
|
1347
|
+
* }
|
|
1348
|
+
*
|
|
1349
|
+
* [self.tableView endUpdates];
|
|
1350
|
+
*
|
|
1351
|
+
* // Try to reselect whatever was selected before
|
|
1352
|
+
*
|
|
1353
|
+
* __block NSIndexPath *indexPath = nil;
|
|
1354
|
+
*
|
|
1355
|
+
* if (selectedIndexPath) {
|
|
1356
|
+
* [databaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
1357
|
+
* indexPath = [[transaction ext:@"widgets"] indexPathForKey:selectedWidgetId
|
|
1358
|
+
* withMappings:mappings];
|
|
1359
|
+
* }];
|
|
1360
|
+
* }
|
|
1361
|
+
*
|
|
1362
|
+
* // Otherwise select the nearest row to whatever was selected before
|
|
1363
|
+
*
|
|
1364
|
+
* if (!indexPath && selectedGroup) {
|
|
1365
|
+
* indexPath = [mappings nearestIndexPathForRow:selectedRow inGroup:selectedGroup];
|
|
1366
|
+
* }
|
|
1367
|
+
*
|
|
1368
|
+
* if (indexPath) {
|
|
1369
|
+
* [self.tableView selectRowAtIndexPath:indexPath
|
|
1370
|
+
* animated:NO
|
|
1371
|
+
* scrollPosition:UITableViewScrollPositionMiddle];
|
|
1372
|
+
* }
|
|
1373
|
+
* }
|
|
1374
|
+
**/
|
|
1375
|
+
- (NSIndexPath *)nearestIndexPathForRow:(NSUInteger)row inGroup:(NSString *)searchGroup
|
|
1376
|
+
{
|
|
1377
|
+
if (searchGroup == nil) return nil;
|
|
1378
|
+
if (snapshotOfLastUpdate == UINT64_MAX) return nil;
|
|
1379
|
+
|
|
1380
|
+
BOOL foundGroup = NO;
|
|
1381
|
+
NSUInteger groupIndex = 0;
|
|
1382
|
+
|
|
1383
|
+
for (NSString *group in allGroups)
|
|
1384
|
+
{
|
|
1385
|
+
if ([group isEqualToString:searchGroup])
|
|
1386
|
+
{
|
|
1387
|
+
foundGroup = YES;
|
|
1388
|
+
break;
|
|
1389
|
+
}
|
|
1390
|
+
groupIndex++;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
if (!foundGroup) return nil;
|
|
1394
|
+
|
|
1395
|
+
BOOL isGroupVisible = NO;
|
|
1396
|
+
NSUInteger visibleGroupIndex = 0;
|
|
1397
|
+
|
|
1398
|
+
for (NSString *visibleGroup in visibleGroups)
|
|
1399
|
+
{
|
|
1400
|
+
if ([visibleGroup isEqualToString:searchGroup])
|
|
1401
|
+
{
|
|
1402
|
+
isGroupVisible = YES;
|
|
1403
|
+
break;
|
|
1404
|
+
}
|
|
1405
|
+
visibleGroupIndex++;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
if (isGroupVisible)
|
|
1409
|
+
{
|
|
1410
|
+
// The searchGroup is visible.
|
|
1411
|
+
|
|
1412
|
+
NSUInteger rows = [self numberOfItemsInGroup:searchGroup];
|
|
1413
|
+
if (rows > 0)
|
|
1414
|
+
{
|
|
1415
|
+
if (row < rows)
|
|
1416
|
+
{
|
|
1417
|
+
#if TARGET_OS_IPHONE
|
|
1418
|
+
return [NSIndexPath indexPathForRow:row inSection:visibleGroupIndex];
|
|
1419
|
+
#else
|
|
1420
|
+
NSUInteger indexes[] = {visibleGroupIndex, row};
|
|
1421
|
+
return [NSIndexPath indexPathWithIndexes:indexes length:2];
|
|
1422
|
+
#endif
|
|
1423
|
+
}
|
|
1424
|
+
else
|
|
1425
|
+
{
|
|
1426
|
+
#if TARGET_OS_IPHONE
|
|
1427
|
+
return [NSIndexPath indexPathForRow:(rows-1) inSection:visibleGroupIndex];
|
|
1428
|
+
#else
|
|
1429
|
+
NSUInteger indexes[] = {visibleGroupIndex, (rows-1)};
|
|
1430
|
+
return [NSIndexPath indexPathWithIndexes:indexes length:2];
|
|
1431
|
+
#endif
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
NSUInteger nearbyGroupIndex;
|
|
1437
|
+
|
|
1438
|
+
// Try to select the closest row below the given group.
|
|
1439
|
+
|
|
1440
|
+
nearbyGroupIndex = groupIndex;
|
|
1441
|
+
while (nearbyGroupIndex > 0)
|
|
1442
|
+
{
|
|
1443
|
+
nearbyGroupIndex--;
|
|
1444
|
+
NSString *nearbyGroup = [allGroups objectAtIndex:nearbyGroupIndex];
|
|
1445
|
+
|
|
1446
|
+
NSUInteger section = [self sectionForGroup:nearbyGroup];
|
|
1447
|
+
if (section != NSNotFound)
|
|
1448
|
+
{
|
|
1449
|
+
NSUInteger rows = [self numberOfItemsInGroup:nearbyGroup];
|
|
1450
|
+
if (rows > 0)
|
|
1451
|
+
{
|
|
1452
|
+
#if TARGET_OS_IPHONE
|
|
1453
|
+
return [NSIndexPath indexPathForRow:(rows-1) inSection:section];
|
|
1454
|
+
#else
|
|
1455
|
+
NSUInteger indexes[] = {section, (rows-1)};
|
|
1456
|
+
return [NSIndexPath indexPathWithIndexes:indexes length:2];
|
|
1457
|
+
#endif
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
// Try to select the closest row above the given group.
|
|
1463
|
+
|
|
1464
|
+
nearbyGroupIndex = groupIndex;
|
|
1465
|
+
while ((nearbyGroupIndex + 1) < [allGroups count])
|
|
1466
|
+
{
|
|
1467
|
+
nearbyGroupIndex++;
|
|
1468
|
+
NSString *nearbyGroup = [allGroups objectAtIndex:nearbyGroupIndex];
|
|
1469
|
+
|
|
1470
|
+
NSUInteger section = [self sectionForGroup:nearbyGroup];
|
|
1471
|
+
if (section != NSNotFound)
|
|
1472
|
+
{
|
|
1473
|
+
NSUInteger rows = [self numberOfItemsInGroup:nearbyGroup];
|
|
1474
|
+
if (rows > 0)
|
|
1475
|
+
{
|
|
1476
|
+
#if TARGET_OS_IPHONE
|
|
1477
|
+
return [NSIndexPath indexPathForRow:0 inSection:section];
|
|
1478
|
+
#else
|
|
1479
|
+
NSUInteger indexes[] = {section, 0};
|
|
1480
|
+
return [NSIndexPath indexPathWithIndexes:indexes length:2];
|
|
1481
|
+
#endif
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
return nil;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1490
|
+
#pragma mark Logging
|
|
1491
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1492
|
+
|
|
1493
|
+
- (NSString *)description
|
|
1494
|
+
{
|
|
1495
|
+
NSMutableString *description = [NSMutableString string];
|
|
1496
|
+
[description appendFormat:@"<YapDatabaseViewMappings[%p]: view(%@)\n", self, registeredViewName];
|
|
1497
|
+
|
|
1498
|
+
if (isUsingConsolidatedGroup)
|
|
1499
|
+
{
|
|
1500
|
+
[description appendFormat:@" section(0) group(%@) totalCount(%lu) \n",
|
|
1501
|
+
consolidatedGroupName, (unsigned long)[self numberOfItemsInAllGroups]];
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
NSUInteger visibleIndex = 0;
|
|
1505
|
+
NSString *visibleGroup = ([visibleGroups count] > 0) ? [visibleGroups objectAtIndex:visibleIndex] : nil;
|
|
1506
|
+
|
|
1507
|
+
NSUInteger groupOffset = 0;
|
|
1508
|
+
|
|
1509
|
+
for (NSString *group in allGroups)
|
|
1510
|
+
{
|
|
1511
|
+
BOOL isVisible = [group isEqualToString:visibleGroup];
|
|
1512
|
+
|
|
1513
|
+
NSUInteger visibleCount = [self visibleCountForGroup:group];
|
|
1514
|
+
BOOL hasRangeOptions = ([rangeOptions objectForKey:group] != nil);
|
|
1515
|
+
|
|
1516
|
+
if (isVisible)
|
|
1517
|
+
{
|
|
1518
|
+
if (isUsingConsolidatedGroup)
|
|
1519
|
+
[description appendFormat:@" -> groupOffset(%lu)", (unsigned long)groupOffset];
|
|
1520
|
+
else
|
|
1521
|
+
[description appendFormat:@" section(%lu)", (unsigned long)visibleIndex];
|
|
1522
|
+
|
|
1523
|
+
}
|
|
1524
|
+
else
|
|
1525
|
+
{
|
|
1526
|
+
if (isUsingConsolidatedGroup)
|
|
1527
|
+
[description appendFormat:@" -> groupOffset(%lu)", (unsigned long)groupOffset];
|
|
1528
|
+
else
|
|
1529
|
+
[description appendString:@" section(-)"];
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
[description appendFormat:@" group(%@)", group];
|
|
1533
|
+
|
|
1534
|
+
if (hasRangeOptions)
|
|
1535
|
+
{
|
|
1536
|
+
[description appendFormat:@" groupCount(%lu) visibleCount(%lu)",
|
|
1537
|
+
(unsigned long)[self fullCountForGroup:group],
|
|
1538
|
+
(unsigned long)visibleCount];
|
|
1539
|
+
|
|
1540
|
+
YapDatabaseViewRangePosition rangePosition = [self rangePositionForGroup:group];
|
|
1541
|
+
|
|
1542
|
+
[description appendFormat:@" range.offsetFromBeginning(%lu) range.offsetFromEnd(%lu)",
|
|
1543
|
+
(unsigned long)rangePosition.offsetFromBeginning,
|
|
1544
|
+
(unsigned long)rangePosition.offsetFromEnd];
|
|
1545
|
+
}
|
|
1546
|
+
else
|
|
1547
|
+
{
|
|
1548
|
+
[description appendFormat:@" count(%lu)", (unsigned long)visibleCount];
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
[description appendString:@"\n"];
|
|
1552
|
+
|
|
1553
|
+
if (isVisible)
|
|
1554
|
+
{
|
|
1555
|
+
visibleIndex++;
|
|
1556
|
+
visibleGroup = ([visibleGroups count] > visibleIndex) ? [visibleGroups objectAtIndex:visibleIndex] : nil;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
groupOffset += visibleCount;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
[description appendString:@">"];
|
|
1563
|
+
|
|
1564
|
+
return description;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
@end
|