@selector () in Swift?
나는 만들려고 해요 NSTimer
에서을 Swift
하지만 몇 가지 문제가 있어요.
NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
같은 클래스의 함수입니다.
편집기에서 오류가 발생합니다.
제공된 인수를 허용하는 'init'에 대한 오버로드를 찾을 수 없습니다.
나는 변경하는 경우 selector: test()
에 selector: nil
오류 사라집니다.
난 노력 했어:
selector: test()
selector: test
selector: Selector(test())
그러나 아무것도 작동하지 않으며 참조에서 해결책을 찾을 수 없습니다.
Swift 자체 는 선택기를 사용하지 않습니다. Objective-C에서 선택기를 사용하는 몇 가지 디자인 패턴은 Swift에서 다르게 작동합니다. (예를 들어, 프로토콜 유형 또는 is
/ as
테스트 에 대해 선택적 체인을 respondsToSelector:
사용 performSelector:
하고 더 나은 유형 / 메모리 안전성 대신 가능한 곳에서 클로저를 사용하십시오 .)
그러나 타이머 및 대상 / 동작 패턴을 포함하여 선택기를 사용하는 중요한 ObjC 기반 API가 여전히 많이 있습니다. Swift는 Selector
이러한 작업을위한 유형을 제공합니다 . (Swift는 ObjC의 SEL
유형 대신 자동으로 이것을 사용 합니다.)
Swift 2.2 (Xcode 7.3) 이상 (Swift 3 / Xcode 8 및 Swift 4 / Xcode 9 포함) :
표현식을 Selector
사용하여 Swift 함수 유형에서 를 생성 할 수 있습니다 #selector
.
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)
이 접근 방식의 장점은 무엇입니까? 함수 참조는 Swift 컴파일러에 의해 확인되므로 #selector
실제로 존재하고 선택 자로 사용할 수있는 클래스 / 메서드 쌍으로 만 표현식을 사용할 수 있습니다 (아래 "선택기 사용 가능성"참조). 또한 함수 유형 명명에 대한 Swift 2.2+ 규칙에 따라 필요한만큼만 함수 참조를 자유롭게 만들 수 있습니다 .
( @selector()
컴파일러의 -Wundeclared-selector
검사는 명명 된 선택자가 존재하는지 만 확인 하기 때문에 이것은 실제로 ObjC의 지시문 보다 개선 된 것입니다. 사용자가 전달하는 Swift 함수 참조 #selector
는 존재, 클래스의 멤버쉽 및 유형 서명을 확인합니다.)
#selector
표현식에 전달하는 함수 참조에 대한 몇 가지 추가주의 사항이 있습니다 .
- 기본 이름이 동일한 여러 함수 는 함수 참조 (예 :
insertSubview(_:at:)
vsinsertSubview(_:aboveSubview:)
)에 대해 앞서 언급 한 구문을 사용하여 매개 변수 레이블로 구분할 수 있습니다 . 그러나 함수에 매개 변수가없는 경우이를 명확히하는 유일한 방법as
은 함수의 유형 서명 (예 :foo as () -> ()
vsfoo(_:)
) 과 함께 캐스트 를 사용하는 것입니다 . - Swift 3.0 이상에는 속성 getter / setter 쌍에 대한 특수 구문이 있습니다. 예를 들어,가 주어지면 또는
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를 사용하고 있는지 확인하십시오.
당신은 아래 선택기에 대한 자세한 읽을 수 오브젝티브 C API를 상호 작용 에 코코아 및 목표 - C와 스위프트를 사용 .
참고 : Swift 2.2 이전에는을 Selector
준수 StringLiteralConvertible
하므로 선택기를 사용하는 API에 베어 문자열이 전달되는 이전 코드를 찾을 수 있습니다. Xcode에서 "Convert to Current Swift Syntax"를 실행하여 #selector
.
다음 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
}
문자열로 전달 된 메서드가 작동하지 않으면 컴파일 타임이 아닌 런타임에 실패하고 앱이 충돌합니다. 조심해
또한 (Swift) 클래스가 Objective-C 클래스의 하위 클래스가 아닌 경우 대상 메서드 이름 문자열 끝에 콜론이 있어야하며 대상 메서드와 함께 @objc 속성을 사용해야합니다.
var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
@objc func method() {
// Something cool here
}
그렇지 않으면 런타임에 "Unrecognised Selector"오류가 발생합니다.
Swift 2.2+ 및 Swift 3 업데이트
새로운 #selector
표현식을 사용하면 문자열 리터럴을 사용할 필요가 없으므로 오류 발생 가능성이 줄어 듭니다. 참고로 :
Selector("keyboardDidHide:")
된다
#selector(keyboardDidHide(_:))
더보기 : Swift Evolution Proposal
참고 (Swift 4.0) :
사용 #selector
하는 경우 기능을 다음과 같이 표시해야합니다.@objc
예:
@objc func something(_ sender: UIButton)
미래의 독자를 위해 나는 문제 unrecognised selector sent to instance
가 발생했으며 대상 func
을 비공개로 표시하여 발생한 오류를 발견했습니다 .
는 func
반드시 셀렉터에 대한 참조 목적으로 불릴 공개적으로 표시.
스위프트 4.0
아래와 같이 선택기를 만듭니다.
1. 다음과 같은 버튼에 이벤트를 추가합니다.
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
기능은 다음과 같습니다.
@objc func clickedButton(sender: AnyObject) {
}
다른 답변이 문제를 해결하지 않은 NSTimer에서 내가 가진 동일한 문제를 다른 사람이 가진 경우를 대비하여 NSObject에서 직접 또는 계층 구조에서 상속되지 않는 클래스를 사용하는 경우 언급하는 것이 정말 중요합니다 ( 예를 들어 수동으로 만든 신속한 파일), 다음과 같이 지정된 경우에도 다른 답변은 작동하지 않습니다.
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
클래스를 NSObject에서 상속하는 것 외에 다른 것을 변경하지 않고 "Unrecognized selector"오류가 발생하는 것을 중단하고 논리가 예상대로 작동하도록했습니다.
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)
}
선택기 텍스트 (tester :)에 콜론을 포함하면 매개 변수가 userInfo에 들어갑니다.
함수는 NSTimer를 매개 변수로 취해야합니다. 그런 다음 userInfo를 추출하여 전달 된 매개 변수를 가져 오십시오.
선택자는 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"
)
또는
var rightBarButton = UIBarButtonItem(
title: "Logout",
style: UIBarButtonItemStyle.Plain,
target: self,
action:Selector("logout")
)
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)
}
자세한 내용은 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
}
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)
// 컨트롤 메서드 새로 고침
func refreshControlValueChanged(){
atableView.reloadData()
refreshCntrl.endRefreshing()
}
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")
}
}
}
사용할 때 performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval()
메서드 (선택자와 일치)를 다음과 같이 표시해야합니다.
@objc
For Swift 2.0:
{
//...
self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
//...
//...
btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
//...
//...
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
//...
}
@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}
For Swift 2.2, you need to write '#selector()' instead of string and selector name so the possibilities of spelling error and crash due to that will not be there anymore. Below is example
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
you create the Selector like below.
1.
UIBarButtonItem(
title: "Some Title",
style: UIBarButtonItemStyle.Done,
target: self,
action: "flatButtonPressed"
)
2.
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
Take note that the @selector syntax is gone and replaced with a simple String naming the method to call. There’s one area where we can all agree the verbosity got in the way. Of course, if we declared that there is a target method called flatButtonPressed: we better write one:
func flatButtonPressed(sender: AnyObject) {
NSLog("flatButtonPressed")
}
set the timer:
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: Selector("flatButtonPressed"),
userInfo: userInfo,
repeats: true)
let mainLoop = NSRunLoop.mainRunLoop() //1
mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal
In order to be complete, here’s the flatButtonPressed
func flatButtonPressed(timer: NSTimer) {
}
I found many of these answers to be helpful but it wasn't clear how to do this with something that wasn't a button. I was adding a gesture recognizer to a UILabel in swift and struggled so here's what I found worked for me after reading everything above:
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: "labelTapped:")
Where the "Selector" was declared as:
func labelTapped(sender: UILabel) { }
Note that it is public and that I am not using the Selector() syntax but it is possible to do this as well.
let tapRecognizer = UITapGestureRecognizer(
target: self,
action: Selector("labelTapped:"))
Using #selector will check your code at compile time to make sure the method you want to call actually exists. Even better, if the method doesn’t exist, you’ll get a compile error: Xcode will refuse to build your app, thus banishing to oblivion another possible source of bugs.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(addNewFireflyRefernce))
}
func addNewFireflyReference() {
gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
}
It may be useful to note where you setup the control that triggers the action matters.
For example, I have found that when setting up a UIBarButtonItem, I had to create the button within viewDidLoad or else I would get an unrecognized selector exception.
override func viewDidLoad() {
super.viewDidLoad()
// add button
let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
self.navigationItem.rightBarButtonItem = addButton
}
func addAction(send: AnyObject?) {
NSLog("addAction")
}
Change as a simple string naming in the method calling for selector syntax
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
After that, type func test().
For Swift 3
//Sample code to create timer
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.
func updateTimer(){
//Implemetation
}
repeats:- true/false specifies that timer should call again n again.
Selector in Swift 4:
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
For swift 3
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
Function declaration In same class:
@objc func test()
{
// my function
}
A selector
is used to describe the name of a function. Swift
doesn’t use selectors, but Objective-C
does. And because many iOS frameworks are written in Objective-C
, and you use those in conjunction with Swift
, you use selectors in Swift
.
Before Swift 2.2
, you’d use strings as selectors. Like this:
Selector("functionToExecute:")
This has a major disadvantage: you can’t check if a selector is valid during compilation. This often leads to the dreaded unrecognized selector sent to instance error
.
So, since Swift 2.2+
you can use the #selector(...)
syntax like this:
#selector(functionToExecute(_:))
Don’t forget to add the @objc
or @objcMembers
[About] attribute to a function that you want to use with target-action.
Quick Tip: Use Xcode’s autocomplete function to get the right function signature. Start typing #selector
(and then hit the Esc-key
. A dropdown with possible function matches appears. Select the right function, and the right signature is added to your code automatically.
참고URL : https://stackoverflow.com/questions/24007650/selector-in-swift
'developer tip' 카테고리의 다른 글
Interop 유형은 삽입 할 수 없습니다. (0) | 2020.10.02 |
---|---|
Swift에서 문자열을 배열로 분할 하시겠습니까? (0) | 2020.10.02 |
CSS 배경 늘리기 및 크기 조정 (0) | 2020.10.02 |
.BAT 파일 내에서 여러 .BAT 파일을 실행하는 방법 (0) | 2020.10.02 |
정규식 : AND 연산자가 있습니까? (0) | 2020.10.02 |