Swift #selector 구문으로 "모호한 사용"컴파일 오류를 해결하려면 어떻게해야합니까?
[ 참고이 질문은 원래 Swift 2.2에서 공식화되었습니다. 두 가지 중요한 언어 변경을 포함하여 Swift 4에서 수정되었습니다. 첫 번째 메소드 매개 변수 외부는 더 이상 자동으로 억제되지 않으며 선택자는 Objective-C에 명시 적으로 노출되어야합니다.]
내 수업에 다음 두 가지 메서드가 있다고 가정 해 보겠습니다.
@objc func test() {}
@objc func test(_ sender:AnyObject?) {}
이제 Swift 2.2의 새로운 #selector
구문을 사용하여 첫 번째 메소드 인 func test()
. 어떻게하나요? 내가 이것을 시도 할 때 :
let selector = #selector(test) // error
... "의 모호한 사용"오류가 표시 test()
됩니다. 하지만 이렇게 말하면 :
let selector = #selector(test(_:)) // ok, but...
... 오류가 도망 간다, 그러나 나는 지금 말하는 겁니다 잘못된 방법 의 하나 와 매개 변수. 매개 변수가 없는 것을 참조하고 싶습니다 . 어떻게하나요?
[참고 : 예제는 인위적이지 않습니다. NSObject에는 Objective-C copy
및 copy:
인스턴스 메서드 인 Swift copy()
및 copy(sender:AnyObject?)
; 실생활에서 쉽게 문제가 발생할 수 있습니다.]
[ 참고이 답변은 원래 Swift 2.2에서 공식화되었습니다. 두 가지 중요한 언어 변경을 포함하여 Swift 4에서 수정되었습니다. 첫 번째 메소드 매개 변수 외부는 더 이상 자동으로 억제되지 않으며 선택자는 Objective-C에 명시 적으로 노출되어야합니다.]
함수 참조를 올바른 메서드 서명 으로 캐스팅 하여이 문제를 해결할 수 있습니다 .
let selector = #selector(test as () -> Void)
(하지만 제 생각에는 이렇게 할 필요가 없습니다. 저는이 상황을 버그로 간주하여 함수를 참조하는 Swift의 구문이 부적절하다는 것을 보여줍니다. 버그 보고서를 제출했지만 소용이 없습니다.)
새 #selector
구문 을 요약하면 다음 과 같습니다.
이 구문의 목적은 선택자를 리터럴 문자열로 제공 할 때 발생할 수있는 너무 흔한 런타임 충돌 (일반적으로 "인식되지 않은 선택자")을 방지하는 것입니다. 함수 참조를#selector()
취하고 컴파일러는 함수가 실제로 존재하는지 확인하고 Objective-C 선택기에 대한 참조를 해결합니다. 따라서 쉽게 실수를 할 수 없습니다.
( 편집 : 예, 할 수 있습니다. 완전한 lunkhead가 될 수 있으며에서 지정한 작업 메시지를 구현하지 않는 인스턴스로 대상을 설정할 수 있습니다 #selector
. 컴파일러는 당신을 멈추지 않을 것이고 당신은 좋은 옛날. 한숨 ...)
함수 참조는 다음 세 가지 형식 중 하나로 나타날 수 있습니다.
베어 이름 함수의. 함수가 모호하지 않으면 충분합니다. 따라서 예를 들면 다음과 같습니다.
@objc func test(_ sender:AnyObject?) {} func makeSelector() { let selector = #selector(test) }
test
메서드 는 하나뿐 이므로#selector
매개 변수를 사용하고#selector
매개 변수를 언급하지 않더라도 참조합니다. 배후에서 해결 된 Objective-C 선택기는 여전히 올바르게"test:"
(콜론을 사용하여 매개 변수를 나타냄) 그대로입니다.나머지 시그니처 와 함께 함수의 이름 . 예를 들면 :
func test() {} func test(_ sender:AnyObject?) {} func makeSelector() { let selector = #selector(test(_:)) }
두 가지
test
방법이 있으므로 차별화해야합니다. 표기법 은 매개 변수test(_:)
가있는 두 번째 표기법으로 해석됩니다 .나머지 서명이 있거나없는 함수의 이름과 매개 변수 유형 을 표시 하는 캐스트 . 그러므로:
@objc func test(_ integer:Int) {} @nonobjc func test(_ string:String) {} func makeSelector() { let selector1 = #selector(test as (Int) -> Void) // or: let selector2 = #selector(test(_:) as (Int) -> Void) }
여기서 우리는 한 오버로드
test(_:)
. 오브젝티브 C는 오버로드를 허용하지 않기 때문에 과부하 때문에 단지 그들 중 하나가 노출되어, 오브젝티브 C에 노출 될 수 없으며, 우리는 단지 하나에 대한 선택 형성 할 수 있다 셀렉터는 오브젝티브 C의 기능이기 때문에, 노출을 . 그러나 우리는 스위프트에 관한 한 여전히 명확하게 해야합니다 .(내 의견으로는 오용되는 것은 위의 답변의 기초로 사용되는 언어 적 기능입니다.)
또한 함수가 어떤 클래스에 있는지 알려줌으로써 Swift가 함수 참조를 해결하도록 도와야 할 수도 있습니다.
If the class is the same as this one, or up the superclass chain from this one, no further resolution is usually needed (as shown in the examples above); optionally, you can say
self
, with dot-notation (e.g.#selector(self.test)
, and in some situations you might have to do so.Otherwise, you use either a reference to an instance for which the method is implemented, with dot-notation, as in this real-life example (
self.mp
is an MPMusicPlayerController):let pause = UIBarButtonItem(barButtonSystemItem: .pause, target: self.mp, action: #selector(self.mp.pause))
...or you can use the name of the class, with dot-notation:
class ClassA : NSObject { @objc func test() {} } class ClassB { func makeSelector() { let selector = #selector(ClassA.test) } }
(This seems a curious notation, because it looks like you're saying
test
is a class method rather than an instance method, but it will be correctly resolved to a selector nonetheless, which is all that matters.)
'programing tip' 카테고리의 다른 글
동적으로 생성 된 요소에 대한 jQuery "생성시"이벤트 (0) | 2020.11.02 |
---|---|
단편화 여부-활동에 대한 중첩 단편. (0) | 2020.11.02 |
Python 및 Django와 함께 사용할 HAML 구현이 있습니까? (0) | 2020.11.02 |
부분 클래스에서 속성을 정의한 다음 다른 부분 클래스의 속성으로 표시 할 수 있습니까? (0) | 2020.11.02 |
행렬을 하나의 열로 하위 집합하고, 행렬 데이터 유형을 유지하고, 행 / 열 이름을 유지하는 방법은 무엇입니까? (0) | 2020.11.02 |