Skip to content

Instantly share code, notes, and snippets.

@amelnychuck
Created July 27, 2017 23:23
Show Gist options
  • Save amelnychuck/4cc03b252d2f8ebf8a8b05dade7d07e5 to your computer and use it in GitHub Desktop.
Save amelnychuck/4cc03b252d2f8ebf8a8b05dade7d07e5 to your computer and use it in GitHub Desktop.
Example of why we need closures to replace the last instances of #selectors in Cocoa Touch
import UIKit
class TabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: Keyboard Commands
override internal var keyCommands: [UIKeyCommand]? {
guard let controllers = viewControllers else {
return nil
}
var commands = [UIKeyCommand]()
for controller in controllers {
if let index = tabBar.items?.index(of: controller.tabBarItem) {
var pressedAction: Selector?
switch index {
case 0:
pressedAction = #selector(TabBarViewController.pressed1)
case 1:
pressedAction = #selector(TabBarViewController.pressed2)
case 2:
pressedAction = #selector(TabBarViewController.pressed3)
default:
break
}
if let action = pressedAction {
let command = UIKeyCommand(input: String(describing: index + 1), modifierFlags: .command, action: action, discoverabilityTitle: controller.tabBarItem.title!)
commands.append(command)
}
}
}
return commands
}
@objc func pressed1() {
selectedIndex = 0
}
@objc func pressed2() {
selectedIndex = 1
}
@objc func pressed3() {
selectedIndex = 2
}
}
@leonardpauli
Copy link

Explored some additional choises; (I find syntax to be quite intriguing... pondering about writing my own...:) )

Swift; more functional

import UIKit

class TabBarViewController: UITabBarController {
  
  // MARK: Keyboard Commands
  var keyCommandsMap:[String:Int] = [:]
  override internal var keyCommands: [UIKeyCommand]? {
    let getInput = { (i: Int) -> String in
      let key = "\(i + 1)"
      return keyCommandsMap[key] = i
    }

    return viewControllers?.map {$0.tabBarItem}.map {(
        index: tabBar.items?.index(of: $0),
        item: $0
      )}.filter {$0.index != nil}.map {UIKeyCommand(
        input: getInput($0.index!),
        modifierFlags: .command,
        action: #selector(TabBarViewController.pressed),
        discoverabilityTitle: $0.item.title!
      )}
  }

  @objc func pressed(sender: UIKeyCommand) {
    guard let index = keyCommandsMap[sender.input] else { return }
    selectedIndex = index
  }
  
}

Swift; if closures were supported instead of selectors

import UIKit

class TabBarViewController: UITabBarController {
  
  // MARK: Keyboard Commands
  override internal var keyCommands: [UIKeyCommand]? {
    return viewControllers?.map {$0.tabBarItem}.map {(
        index: tabBar.items?.index(of: $0),
        item: $0
      )}.filter {$0.index != nil}.map {UIKeyCommand(
        input: "\($0.index! + 1)",
        modifierFlags: .command,
        discoverabilityTitle: $0.item.title!
      ) { [weak self] in self.selectedIndex = $0.index! }}
  }
  
}

LiteScript; Superset of ES7 JavaScript

import { UITabBarController, UIKeyCommand } from 'UIKit'

class TabBarViewController extends UITabBarController
  
  keyCommands() -get>
    this.viewControllers?.map(v-> v.tabBarItem)
      .map(item-> ({item, index: tabBar.items?.indexOf(item)}))
      .filter(({index})-> index)
      .map(({index, item})-> new UIKeyCommand({
        input: index+1+''
        modifierFlags: 'command'
        discoverabilityTitle: item.title
        action: ()=> this.selectedIndex = index
      })

Custom syntax; direct translation

import from UIKit: UITabBarController, UIKeyCommand

TabBarViewController inherits UITabBarController
  keyCommands: viewControllers?
    | map: .tabBarItem
    | map as item: {item, index: tabBar.items?.indexOf item}
    | filter: .index?
    | map: UIKeyCommand
      input: .index+1
      modifiers: :command
      title: .item.title
      on action: selectedIndex= .index

Custom syntax; how I think I would like to write it

import from UIKit: UITabBarController, UIKeyCommand

TabBarViewController inherits UITabBarController
  keyCommands: if viewControllers: iterate them:
    item: its tabBarItem
    index: tabBar.items?.indexOf item
    skip if !index
    yield UIKeyCommand
      input: index+1
      modifiers: :command
      title: item.title
      on action: selectedIndex= index

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment