Arb*_*tur 647 selector nstimer swift
我正在尝试创建一个NSTimer
in Swift
但我遇到了一些麻烦.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
Run Code Online (Sandbox Code Playgroud)
test()
是同一个类中的函数.
我在编辑器中收到错误:
找不到接受提供的参数的'init'的重载
当我改变selector: test()
到selector: nil
错误消失.
我试过了:
selector: test()
selector: test
selector: Selector(test())
但没有任何作用,我在参考文献中找不到解决方案.
ric*_*ter 920
Swift 本身不使用选择器 - 在Objective-C中使用选择器的几种设计模式在Swift中的工作方式不同.(例如,在协议类型或is
/ as
tests 上使用可选链接代替respondsToSelector:
,并在任何地方使用闭包,而不是performSelector:
为了更好的类型/内存安全性.)
但是仍然有许多基于ObjC的重要API使用选择器,包括定时器和目标/动作模式.Swift提供了Selector
使用它们的类型.(Swift自动使用它来代替ObjC的SEL
类型.)
您可以Selector
使用#selector
表达式从Swift函数类型构造一个.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
Run Code Online (Sandbox Code Playgroud)
关于这种方法的好处是什么?函数引用由Swift编译器检查,因此您只能将#selector
表达式用于实际存在且可用作选择器的类/方法对(请参阅下面的"选择器可用性").根据Swift 2.2+函数类型命名规则,您也可以根据需要自由选择函数.
(这实际上是对ObjC @selector()
指令的改进,因为编译器的-Wundeclared-selector
检查仅验证指定的选择器是否存在.您传递的Swift函数引用#selector
检查存在,类的成员资格和类型签名.)
您传递给#selector
表达式的函数引用还有一些额外的注意事项:
insertSubview(_:at:)
vs insertSubview(_:aboveSubview:)
)来区分.但是如果函数没有参数,则消除歧义的唯一方法是使用as
具有函数类型签名的强制转换(例如foo as () -> ()
vs foo(_:)
).var foo: Int
,您可以使用#selector(getter: MyClass.foo)
或#selector(setter: MyClass.foo)
.情况下#selector
不能正常工作,并命名:有时候你没有一个函数的引用,使一个选择器(例如,用在ObjC运行时动态注册的方法).在这种情况下,您可以Selector
从字符串构造一个:例如Selector("dynamicMethod:")
- 虽然您丢失了编译器的有效性检查.执行此操作时,您需要遵循ObjC命名规则,包括:
每个参数的冒号().
选择器可用性:选择器引用的方法必须公开给ObjC运行时.在Swift 4中,暴露给ObjC的每个方法都必须在声明前面加上@objc
属性.(在以前的版本中,在某些情况下,您可以免费获得该属性,但现在您必须明确声明它.)
请记住,private
符号也不会暴露给运行时 - 您的方法至少需要具有internal
可见性.
关键路径:这些与选择器相关但不完全相同.在Swift 3中也有一些特殊的语法:例如chris.valueForKeyPath(#keyPath(Person.friends.firstName))
.有关详细信息,请参阅SE-0062.KeyPath
在Swift 4中还有更多东西,所以请确保在适当的时候使用正确的基于KeyPath的API而不是选择器.
您可以在使用Swift with Cocoa和Objective-C的" 与Objective-C API交互"下阅读有关选择器的更多信息.
注意:在Selector
符合Swift 2.2之前StringLiteralConvertible
,您可能会发现旧代码将裸字符串传递给采用选择器的API.您将要在Xcode中运行"转换为当前Swift语法"以获取使用它们#selector
.
Osc*_*ros 84
这是一个关于如何Selector
在Swift 上使用该类的快速示例:
override func viewDidLoad() {
super.viewDidLoad()
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
self.navigationItem.rightBarButtonItem = rightButton
}
func method() {
// Something cool here
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果作为字符串传递的方法不起作用,它将在运行时失败,而不是编译时间,并使应用程序崩溃.小心
小智 46
此外,如果您的(Swift)类不是从Objective-C类下降,那么您必须在目标方法名称字符串的末尾添加冒号,并且必须将@objc属性与目标方法一起使用,例如
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
Run Code Online (Sandbox Code Playgroud)
否则您将在运行时收到"无法识别的选择器"错误.
Kyl*_*egg 31
Swift 2.2+和Swift 3更新
使用新#selector
表达式,这消除了使用字符串文字的需要,使得使用不易出错.以供参考:
Selector("keyboardDidHide:")
Run Code Online (Sandbox Code Playgroud)
变
#selector(keyboardDidHide(_:))
Run Code Online (Sandbox Code Playgroud)
注意(Swift 4.0):
如果使用#selector
,则需要将该功能标记为@objc
例:
@objc func something(_ sender: UIButton)
Rob*_*ers 23
对于未来的读者,我发现我遇到了一个问题,并且因为unrecognised selector sent to instance
将目标标记func
为私有而导致错误.
在func
必须公开显示通过与到选择的参考对象被调用.
小智 22
Swift 4.0
你创建如下所示的选择器.
1.将事件添加到如下按钮:
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
Run Code Online (Sandbox Code Playgroud)
功能如下:
@objc func clickedButton(sender: AnyObject) {
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*res 19
为了防止其他人遇到与NSTimer相同的问题,其中没有其他答案解决了这个问题,非常重要的是,如果你使用的是一个不直接或深层次地从NSObject继承的类(例如,手动创建swift文件),即使指定如下,其他任何答案都不会起作用:
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
Run Code Online (Sandbox Code Playgroud)
除了让类继承自NSObject之外,我没有改变任何其他东西,我停止了"无法识别的选择器"错误并使我的逻辑按预期工作.
Sco*_*ter 14
如果您想将参数从NSTimer传递给函数,那么这是您的解决方案:
var somethingToPass = "It worked"
let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)
func tester(timer: NSTimer)
{
let theStringToPrint = timer.userInfo as String
println(theStringToPrint)
}
Run Code Online (Sandbox Code Playgroud)
在选择器文本(tester :)中包含冒号,您的参数在userInfo中.
您的函数应该将NSTimer作为参数.然后只需提取userInfo即可获取传递的参数.
Jon*_*ros 10
选择器是Objective-C中方法名称的内部表示.在Objective-C中,"@ selector(methodName)"会将源代码方法转换为SEL的数据类型.由于您无法在Swift中使用@selector语法(rickster就在那里),您必须直接手动将方法名称指定为String对象,或者将String对象传递给Selector类型.这是一个例子:
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:"logout"
)
Run Code Online (Sandbox Code Playgroud)
要么
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
Run Code Online (Sandbox Code Playgroud)
Swift 4.1
带有轻拍手势的样本
let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))
// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))
@objc func dismiss(completion: (() -> Void)?) {
self.dismiss(animated: true, completion: completion)
}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅Apple的文档:选择器表达式
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)
// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)
func tappedButton() {
print("tapped")
}
func tappedButton2(sender: UIButton) {
print("tapped 2")
}
// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton) {
// tapped
}
button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)
func tappedButton(_ sender: UIButton, _ event: UIEvent) {
// tapped
}
Run Code Online (Sandbox Code Playgroud)
Objective-C 选择器
选择器标识一个方法。
//Compile time
SEL selector = @selector(foo);
//Runtime
SEL selector = NSSelectorFromString(@"foo");
Run Code Online (Sandbox Code Playgroud)
例如
[object sayHello:@"Hello World"];
//sayHello: is a selector
Run Code Online (Sandbox Code Playgroud)
selector
是来自 world 的一个词Objective-C
,您可以使用它 fromSwift
来调用Objective-C
fromSwift
它允许您在运行时执行一些代码
之前的Swift 2.2
语法是:
Selector("foo:")
Run Code Online (Sandbox Code Playgroud)
Selector
由于函数名称作为参数传递String
(“foo”),因此不可能在编译时检查名称。结果你可能会得到一个运行时错误:
unrecognized selector sent to instance
Run Code Online (Sandbox Code Playgroud)
之后的Swift 2.2+
语法是:
#selector(foo(_:))
Run Code Online (Sandbox Code Playgroud)
Xcode 的自动完成功能可帮助您调用正确的方法
Create Refresh control using Selector method.
var refreshCntrl : UIRefreshControl!
refreshCntrl = UIRefreshControl()
refreshCntrl.tintColor = UIColor.whiteColor()
refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
atableView.addSubview(refreshCntrl)
Run Code Online (Sandbox Code Playgroud)
//刷新控制方法
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
Run Code Online (Sandbox Code Playgroud)
自从Swift 3.0发布以来,声明一个适当的targetAction甚至更加微妙
class MyCustomView : UIView {
func addTapGestureRecognizer() {
// the "_" is important
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// since Swift 3.0 this "_" in the method implementation is very important to
// let the selector understand the targetAction
func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {
if tapGesture.state == .ended {
print("TapGesture detected")
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
301338 次 |
最近记录: |