Last active
April 12, 2019 07:15
-
-
Save danielctull/732ada6245d448dbb91fee22478b99e3 to your computer and use it in GitHub Desktop.
Shows selection of table view cells on pressing the up/down arrow keys.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation AppDelegate | |
#pragma mark - Key Command Controller | |
- (KeyCommandController *)keyCommandController { | |
if (!_keyCommandController) { | |
UIViewController *rootViewController = self.window.rootViewController; | |
if (rootViewController){ | |
_keyCommandController = [[KeyCommandController alloc] initWithRootViewController:rootViewController]; | |
} | |
} | |
return _keyCommandController; | |
} | |
// Make the KeyCommandController part of the responder chain. | |
- (UIResponder *)nextResponder { | |
return self.keyCommandController; | |
} | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation IssuesViewController | |
- (NSArray<UIKeyCommand *> *)keyCommands { | |
NSMutableArray<UIKeyCommand *> *commands = [NSMutableArray new]; | |
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:(UIKeyModifierFlags)0 action:@selector(selectPreviousIssue:) discoverabilityTitle:@"Select Previous Issue"]]; | |
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:(UIKeyModifierFlags)0 action:@selector(selectNextIssue:) discoverabilityTitle:@"Select Next Issue"]]; | |
return commands; | |
} | |
- (IBAction)selectNextIssue:(id)sender { | |
[self selectIndexPath:self.nextIndexPath]; | |
} | |
- (IBAction)selectPreviousIssue:(id)sender { | |
[self selectIndexPath:self.previousIndexPath]; | |
} | |
- (void)selectIndexPath:(NSIndexPath *)indexPath { | |
if (!indexPath) return; | |
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; | |
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES]; | |
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; | |
[self performSegueWithIdentifier:@"issue" sender:cell]; | |
} | |
- (NSIndexPath *)previousIndexPath { | |
NSIndexPath *selectedIndexPath = self.tableView.indexPathForSelectedRow; | |
if (!selectedIndexPath) { | |
return [self lastIndexPath]; | |
} | |
NSInteger selectedRow = selectedIndexPath.row; | |
// Loop round to the end | |
if (selectedRow == 0) { | |
return [self lastIndexPath]; | |
} | |
return [NSIndexPath indexPathForRow:selectedRow - 1 inSection:0]; | |
} | |
- (NSIndexPath *)nextIndexPath { | |
NSIndexPath *selectedIndexPath = self.tableView.indexPathForSelectedRow; | |
if (!selectedIndexPath) { | |
return [self firstIndexPath]; | |
} | |
NSInteger rows = [self.tableView numberOfRowsInSection:0]; | |
NSInteger selectedRow = selectedIndexPath.row; | |
// Loop round to the start | |
if (rows - 1 <= selectedRow) { | |
return [self firstIndexPath]; | |
} | |
return [NSIndexPath indexPathForRow:selectedRow + 1 inSection:0]; | |
} | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
public class KeyCommandController: UIResponder { | |
public let rootViewController: UIViewController | |
public init(rootViewController: UIViewController) { | |
self.rootViewController = rootViewController | |
} | |
// Lets have the this become the first responder and go through all | |
// the view controllers and combine all their key commands. We need to make | |
// a note of which key commands belong to which view controller so we can | |
// provide the view controller in targetForAction(:withSender:) later on. | |
// The sender in that case is the key command, so we can just store a | |
// dictionary of key commands to view controllers. | |
var targets: [UIKeyCommand : UIViewController] = [:] | |
override public var keyCommands: [UIKeyCommand]? { | |
var commands: [UIKeyCommand] = [] | |
var targets: [UIKeyCommand : UIViewController] = [:] | |
rootViewController.recurseVisibleChildViewControllers { viewController in | |
guard let viewControllerCommands = viewController.keyCommands else { | |
return | |
} | |
for command in viewControllerCommands { | |
commands.append(command) | |
targets[command] = viewController | |
} | |
} | |
self.targets = targets | |
return commands | |
} | |
override public func canBecomeFirstResponder() -> Bool { | |
return true | |
} | |
override public func targetForAction(action: Selector, withSender sender: AnyObject?) -> AnyObject? { | |
guard let command = sender as? UIKeyCommand else { | |
return nil | |
} | |
return targets[command] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment