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

Fix shortcuts for view controllers

Refactor FLEXShortcut and FLEXActionShortcut so that shortcuts can perform any arbitrary action when they are selected. View controllers will show a dialog when they cannot be pushed.
Tanner Bennett лет назад: 6
Родитель
Сommit
d8ff46853d

+ 13 - 10
Classes/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.m

@@ -7,21 +7,24 @@
 //
 
 #import "FLEXBundleShortcuts.h"
+#import "FLEXShortcut.h"
 #import "FLEXFileBrowserTableViewController.h"
 
+#pragma mark -
 @implementation FLEXBundleShortcuts
-#pragma mark - Overrides
+#pragma mark Overrides
 
 + (instancetype)forObject:(NSBundle *)bundle {
-    return [self forObject:bundle additionalRows:@[@"Browse bundle directory"]];
-}
-
-- (UIViewController *)viewControllerToPushForRow:(NSInteger)row {
-    if (row == 0) {
-        return [FLEXFileBrowserTableViewController path:[self.object bundlePath]];
-    }
-
-    return [super viewControllerToPushForRow:row];
+    return [self forObject:bundle additionalRows:@[
+        [FLEXActionShortcut title:@"Browse Bundle Directory" subtitle:nil
+            viewer:^UIViewController *(id view) {
+                return [FLEXFileBrowserTableViewController path:bundle.bundlePath];
+            }
+            accessoryType:^UITableViewCellAccessoryType(id view) {
+                return UITableViewCellAccessoryDisclosureIndicator;
+            }
+        ]
+    ]];
 }
 
 @end

+ 7 - 2
Classes/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.m

@@ -15,6 +15,7 @@
 /// a useful subtitle for the bundles of classes
 @interface FLEXBundleShortcut : NSObject <FLEXShortcut>
 @end
+#pragma mark - 
 @implementation FLEXBundleShortcut
 
 - (NSString *)titleWith:(id)object {
@@ -51,23 +52,27 @@
     return nil;
 }
 
+- (void (^)(UIViewController *))didSelectActionWith:(id)object { 
+    return nil;
+}
 
 @end
 
+#pragma mark - 
 @interface FLEXClassShortcuts ()
 @property (nonatomic, readonly) Class cls;
 @end
 
 @implementation FLEXClassShortcuts
 
-#pragma mark - Internal
+#pragma mark Internal
 
 - (Class)cls {
     return self.object;
 }
 
 
-#pragma mark - Overrides
+#pragma mark Overrides
 
 + (instancetype)forObject:(Class)cls {
     // These additional rows will appear at the beginning of the shortcuts section.

+ 6 - 1
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h

@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (nonnull  NSString *)titleWith:(id)object;
 - (nullable NSString *)subtitleWith:(id)object;
-//- (void (^)(UIViewController *))didSelectAction:(id)object;
+- (nullable void (^)(UIViewController *host))didSelectActionWith:(id)object;
 /// Called when the row is selected
 - (nullable UIViewController *)viewerWith:(id)object;
 /// Basically, whether or not to show a detail disclosure indicator
@@ -61,6 +61,11 @@ NS_ASSUME_NONNULL_BEGIN
                viewer:(nullable UIViewController *(^)(id object))viewerFuture
         accessoryType:(nullable UITableViewCellAccessoryType(^)(id object))accessoryTypeFuture;
 
++ (instancetype)title:(NSString *)title
+             subtitle:(nullable NSString *(^)(id object))subtitleFuture
+     selectionHandler:(nullable void (^)(UIViewController *host, id object))tapAction
+        accessoryType:(nullable UITableViewCellAccessoryType(^)(id object))accessoryTypeFuture;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 26 - 1
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m

@@ -94,6 +94,10 @@
     return @"";
 }
 
+- (void (^)(UIViewController *))didSelectActionWith:(id)object { 
+    return nil;
+}
+
 - (UIViewController *)viewerWith:(id)object {
     NSAssert(self.metadataKind, @"Static titles cannot be viewed");
     return [self.metadata viewerWithTarget:object];
@@ -136,6 +140,7 @@
 @property (nonatomic, readonly) NSString *title;
 @property (nonatomic, readonly) NSString *(^subtitleFuture)(id);
 @property (nonatomic, readonly) UIViewController *(^viewerFuture)(id);
+@property (nonatomic, readonly) void (^selectionHandler)(UIViewController *, id);
 @property (nonatomic, readonly) UITableViewCellAccessoryType (^accessoryTypeFuture)(id);
 @end
 
@@ -145,21 +150,31 @@
              subtitle:(NSString *(^)(id))subtitle
                viewer:(UIViewController *(^)(id))viewer
         accessoryType:(UITableViewCellAccessoryType (^)(id))type {
-    return [[self alloc] initWithTitle:title subtitle:subtitle viewer:viewer accessoryType:type];
+    return [[self alloc] initWithTitle:title subtitle:subtitle viewer:viewer selectionHandler:nil accessoryType:type];
+}
+
++ (instancetype)title:(NSString *)title
+             subtitle:(NSString * (^)(id))subtitle
+     selectionHandler:(void (^)(UIViewController *, id))tapAction
+        accessoryType:(UITableViewCellAccessoryType (^)(id))type {
+    return [[self alloc] initWithTitle:title subtitle:subtitle viewer:nil selectionHandler:tapAction accessoryType:type];
 }
 
 - (id)initWithTitle:(NSString *)title
            subtitle:(id)subtitleFuture
              viewer:(id)viewerFuture
+   selectionHandler:(id)tapAction
       accessoryType:(id)accessoryTypeFuture {
     NSParameterAssert(title.length);
 
     self = [super init];
     if (self) {
         id nilBlock = ^id (id obj) { return nil; };
+        
         _title = title;
         _subtitleFuture = subtitleFuture ?: nilBlock;
         _viewerFuture = viewerFuture ?: nilBlock;
+        _selectionHandler = tapAction;
         _accessoryTypeFuture = accessoryTypeFuture ?: nilBlock;
     }
 
@@ -174,6 +189,16 @@
     return self.subtitleFuture(object);
 }
 
+- (void (^)(UIViewController *))didSelectActionWith:(id)object {
+    if (self.selectionHandler) {
+        return ^(UIViewController *host) {
+            self.selectionHandler(host, object);
+        };
+    }
+    
+    return nil;
+}
+
 - (UIViewController *)viewerWith:(id)object {
     return self.viewerFuture(object);
 }

+ 4 - 0
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m

@@ -186,6 +186,10 @@
     return hasDisclosure;
 }
 
+- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row {
+    return [self.shortcuts[row] didSelectActionWith:self.object];
+}
+
 - (UIViewController *)viewControllerToPushForRow:(NSInteger)row {
     /// Nil if shortcuts is nil, i.e. if initialized with forObject:rowTitles:rowSubtitles:
     return [self.shortcuts[row] viewerWith:self.object];

+ 33 - 32
Classes/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.m

@@ -7,6 +7,9 @@
 //
 
 #import "FLEXViewControllerShortcuts.h"
+#import "FLEXObjectExplorerFactory.h"
+#import "FLEXRuntimeUtility.h"
+#import "FLEXShortcut.h"
 #import "FLEXAlert.h"
 
 @interface FLEXViewControllerShortcuts ()
@@ -36,41 +39,39 @@
 #pragma mark - Overrides
 
 + (instancetype)forObject:(UIViewController *)viewController {
-    // These additional rows will appear at the beginning of the shortcuts section.
-    // The methods below are written in such a way that they will not interfere
-    // with properties/etc being registered alongside these
-    return [self forObject:viewController additionalRows:@[@"Push View Controller"]];
-}
+    BOOL (^vcIsInuse)(UIViewController *) = ^BOOL(UIViewController *controller) {
+        if (controller.view.window) {
+            return YES;
+        }
 
-- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row {
-    if (row == 0) {
-        return ^(UIViewController *host) {
-            if (!self.viewControllerIsInUse) {
-                [host.navigationController pushViewController:self.viewController animated:YES];
-            } else {
-                [FLEXAlert
-                    showAlert:@"Cannot Push View Controller"
-                    message:@"This view controller's view is currently in use."
-                    from:host
-                ];
+        return controller.navigationController != nil;
+    };
+    
+    return [self forObject:viewController additionalRows:@[
+        [FLEXActionShortcut title:@"Push View Controller"
+            subtitle:^NSString *(UIViewController *controller) {
+                return vcIsInuse(controller) ? @"In use, cannot push" : nil;
             }
-        };
-    }
-
-    return [super didSelectRowAction:row];
-}
-
-- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row {
-    switch (row) {
-        case 0:
-            if (self.viewControllerIsInUse) {
-                return UITableViewCellAccessoryDisclosureIndicator;
-            } else {
-                return UITableViewCellAccessoryNone;
+            selectionHandler:^void(UIViewController *host, UIViewController *controller) {
+                if (!vcIsInuse(controller)) {
+                    [host.navigationController pushViewController:controller animated:YES];
+                } else {
+                    [FLEXAlert
+                        showAlert:@"Cannot Push View Controller"
+                        message:@"This view controller's view is currently in use."
+                        from:host
+                    ];
+                }
             }
-        default:
-            return [super accessoryTypeForRow:row];
-    }
+            accessoryType:^UITableViewCellAccessoryType(UIViewController *controller) {
+                if (!vcIsInuse(controller)) {
+                    return UITableViewCellAccessoryDisclosureIndicator;
+                } else {
+                    return UITableViewCellAccessoryNone;
+                }
+            }
+        ]
+    ]];
 }
 
 @end