我可以让选择器引用Swift中的闭包吗?
我想让我的方法的我可以让选择器引用Swift中的闭包吗?,swift,closures,selector,Swift,Closures,Selector,我想让我的方法的选择器参数引用一个闭包属性,它们都存在于同一个范围内。比如说, func backgroundChange() { self.view.backgroundColor = UIColor.blackColor() self.view.alpha = 0.55 let backToOriginalBackground = { self.view.backgroundColor = UIColor.whiteColor() s
选择器参数引用一个闭包属性,它们都存在于同一个范围内。比如说,
func backgroundChange() {
self.view.backgroundColor = UIColor.blackColor()
self.view.alpha = 0.55
let backToOriginalBackground = {
self.view.backgroundColor = UIColor.whiteColor()
self.view.alpha = 1.0
}
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(backToOriginalBackground), userInfo: nil, repeats: false)
}
但是,这显示了一个错误:#selector的参数不能引用属性
当然,我可以定义一个新的、单独的方法,并将闭包的实现转移到它,但我希望对于这样一个小的实现保持它的简洁性
是否可以将闭包设置为#selector
参数?否,#selector指的是Objective-C方法
不过,您可以做得更好:向NSTimer添加一个扩展,它允许您创建一个定时计时器,而不是使用目标和选择器,而是使用闭包 否,#选择器指的是Objective-C方法
不过,您可以做得更好:向NSTimer添加一个扩展,它允许您创建一个定时计时器,而不是使用目标和选择器,而是使用闭包 不是直接的,但有些变通方法是可能的。看看下面的例子
/// Target-Action helper.
final class Action: NSObject {
private let _action: () -> ()
init(action: @escaping () -> ()) {
_action = action
super.init()
}
@objc func action() {
_action()
}
}
let action1 = Action { print("action1 triggered") }
let button = UIButton()
button.addTarget(action1, action: #selector(action1.action), forControlEvents: .TouchUpInside)
不是直接的,但有些变通办法是可能的。看看下面的例子
/// Target-Action helper.
final class Action: NSObject {
private let _action: () -> ()
init(action: @escaping () -> ()) {
_action = action
super.init()
}
@objc func action() {
_action()
}
}
let action1 = Action { print("action1 triggered") }
let button = UIButton()
button.addTarget(action1, action: #selector(action1.action), forControlEvents: .TouchUpInside)
如果将块的作用域更改为类作用域而不是函数,并在其中保留对闭包的引用
您可以使用函数调用该闭包。在课堂上。这样,您就可以将该闭包作为选择器调用
大概是这样的:
class Test: NSObject {
let backToOriginalBackground = {
}
func backgroundChange() {
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(test), userInfo: nil, repeats: false)
}
func test() {
self.backToOriginalBackground()
}
}
如果将块的作用域更改为类作用域而不是函数,并在其中保留对闭包的引用
您可以使用函数调用该闭包。在课堂上。这样,您就可以将该闭包作为选择器调用
大概是这样的:
class Test: NSObject {
let backToOriginalBackground = {
}
func backgroundChange() {
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(test), userInfo: nil, repeats: false)
}
func test() {
self.backToOriginalBackground()
}
}
正如@gnasher729所指出的,这是不可能的,因为选择器只是方法的名称,而不是方法本身。在一般情况下,我会在这里使用dispatch\u
,但在这种特殊情况下,更好的工具IMO是UIView.animateWithDuration
,因为它正是该函数的功能所在,并且很容易调整转换:
UIView.animateWithDuration(0, delay: 0.5, options: [], animations: {
self.view.backgroundColor = UIColor.whiteColor()
self.view.alpha = 1.0
}, completion: nil)
正如@gnasher729所指出的,这是不可能的,因为选择器只是方法的名称,而不是方法本身。在一般情况下,我会在这里使用dispatch\u
,但在这种特殊情况下,更好的工具IMO是UIView.animateWithDuration
,因为它正是该函数的功能所在,并且很容易调整转换:
UIView.animateWithDuration(0, delay: 0.5, options: [], animations: {
self.view.backgroundColor = UIColor.whiteColor()
self.view.alpha = 1.0
}, completion: nil)
我的解决方案是创建一个类块变量,如:
let completionBlock: () -> () = nil
创建调用此completionBlock的方法:
func completed(){
self.completionBlock!()
}
我想把选择器放在里面,就像我做的块一样:
func myFunc(){
self.completionBlock = {//what I want to be done}
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(Myclass.completed), userInfo: nil, repeats: false)
}
我的解决方案是创建一个类块变量,如:
let completionBlock: () -> () = nil
创建调用此completionBlock的方法:
func completed(){
self.completionBlock!()
}
我想把选择器放在里面,就像我做的块一样:
func myFunc(){
self.completionBlock = {//what I want to be done}
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(Myclass.completed), userInfo: nil, repeats: false)
}
因此,我对将选择器
以类似快捷的方式分配给闭包
的回答类似于已经给出的一些答案,但我想我会分享一个真实的例子,说明我是如何在UIViewController
扩展中这样做的
fileprivate class BarButtonItem: UIBarButtonItem {
var actionCallback: ( () -> Void )?
func buttonAction() {
actionCallback?()
}
}
fileprivate extension Selector {
static let onBarButtonAction = #selector(BarButtonItem.buttonAction)
}
extension UIViewController {
func createBarButtonItem(title: String, action: @escaping () -> Void ) -> UIBarButtonItem {
let button = BarButtonItem(title: title, style: .plain, target nil, action: nil)
button.actionCallback = action
button.action = .onBarButtonAction
return button
}
}
// Example where button is inside a method of a UIViewController
// and added to the navigationItem of the UINavigationController
let button = createBarButtonItem(title: "Done"){
print("Do something when done")
}
navigationItem.setLeftbarButtonItems([button], animated: false)
因此,我对将选择器
以类似快捷的方式分配给闭包
的回答类似于已经给出的一些答案,但我想我会分享一个真实的例子,说明我是如何在UIViewController
扩展中这样做的
fileprivate class BarButtonItem: UIBarButtonItem {
var actionCallback: ( () -> Void )?
func buttonAction() {
actionCallback?()
}
}
fileprivate extension Selector {
static let onBarButtonAction = #selector(BarButtonItem.buttonAction)
}
extension UIViewController {
func createBarButtonItem(title: String, action: @escaping () -> Void ) -> UIBarButtonItem {
let button = BarButtonItem(title: title, style: .plain, target nil, action: nil)
button.actionCallback = action
button.action = .onBarButtonAction
return button
}
}
// Example where button is inside a method of a UIViewController
// and added to the navigationItem of the UINavigationController
let button = createBarButtonItem(title: "Done"){
print("Do something when done")
}
navigationItem.setLeftbarButtonItems([button], animated: false)
现在这是可能的。我为Swift 4中基于块的选择器创建了一个要点
用法:
UIButton().addTarget(选择器,操作:选择器{debugPrint(“我的代码在这里”)},用于:.touchUpInside)`
现在可以了。我为Swift 4中基于块的选择器创建了一个要点
用法:
UIButton().addTarget(选择器,操作:选择器{debugPrint(“我的代码在这里”)},用于:.touchUpInside)`
我至少为UIBarbuttonite尝试了以下方法:
private var actionKey: Void?
extension UIBarButtonItem {
private var _action: () -> () {
get {
return objc_getAssociatedObject(self, &actionKey) as! () -> ()
}
set {
objc_setAssociatedObject(self, &actionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
convenience init(title: String?, style: UIBarButtonItemStyle, action: @escaping () -> ()) {
self.init(title: title, style: style, target: nil, action: #selector(pressed))
self.target = self
self._action = action
}
@objc private func pressed(sender: UIBarButtonItem) {
_action()
}
}
然后你可以这样做:
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Test", style: .plain, action: {
print("Hello World!")
})
我试过这个,至少是为了维吾尔人:
private var actionKey: Void?
extension UIBarButtonItem {
private var _action: () -> () {
get {
return objc_getAssociatedObject(self, &actionKey) as! () -> ()
}
set {
objc_setAssociatedObject(self, &actionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
convenience init(title: String?, style: UIBarButtonItemStyle, action: @escaping () -> ()) {
self.init(title: title, style: style, target: nil, action: #selector(pressed))
self.target = self
self._action = action
}
@objc private func pressed(sender: UIBarButtonItem) {
_action()
}
}
然后你可以这样做:
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Test", style: .plain, action: {
print("Hello World!")
})
您可以使用支持UIControl、UIButton、UIRefreshControl、UIGestureRecognitor和UIBarButtonItem的ActionClosurable。
下面展示了一个uibarbuttonite的例子
// UIBarButtonItem
let barButtonItem = UIBarButtonItem(title: "title", style: .plain) { _ in
print("barButtonItem title")
}
您可以使用支持UIControl、UIButton、UIRefreshControl、UIGestureRecognitor和UIBarButtonItem的ActionClosurable。
下面展示了一个uibarbuttonite的例子
// UIBarButtonItem
let barButtonItem = UIBarButtonItem(title: "title", style: .plain) { _ in
print("barButtonItem title")
}
@韦雷迪弗的回答很好。这里有一个更新,允许您将其作为函数调用
<代码>导入基础
公共扩展选择器{
///将闭包包装在“选择器”中。
///-注意:可作为函数调用。
最后一个类执行:NSObject{
public init(u-perform:@escaping()->Void){
self.perform=perform
super.init()
}
私有让执行:()->无效
}
}
//马克:公众
公共扩展选择器。执行{
@objc func callAsFunction(){perform()}
变量选择器:选择器{#选择器(callAsFunction)}
}
您需要管理对选择器的强引用。执行s。一种方法是对设计用于目标操作的UIKit类进行子类化:
///包装闭包的“UITapgestureRecognitor”。
公共最终类TapGestureRecognitor:UITapGestureRecognitor{
public init(u-perform:@escaping()->Void){
self.perform=.init(执行)
super.init(目标:self.perform,操作:self.perform.selector)
}
public-let-perform:Selector.perform
}
让tapRecognizer=TapGestureRecognizer{print(@werediver的答案非常好。下面是一个更新,允许您将其作为函数调用
<代码>导入基础
公共扩展选择器{
///将闭包包装在“选择器”中。
///-注意:可作为函数调用。
最后一个类执行:NSObject{
public init(u-perform:@escaping()->Void){
self.perform=perform
super.init()
}
私有让执行:()->无效
}
}
//马克:公众
公共扩展选择器。执行{
@objc func callAsFunction(){perform()}
变量选择器:选择器{#选择器(