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.
Files changed (348) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.lock +63 -0
  6. data/README.md +16 -0
  7. data/Rakefile +20 -0
  8. data/app/app_delegate.rb +5 -0
  9. data/lib/yapper.rb +30 -0
  10. data/lib/yapper/attachment.rb +48 -0
  11. data/lib/yapper/bson.rb +20 -0
  12. data/lib/yapper/config.rb +18 -0
  13. data/lib/yapper/db.rb +151 -0
  14. data/lib/yapper/document.rb +54 -0
  15. data/lib/yapper/document/attachment.rb +26 -0
  16. data/lib/yapper/document/callbacks.rb +86 -0
  17. data/lib/yapper/document/persistance.rb +171 -0
  18. data/lib/yapper/document/relation.rb +84 -0
  19. data/lib/yapper/document/selection.rb +100 -0
  20. data/lib/yapper/extensions.rb +80 -0
  21. data/lib/yapper/log.rb +5 -0
  22. data/lib/yapper/sync.rb +134 -0
  23. data/lib/yapper/sync/data.rb +12 -0
  24. data/lib/yapper/sync/event.rb +194 -0
  25. data/lib/yapper/sync/queue.rb +164 -0
  26. data/lib/yapper/timestamps.rb +16 -0
  27. data/lib/yapper/version.rb +3 -0
  28. data/lib/yapper/yapper.rb +2 -0
  29. data/spec/helpers/time_helper.rb +3 -0
  30. data/spec/integration/all_spec.rb +40 -0
  31. data/spec/integration/callback_spec.rb +87 -0
  32. data/spec/integration/db_spec.rb +40 -0
  33. data/spec/integration/find_spec.rb +51 -0
  34. data/spec/integration/persistance_spec.rb +118 -0
  35. data/spec/integration/relation_spec.rb +174 -0
  36. data/spec/integration/sync_spec.rb +42 -0
  37. data/spec/integration/timestamps_spec.rb +34 -0
  38. data/spec/integration/types_spec.rb +23 -0
  39. data/spec/integration/when_spec.rb +29 -0
  40. data/spec/integration/where_spec.rb +132 -0
  41. data/vendor/Podfile.lock +24 -0
  42. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.h +641 -0
  43. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.m +1396 -0
  44. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +133 -0
  45. data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m +327 -0
  46. data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.h +113 -0
  47. data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.m +321 -0
  48. data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.h +71 -0
  49. data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.m +150 -0
  50. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  51. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.m +157 -0
  52. data/vendor/Pods/AFNetworking/AFNetworking/AFNetworking.h +43 -0
  53. data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  54. data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.m +143 -0
  55. data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h +370 -0
  56. data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m +848 -0
  57. data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.h +89 -0
  58. data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.m +167 -0
  59. data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.h +78 -0
  60. data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.m +191 -0
  61. data/vendor/Pods/AFNetworking/LICENSE +19 -0
  62. data/vendor/Pods/AFNetworking/README.md +208 -0
  63. data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPClient.h +641 -0
  64. data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPRequestOperation.h +133 -0
  65. data/vendor/Pods/BuildHeaders/AFNetworking/AFImageRequestOperation.h +113 -0
  66. data/vendor/Pods/BuildHeaders/AFNetworking/AFJSONRequestOperation.h +71 -0
  67. data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  68. data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworking.h +43 -0
  69. data/vendor/Pods/BuildHeaders/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  70. data/vendor/Pods/BuildHeaders/AFNetworking/AFURLConnectionOperation.h +370 -0
  71. data/vendor/Pods/BuildHeaders/AFNetworking/AFXMLRequestOperation.h +89 -0
  72. data/vendor/Pods/BuildHeaders/AFNetworking/UIImageView+AFNetworking.h +78 -0
  73. data/vendor/Pods/BuildHeaders/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
  74. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +41 -0
  75. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
  76. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +334 -0
  77. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +601 -0
  78. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +167 -0
  79. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
  80. data/vendor/Pods/BuildHeaders/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  81. data/vendor/Pods/BuildHeaders/Reachability/Reachability.h +109 -0
  82. data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +90 -0
  83. data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +20 -0
  84. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +547 -0
  85. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +447 -0
  86. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnectionState.h +29 -0
  87. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +37 -0
  88. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtension.h +15 -0
  89. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
  90. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
  91. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
  92. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +108 -0
  93. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
  94. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
  95. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
  96. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
  97. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
  98. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
  99. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  100. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
  101. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseLogging.h +158 -0
  102. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseManager.h +17 -0
  103. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +424 -0
  104. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseQuery.h +42 -0
  105. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
  106. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
  107. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
  108. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
  109. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
  110. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseStatement.h +13 -0
  111. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseString.h +121 -0
  112. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +541 -0
  113. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +186 -0
  114. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +272 -0
  115. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
  116. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +115 -0
  117. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +825 -0
  118. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
  119. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +56 -0
  120. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPage.h +36 -0
  121. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
  122. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +153 -0
  123. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
  124. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  125. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +447 -0
  126. data/vendor/Pods/BuildHeaders/YapDatabase/YapMemoryTable.h +74 -0
  127. data/vendor/Pods/BuildHeaders/YapDatabase/YapNull.h +17 -0
  128. data/vendor/Pods/BuildHeaders/YapDatabase/YapSet.h +41 -0
  129. data/vendor/Pods/BuildHeaders/YapDatabase/YapTouch.h +15 -0
  130. data/vendor/Pods/CocoaLumberjack/LICENSE.txt +18 -0
  131. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +41 -0
  132. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +99 -0
  133. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +102 -0
  134. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +727 -0
  135. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +334 -0
  136. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +1353 -0
  137. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +601 -0
  138. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +1083 -0
  139. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +167 -0
  140. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +1479 -0
  141. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
  142. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
  143. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
  144. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
  145. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +7 -0
  146. data/vendor/Pods/CocoaLumberjack/README.markdown +37 -0
  147. data/vendor/Pods/Headers/AFNetworking/AFHTTPClient.h +641 -0
  148. data/vendor/Pods/Headers/AFNetworking/AFHTTPRequestOperation.h +133 -0
  149. data/vendor/Pods/Headers/AFNetworking/AFImageRequestOperation.h +113 -0
  150. data/vendor/Pods/Headers/AFNetworking/AFJSONRequestOperation.h +71 -0
  151. data/vendor/Pods/Headers/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  152. data/vendor/Pods/Headers/AFNetworking/AFNetworking.h +43 -0
  153. data/vendor/Pods/Headers/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  154. data/vendor/Pods/Headers/AFNetworking/AFURLConnectionOperation.h +370 -0
  155. data/vendor/Pods/Headers/AFNetworking/AFXMLRequestOperation.h +89 -0
  156. data/vendor/Pods/Headers/AFNetworking/UIImageView+AFNetworking.h +78 -0
  157. data/vendor/Pods/Headers/CocoaLumberjack/ContextFilterLogFormatter.h +65 -0
  158. data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +41 -0
  159. data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +102 -0
  160. data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +334 -0
  161. data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +601 -0
  162. data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +167 -0
  163. data/vendor/Pods/Headers/CocoaLumberjack/DispatchQueueLogFormatter.h +116 -0
  164. data/vendor/Pods/Headers/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  165. data/vendor/Pods/Headers/Reachability/Reachability.h +109 -0
  166. data/vendor/Pods/Headers/YapDatabase/YapCache.h +90 -0
  167. data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +20 -0
  168. data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +547 -0
  169. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +447 -0
  170. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnectionState.h +29 -0
  171. data/vendor/Pods/Headers/YapDatabase/YapDatabaseDefaults.h +37 -0
  172. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtension.h +15 -0
  173. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionConnection.h +11 -0
  174. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionPrivate.h +440 -0
  175. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionTransaction.h +11 -0
  176. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +108 -0
  177. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewConnection.h +12 -0
  178. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewPrivate.h +19 -0
  179. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +39 -0
  180. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearch.h +89 -0
  181. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchConnection.h +32 -0
  182. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchPrivate.h +69 -0
  183. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  184. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchTransaction.h +68 -0
  185. data/vendor/Pods/Headers/YapDatabase/YapDatabaseLogging.h +158 -0
  186. data/vendor/Pods/Headers/YapDatabase/YapDatabaseManager.h +17 -0
  187. data/vendor/Pods/Headers/YapDatabase/YapDatabasePrivate.h +424 -0
  188. data/vendor/Pods/Headers/YapDatabase/YapDatabaseQuery.h +42 -0
  189. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +100 -0
  190. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexConnection.h +33 -0
  191. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +73 -0
  192. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexSetup.h +33 -0
  193. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +58 -0
  194. data/vendor/Pods/Headers/YapDatabase/YapDatabaseStatement.h +13 -0
  195. data/vendor/Pods/Headers/YapDatabase/YapDatabaseString.h +121 -0
  196. data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +541 -0
  197. data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +186 -0
  198. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +272 -0
  199. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChangePrivate.h +94 -0
  200. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +115 -0
  201. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +825 -0
  202. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappingsPrivate.h +72 -0
  203. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +56 -0
  204. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPage.h +36 -0
  205. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPageMetadata.h +27 -0
  206. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPrivate.h +153 -0
  207. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptions.h +330 -0
  208. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  209. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +447 -0
  210. data/vendor/Pods/Headers/YapDatabase/YapMemoryTable.h +74 -0
  211. data/vendor/Pods/Headers/YapDatabase/YapNull.h +17 -0
  212. data/vendor/Pods/Headers/YapDatabase/YapSet.h +41 -0
  213. data/vendor/Pods/Headers/YapDatabase/YapTouch.h +15 -0
  214. data/vendor/Pods/Headers/____Pods-AFNetworking-prefix.h +17 -0
  215. data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +5 -0
  216. data/vendor/Pods/Headers/____Pods-NSData+MD5Digest-prefix.h +5 -0
  217. data/vendor/Pods/Headers/____Pods-Reachability-prefix.h +5 -0
  218. data/vendor/Pods/Headers/____Pods-YapDatabase-prefix.h +5 -0
  219. data/vendor/Pods/Headers/____Pods-environment.h +38 -0
  220. data/vendor/Pods/Manifest.lock +24 -0
  221. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.h +18 -0
  222. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.m +39 -0
  223. data/vendor/Pods/NSData+MD5Digest/README.md +11 -0
  224. data/vendor/Pods/Pods-AFNetworking-Private.xcconfig +5 -0
  225. data/vendor/Pods/Pods-AFNetworking-dummy.m +5 -0
  226. data/vendor/Pods/Pods-AFNetworking-prefix.pch +17 -0
  227. data/vendor/Pods/Pods-AFNetworking.xcconfig +1 -0
  228. data/vendor/Pods/Pods-Acknowledgements.markdown +96 -0
  229. data/vendor/Pods/Pods-Acknowledgements.plist +142 -0
  230. data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +5 -0
  231. data/vendor/Pods/Pods-CocoaLumberjack-dummy.m +5 -0
  232. data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +5 -0
  233. data/vendor/Pods/Pods-CocoaLumberjack.xcconfig +0 -0
  234. data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +5 -0
  235. data/vendor/Pods/Pods-NSData+MD5Digest-dummy.m +5 -0
  236. data/vendor/Pods/Pods-NSData+MD5Digest-prefix.pch +5 -0
  237. data/vendor/Pods/Pods-NSData+MD5Digest.xcconfig +0 -0
  238. data/vendor/Pods/Pods-Reachability-Private.xcconfig +5 -0
  239. data/vendor/Pods/Pods-Reachability-dummy.m +5 -0
  240. data/vendor/Pods/Pods-Reachability-prefix.pch +5 -0
  241. data/vendor/Pods/Pods-Reachability.xcconfig +1 -0
  242. data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +5 -0
  243. data/vendor/Pods/Pods-YapDatabase-dummy.m +5 -0
  244. data/vendor/Pods/Pods-YapDatabase-prefix.pch +5 -0
  245. data/vendor/Pods/Pods-YapDatabase.xcconfig +1 -0
  246. data/vendor/Pods/Pods-dummy.m +5 -0
  247. data/vendor/Pods/Pods-environment.h +38 -0
  248. data/vendor/Pods/Pods-resources.sh +68 -0
  249. data/vendor/Pods/Pods.bridgesupport +5096 -0
  250. data/vendor/Pods/Pods.xcconfig +5 -0
  251. data/vendor/Pods/Pods.xcodeproj/project.pbxproj +5536 -0
  252. data/vendor/Pods/Reachability/LICENCE.txt +24 -0
  253. data/vendor/Pods/Reachability/README.md +65 -0
  254. data/vendor/Pods/Reachability/Reachability.h +109 -0
  255. data/vendor/Pods/Reachability/Reachability.m +527 -0
  256. data/vendor/Pods/YapDatabase/LICENSE.txt +18 -0
  257. data/vendor/Pods/YapDatabase/README.md +30 -0
  258. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +19 -0
  259. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +108 -0
  260. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +175 -0
  261. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h +12 -0
  262. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m +41 -0
  263. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +39 -0
  264. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +966 -0
  265. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +69 -0
  266. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +89 -0
  267. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +146 -0
  268. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +32 -0
  269. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +298 -0
  270. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h +79 -0
  271. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m +95 -0
  272. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +68 -0
  273. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +1352 -0
  274. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +440 -0
  275. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.h +15 -0
  276. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +58 -0
  277. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +11 -0
  278. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +46 -0
  279. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +11 -0
  280. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +180 -0
  281. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +73 -0
  282. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +100 -0
  283. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +149 -0
  284. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h +33 -0
  285. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +330 -0
  286. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h +33 -0
  287. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +184 -0
  288. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h +58 -0
  289. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +1166 -0
  290. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h +94 -0
  291. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h +72 -0
  292. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h +36 -0
  293. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm +296 -0
  294. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h +27 -0
  295. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m +28 -0
  296. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +153 -0
  297. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h +17 -0
  298. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +272 -0
  299. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +2494 -0
  300. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +825 -0
  301. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +1567 -0
  302. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h +330 -0
  303. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m +141 -0
  304. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +186 -0
  305. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +191 -0
  306. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +115 -0
  307. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +897 -0
  308. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +56 -0
  309. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +27 -0
  310. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +447 -0
  311. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +4505 -0
  312. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +90 -0
  313. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +453 -0
  314. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.h +29 -0
  315. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.m +48 -0
  316. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +37 -0
  317. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +83 -0
  318. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.h +158 -0
  319. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.m +73 -0
  320. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.h +17 -0
  321. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.m +56 -0
  322. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +424 -0
  323. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.h +13 -0
  324. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.m +26 -0
  325. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseString.h +121 -0
  326. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.h +74 -0
  327. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.m +603 -0
  328. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.h +17 -0
  329. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +31 -0
  330. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.h +15 -0
  331. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.m +31 -0
  332. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +20 -0
  333. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +194 -0
  334. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +42 -0
  335. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +96 -0
  336. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +41 -0
  337. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.m +82 -0
  338. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +547 -0
  339. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +2022 -0
  340. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +447 -0
  341. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +3874 -0
  342. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +541 -0
  343. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +5282 -0
  344. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +16 -0
  345. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +13 -0
  346. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +20 -0
  347. data/yapper.gemspec +24 -0
  348. 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:&section 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:&sectionChanges
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