FLEXCollectionContentSection.m 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // FLEXCollectionContentSection.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 8/28/19.
  6. // Copyright © 2019 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXCollectionContentSection.h"
  9. #import "FLEXUtility.h"
  10. #import "FLEXRuntimeUtility.h"
  11. #import "FLEXSubtitleTableViewCell.h"
  12. #import "FLEXTableView.h"
  13. #import "FLEXObjectExplorerFactory.h"
  14. typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
  15. FLEXUnsupportedCollection,
  16. FLEXOrderedCollection,
  17. FLEXUnorderedCollection,
  18. FLEXKeyedCollection
  19. };
  20. @interface FLEXCollectionContentSection ()
  21. @property (nonatomic) id<FLEXCollection> cachedCollection;
  22. @property (nonatomic, readonly) id<FLEXCollection> collection;
  23. @property (nonatomic, readonly) FLEXCollectionContentFuture collectionFuture;
  24. @property (nonatomic, readonly) FLEXCollectionType collectionType;
  25. @end
  26. @implementation FLEXCollectionContentSection
  27. #pragma mark Initialization
  28. + (instancetype)forObject:(id)object {
  29. return [self forCollection:object];
  30. }
  31. + (id)forCollection:(id<FLEXCollection>)collection {
  32. FLEXCollectionContentSection *section = [self new];
  33. section->_collectionType = [self typeForCollection:collection];
  34. section->_collection = collection;
  35. section.cachedCollection = collection.copy;
  36. return section;
  37. }
  38. + (id)forReusableFuture:(FLEXCollectionContentFuture)collectionFuture {
  39. FLEXCollectionContentSection *section = [self new];
  40. section->_collectionFuture = collectionFuture;
  41. section.cachedCollection = collectionFuture(section);
  42. section->_collectionType = [self typeForCollection:section.cachedCollection];
  43. return section;
  44. }
  45. #pragma mark - Misc
  46. + (FLEXCollectionType)typeForCollection:(id<FLEXCollection>)collection {
  47. // Order matters here, as NSDictionary is keyed but it responds to allObjects
  48. if ([collection respondsToSelector:@selector(objectAtIndexedSubscript:)]) {
  49. return FLEXOrderedCollection;
  50. }
  51. if ([collection respondsToSelector:@selector(objectForKeyedSubscript:)]) {
  52. return FLEXKeyedCollection;
  53. }
  54. if ([collection respondsToSelector:@selector(allObjects)]) {
  55. return FLEXUnorderedCollection;
  56. }
  57. [NSException raise:NSInvalidArgumentException
  58. format:@"Given collection does not properly conform to FLEXCollection"];
  59. return FLEXUnsupportedCollection;
  60. }
  61. /// Row titles
  62. /// - Ordered: the index
  63. /// - Unordered: the object
  64. /// - Keyed: the key
  65. - (NSString *)titleForRow:(NSInteger)row {
  66. switch (self.collectionType) {
  67. case FLEXOrderedCollection:
  68. return @(row).stringValue;
  69. case FLEXUnorderedCollection:
  70. return [self describe:[self objectForRow:row]];
  71. case FLEXKeyedCollection:
  72. return [self describe:self.collection.allKeys[row]];
  73. case FLEXUnsupportedCollection:
  74. return nil;
  75. }
  76. }
  77. /// Row subtitles
  78. /// - Ordered: the object
  79. /// - Unordered: nothing
  80. /// - Keyed: the value
  81. - (NSString *)subtitleForRow:(NSInteger)row {
  82. switch (self.collectionType) {
  83. case FLEXOrderedCollection:
  84. case FLEXKeyedCollection:
  85. return [self describe:[self objectForRow:row]];
  86. case FLEXUnorderedCollection:
  87. return nil;
  88. case FLEXUnsupportedCollection:
  89. return nil;
  90. }
  91. }
  92. - (NSString *)describe:(id)object {
  93. return [FLEXRuntimeUtility summaryForObject:object];
  94. }
  95. - (id)objectForRow:(NSInteger)row {
  96. switch (self.collectionType) {
  97. case FLEXOrderedCollection:
  98. return self.collection[row];
  99. case FLEXUnorderedCollection:
  100. return self.collection.allObjects[row];
  101. case FLEXKeyedCollection:
  102. return self.collection[self.collection.allKeys[row]];
  103. case FLEXUnsupportedCollection:
  104. return nil;
  105. }
  106. }
  107. #pragma mark - Overrides
  108. - (NSString *)title {
  109. return FLEXPluralString(self.cachedCollection.count, @"Entries", @"Entry");
  110. }
  111. - (NSInteger)numberOfRows {
  112. return self.cachedCollection.count;
  113. }
  114. - (void)reloadData {
  115. if (self.collectionFuture) {
  116. self.cachedCollection = self.collectionFuture(self);
  117. } else {
  118. self.cachedCollection = self.collection.copy;
  119. }
  120. }
  121. - (BOOL)canSelectRow:(NSInteger)row {
  122. return YES;
  123. }
  124. - (UIViewController *)viewControllerToPushForRow:(NSInteger)row {
  125. return [FLEXObjectExplorerFactory explorerViewControllerForObject:[self objectForRow:row]];
  126. }
  127. - (NSString *)reuseIdentifierForRow:(NSInteger)row {
  128. // Default for unordered, subtitle for others
  129. return self.collectionType == FLEXUnorderedCollection ? kFLEXDefaultCell : kFLEXDetailCell;
  130. }
  131. - (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row {
  132. cell.titleLabel.text = [self titleForRow:row];
  133. cell.subtitleLabel.text = [self subtitleForRow:row];
  134. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  135. }
  136. @end