나는 만들려고 해요 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())
그러나 아무것도 작동하지 않으며 참조에서 해결책을 찾을 수 없습니다.
답변
스위프트 자체 는 선택기를 사용하지 않습니다. Objective-C에서 선택기를 사용하는 여러 디자인 패턴이 스위프트에서 다르게 작동합니다. (예를 들어, 프로토콜 유형 또는 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의 지시문에 비해 개선 된 것입니다. 스위프트 함수 참조 #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
문자열에서 from을 구성 할 수 있습니다 . 예를 들어 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에서 “현재 스위프트 구문으로 변환”을 실행하여을 사용하는 사용자를 얻으십시오 #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
}
그렇지 않으면 런타임에 “인식 할 수없는 선택기”오류가 발생합니다.
답변
Swift 2.2 이상 및 Swift 3 업데이트
새로운 #selector
표현식을 사용하면 문자열 리터럴을 사용할 필요가 없어 오류 발생이 줄어 듭니다. 참고로 :
Selector("keyboardDidHide:")
된다
#selector(keyboardDidHide(_:))
또한보십시오 : 신속한 진화 제안
참고 (Swift 4.0) :
사용 #selector
하는 경우 기능을 다음과 같이 표시해야합니다@objc
예:
@objc func something(_ sender: UIButton)
답변
스위프트 4.0
아래와 같이 선택기를 만듭니다.
1. 다음과 같은 버튼에 이벤트를 추가하십시오.
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
기능은 다음과 같습니다.
@objc func clickedButton(sender: AnyObject) {
}
답변
장래 독자들을 위해, 나는 문제 unrecognised selector sent to instance
가 발생했고 대상 func
을 개인 으로 표시하여 발생 하는 오류가 발생 한다는 것을 알았습니다 .
는 func
반드시 셀렉터에 대한 참조 목적으로 불릴 공개적으로 표시.
답변
NSTimer에서 다른 사람과 같은 문제를 겪고있는 누군가 가이 문제를 해결하지 못한 경우 NSObject에서 상속하지 않는 클래스를 계층 구조의 직접 또는 깊게 상속하지 않는 클래스를 사용하는 경우 실제로 언급하는 것이 중요합니다. 예를 들어 수동으로 생성 된 빠른 파일)의 경우 다음과 같이 지정된 경우에도 다른 답변은 작동하지 않습니다.
let timer = NSTimer(timeInterval: 1, target: self, selector: "test",
userInfo: nil, repeats: false)
func test () {}
NSObject에서 클래스를 상속받는 것 이외의 다른 것을 변경하지 않고 “인식되지 않은 선택기”오류가 발생하지 않고 논리가 예상대로 작동했습니다.
