나는 당신의 질문에 대답 할 수 있다고 생각하지만 당신이 좋아할 대답은 아닙니다.
요약 : @objc 기능은 현재 프로토콜 확장에 없을 수 있습니다. 이상적인 솔루션은 아니지만 대신 기본 클래스를 만들 수 있습니다.
프로토콜 확장 및 Objective-C
첫째,이 질문 / 답변 ( Can Swift Method Defined on Extensions on Extensions on Protocols Accessed in Objective-c )은 프로토콜 확장이 내부적으로 전달되는 방식 때문에 프로토콜 확장에서 선언 된 메서드가 objc_msgSend()함수에 표시되지 않음을 시사하는 것 같습니다. 따라서 Objective-C 코드에는 표시되지 않습니다. 확장 프로그램에서 정의하려는 방법은 Objective-C에서 볼 수 있어야하기 때문에 ( UIKit사용할 수 있으므로)를 포함하지 않은 것에 대해 소리를 지르지 @objc만 일단 포함하면 @objc허용되지 않기 때문에 소리를 지 릅니다 . 프로토콜 확장. 이는 프로토콜 확장이 현재 Objective-C에 표시되지 않기 때문일 수 있습니다.
@objc"@objc는 클래스의 멤버, @objc 프로토콜 및 클래스의 구체적인 확장에만 사용할 수 있습니다."라는 상태 를 추가하면 오류 메시지가 표시 됩니다. 이것은 수업이 아닙니다. @objc 프로토콜에 대한 확장은 프로토콜 정의 자체 (예 : 요구 사항)에있는 것과 동일하지 않으며 "concrete"라는 단어는 프로토콜 확장이 구체적인 클래스 확장으로 간주되지 않음을 암시합니다.
해결 방법
불행히도 이것은 기본 구현이 Objective-C 프레임 워크에 표시되어야 할 때 프로토콜 확장을 사용하는 것을 거의 완전히 방지합니다. 처음 @objc에는 Swift Compiler가 형식을 준수하는 클래스가 클래스라는 것을 보장 할 수 없기 때문에 프로토콜 확장에서 허용되지 않는다고 생각했습니다 UIViewController. 그래서 내가 넣어 class에 요구 사항을 P1. 이것은 작동하지 않았습니다.
아마도 유일한 해결 방법은 여기에서 프로토콜 대신 기본 클래스를 사용하는 것입니다.하지만 클래스가 단일 기본 클래스 만 가질 수 있지만 여러 프로토콜을 준수 할 수 있기 때문에 이것은 분명히 완전히 이상적이지는 않습니다.
이 경로를 선택하는 경우이 질문 ( Swift 3 ObjC Optional Protocol Method Not Called in Subclass )을 고려하십시오. Swift 3의 또 다른 현재 문제는 하위 클래스가 수퍼 클래스의 선택적 프로토콜 요구 사항 구현을 자동으로 상속하지 않는다는 것입니다. 그 질문에 대한 대답 @objc은 그것을 우회하기 위해 특별한 적응을 사용 합니다.
문제보고
Swift 오픈 소스 프로젝트에서 일하는 사람들 사이에서 이미 논의되고 있다고 생각하지만 , 결국 Swift Core Team으로 갈 가능성이있는 Apple의 Bug Reporter 또는 Swift의 버그 리포터 를 사용하여 알고 있는지 확인할 수 있습니다 . 그러나 이들 중 하나는 버그가 너무 광범위하거나 이미 알려져 있음을 알 수 있습니다. Swift 팀은 당신이 찾고있는 것을 새로운 언어 기능으로 고려할 수도 있습니다.이 경우 먼저 메일 링리스트를 확인해야 합니다 .
최신 정보
2016 년 12 월이 문제 는 Swift 커뮤니티 에보고 되었습니다. 이 문제는 여전히 중간 우선 순위로 진행 중으로 표시되지만 다음과 같은 댓글이 추가되었습니다.
이것은 의도 된 것입니다. 프로토콜 준수 후에 확장이 추가 될 수 있기 때문에 모든 채택 자에게 메소드 구현을 추가 할 방법이 없습니다. 하지만 확장이 프로토콜과 동일한 모듈에 있으면 허용 할 수 있다고 생각합니다.
그러나 프로토콜이 확장과 동일한 모듈에 있기 때문에 향후 Swift 버전에서이 작업을 수행 할 수 있습니다.
업데이트 2
2017 년 2 월,이 문제 는 다음 메시지와 함께 Swift Core Team 멤버 중 한 명이 "Wo n't Do" 로 공식적으로 종결 되었습니다.
이는 의도적입니다. 프로토콜 확장은 Objective-C 런타임의 제한으로 인해 @objc 진입 점을 도입 할 수 없습니다. @objc 진입 점을 NSObject에 추가하려면 NSObject를 확장합니다.
확장 NSObject하거나 심지어 UIViewController원하는 것을 정확하게 달성하지 못하지만 불행히도 가능해 보이지는 않습니다.
(매우) 장기적인 미래에 우리는 @objc메소드에 대한 의존도를 완전히 없앨 수 있을지 모르지만 Cocoa 프레임 워크가 현재 Swift로 작성되지 않았기 때문에 조만간 오지 않을 것입니다 (안정적인 ABI를 갖기 전까지는 불가능합니다). .
업데이트 3
2019 년 가을부터 점점 더 많은 Apple 프레임 워크가 Swift로 작성되고 있기 때문에 이것은 문제가되지 않습니다. 예를 들어, SwiftUI대신 을 사용 하면 메서드를 참조 할 때 필요하지 UIKit않으므로 문제를 완전히 피할 @objc수 있습니다 SwiftUI.
Swift로 작성된 Apple 프레임 워크는 다음과 같습니다.
- SwiftUI
- RealityKit
- 결합시키다
- CryptoKit
Swift가 공식적으로 Swift 5.0 및 5.1에서 각각 ABI 및 모듈 안정이므로이 패턴이 시간이 지남에 따라 계속 될 것으로 예상 할 수 있습니다.
@objc