development

Swift 4에서 #selector ()를 사용하여 @objc 추론 폐기를 처리하는 방법은 무엇입니까?

big-blog 2020. 7. 4. 09:32
반응형

Swift 4에서 #selector ()를 사용하여 @objc 추론 폐기를 처리하는 방법은 무엇입니까?


프로젝트의 소스 코드를 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 호환 상위 NSObject클래스 멤버 @objc가 Objective-C에 노출 된 것으로 추론 되었으므로 Objective-C에 노출 될 수 있으므로 메소드를 검색하기 위해 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에 노출 된 모든 구성원 실제로 필요한 경우가 아니면이 작업을 수행하지 않는 것이 좋습니다 .


As Apple Official Documentation. you need to use @objc to call your Selector Method.

In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and can be constructed using the #selector expression. To create a selector for a method that can be called from Objective-C, pass the name of the method, such as #selector(MyViewController.tappedButton(sender:)). To construct a selector for a property’s Objective-C getter or setter method, pass the property name prefixed by the getter: or setter: label, such as #selector(getter: MyViewController.myButton).


As of, I think Swift 4.2, all you need to do is to assign @IBAction to your method and you can avoid this silly @objc annotation

```

let tap  =  UITapGestureRecognizer(target: self, action: #selector(self.cancel))


@IBAction func cancel()
{
    self.dismiss(animated: true, completion: nil)
}

As already mentioned in other answers, there is no way to avoid the @objc annotation for selectors.

But warning mentioned in the OP can be silenced by taking following steps:

  1. Go to Build Settings
  2. Search for keyword @objc
  3. Set the value of Swift 3 @objc interface to Off

below is the screenshot that illustrates the above mentioned steps:

Silencing the warning "Swift 3 @objc interface"

Hope this helps


If you need objective c members in your view controller just add @objcMembers at the top of the view controller. And you can avoid this by adding IBAction in your code.

@IBAction func buttonAction() {

}

Make sure to connect this outlet in storyboard.

참고URL : https://stackoverflow.com/questions/44390378/how-can-i-deal-with-objc-inference-deprecation-with-selector-in-swift-4

반응형