Просмотр исходного кода

Table sections can update themselves

Tanner Bennett лет назад: 5
Родитель
Сommit
220af5c350

+ 9 - 0
Classes/Core/Controllers/FLEXFilteringTableViewController.m

@@ -111,9 +111,18 @@
 
 - (void)setAllSections:(NSArray<FLEXTableViewSection *> *)allSections {
     _allSections = allSections.copy;
+    // Only display nonempty sections
     self.sections = self.nonemptySections;
 }
 
+- (void)setSections:(NSArray<FLEXTableViewSection *> *)sections {
+    // Allow sections to reload a portion of the table view at will
+    [sections enumerateObjectsUsingBlock:^(FLEXTableViewSection *s, NSUInteger idx, BOOL *stop) {
+        [s setTable:self.tableView section:idx];
+    }];
+    _sections = sections.copy;
+}
+
 
 #pragma mark - UITableViewDataSource
 

+ 15 - 0
Classes/Core/FLEXTableViewSection.h

@@ -24,6 +24,10 @@ NS_ASSUME_NONNULL_BEGIN
     @protected
     /// Unused by default, use if you want
     NSString *_title;
+    
+    @private
+    __weak UITableView *_tableView;
+    NSInteger _sectionIndex;
 }
 
 #pragma mark - Data
@@ -57,6 +61,17 @@ NS_ASSUME_NONNULL_BEGIN
 /// \c setFilterText: to call \c super and call \c reloadData.
 - (void)reloadData;
 
+/// Like \c reloadData, but optionally reloads the table view section
+/// associated with this section object, if any. Do not override.
+/// Do not call outside of the main thread.
+- (void)reloadData:(BOOL)updateTable;
+
+/// Provide a table view and section index to allow the section to efficiently reload
+/// its own section of the table when something changes it. The table reference is
+/// held weakly, and subclasses cannot access it or the index. Call this method again
+/// if the section numbers have changed since you last called it.
+- (void)setTable:(UITableView *)tableView section:(NSInteger)index;
+
 #pragma mark - Row Selection
 
 /// Whether the given row should be selectable, such as if tapping the cell

+ 13 - 0
Classes/Core/FLEXTableViewSection.m

@@ -22,6 +22,19 @@
 
 - (void)reloadData { }
 
+- (void)reloadData:(BOOL)updateTable {
+    [self reloadData];
+    if (updateTable) {
+        NSIndexSet *index = [NSIndexSet indexSetWithIndex:_sectionIndex];
+        [_tableView reloadSections:index withRowAnimation:UITableViewRowAnimationNone];
+    }
+}
+
+- (void)setTable:(UITableView *)tableView section:(NSInteger)index {
+    _tableView = tableView;
+    _sectionIndex = index;
+}
+
 - (NSDictionary<NSString *,Class> *)cellRegistrationMapping {
     return nil;
 }

+ 3 - 0
Classes/ObjectExplorers/Sections/FLEXCollectionContentSection.h

@@ -95,4 +95,7 @@ typedef id<FLEXCollection>(^FLEXCollectionContentFuture)(__kindof FLEXCollection
 /// For dictionaries, this returns the value, not the key.
 - (ObjectType)objectForRow:(NSInteger)row;
 
+/// Subclasses may override.
+- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row;
+
 @end

+ 10 - 1
Classes/ObjectExplorers/Sections/FLEXCollectionContentSection.m

@@ -12,6 +12,7 @@
 #import "FLEXSubtitleTableViewCell.h"
 #import "FLEXTableView.h"
 #import "FLEXObjectExplorerFactory.h"
+#import "FLEXDefaultEditorViewController.h"
 
 typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
     FLEXUnsupportedCollection,
@@ -29,6 +30,7 @@ typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
 /// A collection that may change over time and can be called upon for new data
 @property (nonatomic, readonly) FLEXCollectionContentFuture collectionFuture;
 @property (nonatomic, readonly) FLEXCollectionType collectionType;
+@property (nonatomic, readonly) BOOL isMutable;
 @end
 
 @implementation FLEXCollectionContentSection
@@ -45,6 +47,7 @@ typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
     section->_collectionType = [self typeForCollection:collection];
     section->_collection = collection;
     section.cachedCollection = collection;
+    section->_isMutable = [collection respondsToSelector:@selector(filterUsingPredicate:)];
     return section;
 }
 
@@ -53,6 +56,7 @@ typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
     section->_collectionFuture = collectionFuture;
     section.cachedCollection = collectionFuture(section);
     section->_collectionType = [self typeForCollection:section.cachedCollection];
+    section->_isMutable = [section->_cachedCollection respondsToSelector:@selector(filterUsingPredicate:)];
     return section;
 }
 
@@ -136,6 +140,11 @@ typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
     }
 }
 
+- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row {
+    return UITableViewCellAccessoryDisclosureIndicator;
+//    return self.isMutable ? UITableViewCellAccessoryDetailDisclosureButton : UITableViewCellAccessoryDisclosureIndicator;
+}
+
 
 #pragma mark - Overrides
 
@@ -198,7 +207,7 @@ typedef NS_ENUM(NSUInteger, FLEXCollectionType) {
 - (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row {
     cell.titleLabel.text = [self titleForRow:row];
     cell.subtitleLabel.text = [self subtitleForRow:row];
-    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+    cell.accessoryType = [self accessoryTypeForRow:row];
 }
 
 @end

+ 23 - 0
Classes/ObjectExplorers/Sections/FLEXDefaultsContentSection.m

@@ -7,6 +7,8 @@
 //
 
 #import "FLEXDefaultsContentSection.h"
+#import "FLEXDefaultEditorViewController.h"
+#import "FLEXUtility.h"
 
 @interface FLEXDefaultsContentSection ()
 @property (nonatomic) NSUserDefaults *defaults;
@@ -42,6 +44,27 @@
     return @"Defaults";
 }
 
+- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row {
+    return ^(UIViewController *host) {
+        if ([FLEXDefaultEditorViewController canEditDefaultWithValue:[self objectForRow:row]]) {
+            // We use titleForRow: to get the key because self.keys is not
+            // necessarily in the same order as the keys being displayed
+            FLEXVariableEditorViewController *controller = [FLEXDefaultEditorViewController
+                target:self.defaults key:[self titleForRow:row] commitHandler:^{
+                    [self reloadData:YES];
+                }
+            ];
+            [host.navigationController pushViewController:controller animated:YES];
+        } else {
+            [FLEXAlert showAlert:@"Oh No…" message:@"We can't edit this entry :(" from:host];
+        }
+    };
+}
+
+- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row {
+    return UITableViewCellAccessoryDetailDisclosureButton;
+}
+
 #pragma mark - Private
 
 - (NSArray *)keys {

+ 1 - 1
Classes/ObjectExplorers/Sections/FLEXMetadataSection.m

@@ -180,7 +180,7 @@
 }
 
 - (UIViewController *)editorForRow:(NSInteger)row {
-    return [self.metadata[row] editorWithTarget:self.explorer.object];
+    return [self.metadata[row] editorWithTarget:self.explorer.object section:self];
 }
 
 - (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row {

+ 2 - 2
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m

@@ -104,9 +104,9 @@
     return [self.metadata viewerWithTarget:object];
 }
 
-- (UIViewController *)editorWith:(id)object {
+- (UIViewController *)editorWith:(id)object forSection:(FLEXTableViewSection *)section {
     NSAssert(self.metadataKind, @"Static titles cannot be edited");
-    return [self.metadata editorWithTarget:object];
+    return [self.metadata editorWithTarget:object section:section];
 }
 
 - (UITableViewCellAccessoryType)accessoryTypeWith:(id)object {

+ 3 - 1
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h

@@ -11,6 +11,7 @@
 #import "FLEXIvar.h"
 #import "FLEXMethod.h"
 #import "FLEXProtocol.h"
+#import "FLEXTableViewSection.h"
 
 @class FLEXObjectExplorerDefaults;
 
@@ -42,7 +43,8 @@
 /// For methods, a method calling screen. For all else, an object explorer.
 - (UIViewController *)viewerWithTarget:(id)object;
 /// For methods and protocols, nil. For all else, an a field editor screen.
-- (UIViewController *)editorWithTarget:(id)object;
+/// The given section is reloaded on commit of any changes.
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section;
 /// Used to determine present which interactions are possible to the user
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object;
 /// Return nil to use the default reuse identifier

+ 15 - 7
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.m

@@ -91,9 +91,11 @@ FLEXObjectExplorerDefaultsImpl
     return [FLEXObjectExplorerFactory explorerViewControllerForObject:value];
 }
 
-- (UIViewController *)editorWithTarget:(id)object {
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section {
     id target = [self appropriateTargetForPropertyType:object];
-    return [FLEXFieldEditorViewController target:target property:self];
+    return [FLEXFieldEditorViewController target:target property:self commitHandler:^{
+        [section reloadData:YES];
+    }];
 }
 
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
@@ -226,9 +228,11 @@ FLEXObjectExplorerDefaultsImpl
     return [FLEXObjectExplorerFactory explorerViewControllerForObject:value];
 }
 
-- (UIViewController *)editorWithTarget:(id)object {
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section {
     NSAssert(!object_isClass(object), @"Unreachable state: editing ivar on class object");
-    return [FLEXFieldEditorViewController target:object ivar:self];
+    return [FLEXFieldEditorViewController target:object ivar:self commitHandler:^{
+        [section reloadData:YES];
+    }];
 }
 
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
@@ -342,7 +346,7 @@ FLEXObjectExplorerDefaultsImpl
     return nil;
 }
 
-- (UIViewController *)editorWithTarget:(id)object {
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section {
     // Methods cannot be edited
     @throw NSInternalInconsistencyException;
     return nil;
@@ -441,7 +445,9 @@ FLEXObjectExplorerDefaultsImpl
     return [FLEXObjectExplorerFactory explorerViewControllerForObject:self];
 }
 
-- (UIViewController *)editorWithTarget:(id)object {
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section {
+    // Protocols cannot be edited
+    @throw NSInternalInconsistencyException;
     return nil;
 }
 
@@ -553,7 +559,9 @@ FLEXObjectExplorerDefaultsImpl
     return nil;
 }
 
-- (UIViewController *)editorWithTarget:(id)object {
+- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section {
+    // Static metadata cannot be edited
+    @throw NSInternalInconsistencyException;
     return nil;
 }