在Swift中使用TapGestures

Swift的上一个主要更新的一部分已经发布了许多重大改进。

Swift越来越大,我认为它所采取的方向确实很有希望。

另一方面,确实某些苹果API尚不希望人们利用Swift的所有这些新功能来获得最理想的接口。

如果您在tvOS项目中工作,那么您将不得不经常使用其中之一,那就是UITapGesturesRecognizer,这是为Siri Remote创建自定义手势的一种非常常见的方式。

更具体地说,我说的是为他们设置允许的触摸和按动类型的方式。

 让手势= UITapGestureRecognizer(目标:自我,行动​​:#选择器(触发)) 
 手势.allowedPressTypes = [NSNumber(值:UIPressType.menu.rawValue)] 
手势.allowedTouchTypes = [NSNumber(value:UITouchType.indirect.rawValue)]
  view.addGestureRecognizer(手势) 

之前的代码是用Swift 3编写的,但是您可以在下面的内容中找到最近几年的发展:

  // Objective-C: 
手势.allowedPressTypes = @ [@ UIPressTypeMenu];
gesture.allowedTouchTypes = @ [@ UITouchTypeIndirect];
  // Swift 2: 
pose.allowedPressTypes = [UIPressType.Menu.rawValue]
pose.allowedTouchTypes = [UITouchType.Indirect.rawValue]
  // Swift 3: 
gesture.allowedPressTypes = [NSNumber(值:UIPressType.menu.rawValue)]
gesture.allowedTouchTypes = [NSNumber(值:UITouchType.indirect.rawValue)]

如您所见,每次迭代都使此代码变得越来越难读,从而增加了从NSNumber的演变继承而来的冗余冗长性。

几天前,由于我们正在将Zattoo迁移到Swift 3,我与同事Chris Goldsby先生谈到了这个问题。

而且…他给了我一个好主意。 实际上,获得像克里斯先生所希望的那样清晰易读的界面并不难。

毕竟,这两个属性只是NSNumbers的数组。 创建它们应该不难吗? 我们需要做的就是扩展功能,以便为不同的按键和触摸类型创建一组预定义的NSNumber。

 扩展名NSNumber { 
静态var菜单:NSNumber {
返回NSNumber(pressType:.menu)
}
 静态var playPause:NSNumber { 
返回NSNumber(pressType:.playPause)
}
 静态var选择:NSNumber { 
返回NSNumber(pressType:.select)
}
 静态var upArrow:NSNumber { 
返回NSNumber(pressType:.upArrow)
}

静态var downArrow:NSNumber {
返回NSNumber(pressType:.downArrow)
}
 静态var leftArrow:NSNumber { 
返回NSNumber(pressType:.leftArrow)
}
 静态var rightArrow:NSNumber { 
返回NSNumber(pressType:.rightArrow)
}
  // MARK:-私人 

私人便利init(pressType:UIPressType){
self.init(integerLiteral:pressType.rawValue)
}
}
 扩展名NSNumber { 
静态var直接:NSNumber {
返回NSNumber(touchType:.direct)
}
 静态var间接:NSNumber { 
返回NSNumber(touchType:.indirect)
}
  // MARK:-私人 

私人便利init(touchType:UITouchType){
self.init(integerLiteral:touchType.rawValue)
}
}

仅此而已…我们已经可以以更加可读的方式定义手势识别器:

 让手势= UITapGestureRecognizer(目标:自我,动作:.upDownGestureWasTriggered) 
  pose.allowedPressTypes = [.upArrow,.downArrow] 
pose.allowedTouchTypes = [.indirect]
  view.addGestureRecognizer(手势) 

{关闭,所有事情!!! }

好吧…实际上还不是全部…

很抱歉,但是我目前还无法完成本篇文章,谈论使UITapGestureRecognizers更具可读性,同时最后提供与Selectors配合使用的界面。

选择器是许多Apple API提供的出色接口,并且功能强大。

但是事实是选择器来自目标C,并利用objc运行时与动态调度一起工作。 我非常确定,它们将在不久的将来被闭包取代。

好的方面是,仅需一点点创意和可折叠性,我们就可以从Selectors中获得更快速的界面。

 最后一堂TapGestureRecognizer:UITapGestureRecognizer { 
私人让回调:()->无效

公共初始化(allowedPressTypes:[NSNumber] = [],allowedTouchTypes:[NSNumber] = [.indirect],回调:@escaping()-> Void){
self.callback =回调
super.init(目标:无,动作:无)
self.allowedPressTypes = allowedPressTypes
self.allowedTouchTypes = allowedTouchTypes
addTarget(self,action:#selector(invokeCallback))
}
  // MARK:—私人 

@objc private func invokeCallback(){
打回来()
}
}

仅此而已(再次)。 我们已经可以以更加可读和快速的方式定义手势识别器:

 让手势= TapGestureRecognizer(allowedPressTypes:[.menu]){ 
//按下菜单键
}
view.addGestureRecognizer(手势)

结论

Apple可能(并希望)很快会给仍然需要它的那些API带来所有的爱和温柔,但是与此同时,它们是创造力的好借口,因此获得了更具可读性的代码……别害羞! !!