I'm using UIKeyCommand
to map certain shortcuts (for example "b", arrow keys, "t", "p", etc.) to a functionality inside my UIViewController
subclass. The app is kind of a vector graphics software, which allows addition of text objects inside the canvas. The problem arises when a textView or textField inside the view controller is being edited. While it gets the first responder status, it doesn't receive the shortcut keys (for example writing "beaver" will result in "eaver").
Is there a correct way to handle shortcut keys AND use text objects inside a single view controller?
The solution I found to work best is to go through the responder chain to find the active responder and then check whether it is a UITextField
/UITextView
or something else. In case it is, return nil from the - (NSArray *)keyCommands
method, otherwise return the shortcuts.
Here's the code itself:
@implementation UIResponder (CMAdditions)
- (instancetype)cm_activeResponder {
UIResponder *activeResponder = nil;
if (self.isFirstResponder) {
activeResponder = self;
} else if ([self isKindOfClass:[UIViewController class]]) {
if ([(UIViewController *)self parentViewController]) {
activeResponder = [[(UIViewController *)self parentViewController] cm_activeResponder];
}
if (!activeResponder) {
activeResponder = [[(UIViewController *)self view] cm_activeResponder];
}
} else if ([self isKindOfClass:[UIView class]]) {
for (UIView *subview in [(UIView *)self subviews]) {
activeResponder = [subview cm_activeResponder];
if (activeResponder) break;
}
}
return activeResponder;
}
@end
And this goes inside the keyCommands
method:
- (NSArray *)keyCommands {
if ([self.cm_activeResponder isKindOfClass:[UITextView class]] || [self.cm_activeResponder isKindOfClass:[UITextField class]]) {
return nil;
}
UIKeyCommand *brushTool = [UIKeyCommand keyCommandWithInput:@"b"
modifierFlags:kNilOptions
action:@selector(brushToolEnabled)
discoverabilityTitle:NSLocalizedString(@"Brush tool", @"Brush tool")];
UIKeyCommand *groupKey = [UIKeyCommand keyCommandWithInput:@"g"
modifierFlags:UIKeyModifierCommand
action:@selector(groupKeyPressed)
discoverabilityTitle:NSLocalizedString(@"Group", @"Group")];
UIKeyCommand *ungroupKey = [UIKeyCommand keyCommandWithInput:@"g"
modifierFlags:UIKeyModifierCommand|UIKeyModifierShift
action:@selector(ungroupKeyPressed)
discoverabilityTitle:NSLocalizedString(@"Ungroup", @"Ungroup")];
return @[groupKey, ungroupKey, brushTool];
}