프로젝트의 소스 코드를 Swift 3에서 Swift 4로 변환하려고합니다. Xcode가 알려주는 경고 중 하나는 선택기에 관한 것입니다.
예를 들어 다음과 같이 일반 선택기를 사용하여 버튼에 대상을 추가합니다.
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
이것이 나타내는 경고입니다.
‘#selector’의 인수는 Swift 4에서 사용되지 않는 ‘@objc’속성 유추에 의존하는 ‘ViewController’의 인스턴스 메소드 ‘myAction ()’을 나타냅니다.
이 인스턴스 메소드를 Objective-C에 노출 시키려면 ‘@objc’를 추가하십시오.
이제 Fix
오류 메시지를 누르면 내 기능이 수행됩니다.
// before
func myAction() { /* ... */ }
// after
@objc func myAction() { /* ... */ }
@objc
마크 를 포함하기 위해 모든 기능의 이름을 바꾸고 싶지 않으며 필요하지 않다고 가정합니다.
지원 중단을 처리하기 위해 선택기를 다시 작성하려면 어떻게해야하나요?
관련 질문 :
답변
해결 방법은 정확합니다. Objective-C에 노출되는 방법을 만들기 위해 선택할 수있는 선택기에 대해 아무것도 없습니다.
이 경고의 첫 번째 이유는 SE-0160 의 결과입니다 . Swift 4 이전에는 상속 클래스 internal
의 Objective-C 호환 상위 멤버 가 Objective-C에 노출 된 NSObject
것으로 추론 @objc
되었으므로 선택기를 사용하여 호출 할 수있었습니다 (Obj-C 런타임이 메소드를 검색하기 위해 필요하므로) 주어진 선택기에 대한 구현).
그러나 Swift 4에서는 더 이상 그렇지 않습니다. @objc
예를 들어, @objc
메소드의 오버라이드 , @objc
프로토콜 요구 사항의 구현 및와 @objc
같은 속성을 갖는 선언과 같이 매우 구체적인 선언 만이 유추 됩니다 @IBOutlet
.
위의 링크 된 제안에 자세히 설명 된 바와 같이 이것의 배후의 동기 는 우선 NSObject
동일한 선택기가 있기 때문에 상속 클래스의 메서드 오버로드가 서로 충돌 하는 것을 방지하는 것입니다 . 둘째, Obj-C에 노출 될 필요가없는 멤버에 대해 썽크를 생성하지 않아도되므로 이진 크기를 줄이고 세 번째로 동적 연결 속도를 향상시킵니다.
멤버를 Obj-C에 노출하려면 @objc
예를 들어 다음 과 같이 표시해야합니다 .
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(foo), for: .touchUpInside)
}
@objc func foo() {
// ...
}
}
( “최소 추론”옵션을 선택한 상태로 실행할 때 선택기가있는 경우 마이그레이션 기는이 작업을 자동으로 수행해야합니다)
멤버 그룹을 Obj-C에 노출 시키려면 다음을 사용하십시오 @objc extension
.
@objc extension ViewController {
// both exposed to Obj-C
func foo() {}
func bar() {}
}
이렇게하면 정의 된 모든 멤버가 Obj-C에 노출되고 Obj-C에 노출 될 수없는 멤버 (에 명시 적으로 표시되지 않은 경우 @nonobjc
)에 오류가 발생합니다.
모든 Obj-C 호환 멤버를 Obj-C에 노출 해야하는 클래스가있는 경우 클래스를 @objcMembers
다음 과 같이 표시 할 수 있습니다 .
@objcMembers
class ViewController: UIViewController {
// ...
}
이제 추론 할 수있는 모든 구성원이됩니다 @objc
. 그러나 위에서 언급 한 단점을 불필요하게 노출시키는 단점을 감안할 때 Obj-C에 노출 된 모든 구성원 이 실제로 필요한 경우가 아니면이 작업을 수행하지 않는 것이 좋습니다 .
답변
로 애플 공식 문서 . @objc를 사용하여 Selector 메서드를 호출해야합니다.
Objective-C에서 선택기는 Objective-C 메소드의 이름을 나타내는 유형입니다. Swift에서 Objective-C 선택기는
Selector
구조 로 표시되며#selector
표현식을 사용하여 구성 할 수 있습니다 . Objective-C에서 호출 할 수있는 메소드의 선택기를 작성하려면 다음과 같이 메소드 이름을 전달하십시오
#selector(MyViewController.tappedButton(sender:))
. 특성의 목표-C 게터 세터 또는 방법에 대한 선택을 구성하기 위해, 접두어 속성 이름 통과getter:
또는setter:
같은 라벨,
#selector(getter: MyViewController.myButton)
.
답변
현재 Swift 4.2에서는 @IBAction을 메소드에 할당하는 것만 으로이 어리석은 @objc 주석을 피할 수 있다고 생각합니다.
“`
let tap = UITapGestureRecognizer(target: self, action: #selector(self.cancel))
@IBAction func cancel()
{
self.dismiss(animated: true, completion: nil)
}
답변
다른 답변에서 이미 언급했듯이 @objc
선택기 의 주석 을 피할 수있는 방법이 없습니다 .
그러나 OP에 언급 된 경고는 다음 단계를 수행하여 침묵시킬 수 있습니다.
- 빌드 설정으로 이동
- 키워드 @objc 검색
- Swift 3 @objc 인터페이스 의 값 을
Off
아래는 위에서 언급 한 단계를 보여주는 스크린 샷입니다.
도움이 되었기를 바랍니다
답변
뷰 컨트롤러에 객관적인 c 멤버가 필요한 경우 뷰 컨트롤러 상단에 @objcMembers 를 추가하십시오 . 그리고 코드에 IBAction을 추가하여이를 피할 수 있습니다.
@IBAction func buttonAction() {
}
스토리 보드에서이 콘센트를 연결하십시오.