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 thegetter:
orsetter:
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:
- Go to Build Settings
- Search for keyword @objc
- Set the value of Swift 3 @objc interface to
Off
below is the screenshot that illustrates the above mentioned steps:
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.
'development' 카테고리의 다른 글
'git checkout'을 'git co'로 별칭 지정하는 방법 (0) | 2020.07.05 |
---|---|
Vue v-on : 클릭이 구성 요소에서 작동하지 않습니다 (0) | 2020.07.05 |
.NET 앱의 최대 스레드 수? (0) | 2020.07.04 |
오버로드 된 함수에 대한 포인터를 어떻게 지정합니까? (0) | 2020.07.04 |
Bazel과 Gradle의 차이점은 무엇입니까? (0) | 2020.07.04 |