0

I'm new to Swift and I'm trying to implement a custom UIKeyCommand architecture in a practice app. I wrote the extension below for the base UISplitViewController to show all UIKeyCommands in the current views on screen.

extension UISplitViewController {
    open override var canBecomeFirstResponder: Bool {
        return true
    }

    var BPKeyCommands: [BPKeyCommand]? {
        var commands: [BPKeyCommand] = []

        var mastervc = self.viewControllers.first
        if (mastervc is UINavigationController) {
            mastervc = (mastervc as! UINavigationController).viewControllers.last
        }
        if let masterCommands = mastervc.commands {
            for command in masterCommands {
                commands.append(command)
            }
        }

        return commands
    }

    open override var keyCommands: [UIKeyCommand]? {
        var commands: [UIKeyCommand] = []

        if let bpkeycommands = BPKeyCommands {
            for command in bpkeycommands {
                let new = UIKeyCommand(input: command.input,
                                       modifierFlags: command.modifierFlags,
                                       action: #selector(executeKeyCommand(sender:)),
                                       discoverabilityTitle: command.title)
                commands.append(new)
            }
        }

        return commands
    }

    @objc private func executeKeyCommand(sender: UIKeyCommand) {
        if let index = keyCommands?.firstIndex(of: sender) {
            if let command = BPKeyCommands?[index] {
                command.action(command)
            }
        }
    }
}

Now, as you might expect this throws an error at if let masterCommands = mastervc.commands {, because UIViewController doesn't contain the commands variable out of the box. My question is: how can I haveUIViewControllerhave that variable? Just like all controllers can overridekeyCommands` by default?

Tanvir Nayem
  • 702
  • 10
  • 25
user4992124
  • 1,574
  • 1
  • 17
  • 35

2 Answers2

2

You have to create a protocol with command variable and make your view controller conform to it (step 1). Either you can provide values for particular view controller or you can provide a default implementation.

step 1:- Create a protocol with the variable you need.

protocol Commandable{
   var commands: [String]{set get}
}
extension Commandable{
   var commands: [String]{
        get{return ["hello","world"]}
        set{}
    }
}

step 2:- Make then controllers which you are using conform it

step 3:- change the above code to get commands

if let commandProtocol = masterVC as? Commandable
{
    let commands = commandProtocol.commands
}
else{
    // handle it
}

Make sure the variable is unique so you don't accidentally override it.

Thank you.

0

you can create a extension of UIViewController and add that property on that extension of UIViewController. Then You will get it on child view controllers like UISplitViewController or any other custom ViewControllers. To know more about extensions, Which can be added on extension or what can be done by extension??

Md. Sulayman
  • 781
  • 8
  • 30