스위프트에서 가능합니까? 그렇지 않은 경우 해결 방법이 있습니까?
답변
1. 기본 구현 사용 (권장).
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
장점
-
Objective-C 런타임이 필요하지 않습니다 (적어도 명시 적으로는 아님). 즉, 구조체, 열거 형 및 비
NSObject
클래스를 준수 할 수 있습니다 . 또한 강력한 제네릭 시스템을 활용할 수 있습니다. -
이러한 프로토콜을 준수하는 유형을 만날 때는 항상 모든 요구 사항이 충족되는지 확인할 수 있습니다 . 항상 구체적인 구현이거나 기본 구현입니다. “인터페이스”또는 “계약”이 다른 언어로 작동하는 방식입니다.
단점
-
Void
요구 사항이 아닌 경우 적절한 기본값을 가져야 하지만 항상 가능하지는 않습니다. 그러나이 문제점이 발생하면 해당 요구 사항에 실제로 기본 구현이 없어야하거나 API 디자인 중에 실수를 한 것입니다. -
적어도 특별한 반환 값으로 그 문제를 해결하지 않고 는 기본 구현과 전혀 구현을 구분할 수 없습니다 . 다음 예제를 고려하십시오.
protocol SomeParserDelegate { func validate(value: Any) -> Bool }
방금 반환하는 기본 구현을 제공하면
true
언뜻보기에 괜찮습니다. 이제 다음 의사 코드를 고려하십시오.final class SomeParser { func parse(data: Data) -> [Any] { if /* delegate.validate(value:) is not implemented */ { /* parse very fast without validating */ } else { /* parse and validate every value */ } } }
이러한 최적화를 구현할 수있는 방법은 없습니다. 대리인이 메소드를 구현하는지 여부를 알 수 없습니다.
이 문제를 극복 할 수있는 여러 가지 방법이 있지만 (선택적 클로저, 서로 다른 작업을위한 다른 대리자 개체를 사용하여),이 예는 문제를 명확하게 나타냅니다.
사용 @objc optional
.
@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
장점
- 기본 구현이 필요하지 않습니다. 선택적인 메소드 나 변수를 선언하면 준비가 끝납니다.
단점
-
모든 준수 유형이 Objective-C와 호환되도록 요구 하여 프로토콜의 기능 을 심각하게 제한합니다 . 즉, 상속받은 클래스 만
NSObject
이러한 프로토콜을 준수 할 수 있습니다. 구조체, 열거 형, 관련 유형이 없습니다. -
선택적으로 적합한 메소드를 구현 하거나 구현하는지 확인하여 선택적 메소드가 구현되는지 항상 확인해야 합니다. 선택적 메소드를 자주 호출하는 경우 많은 상용구가 발생할 수 있습니다.
답변
Swift 2 이상에서는 프로토콜의 기본 구현을 추가 할 수 있습니다. 이것은 프로토콜에서 새로운 선택적인 방법을 만듭니다.
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
선택적 프로토콜 메소드를 작성하는 것은 좋은 방법은 아니지만 프로토콜 콜백에서 구조체를 사용할 수 있습니다.
나는 여기에 작은 요약을 썼다 :
https://www.avanderlee.com/swift-2-0/optional-protocol-methods/
답변
선택적 수정 자 및 @objc 속성 을 사용하여 선택적 요구 사항 프로토콜을 정의 하는 방법에 대한 답변 이 있으므로 프로토콜 확장을 사용하여 선택적 프로토콜을 정의하는 방법에 대한 샘플을 제공합니다.
아래 코드는 Swift 3. *입니다.
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*
프로토콜 확장 메소드는 Objective-C 코드로 호출 할 수 없으며 Swift 팀은이를 수정하지 않습니다. https://bugs.swift.org/browse/SR-492
답변
신속한 특정 유형을 사용하는 경우 프로토콜을 “@objc”로 표시하는 것과 관련된 다른 답변은 작동하지 않습니다.
struct Info {
var height: Int
var weight: Int
}
@objc protocol Health {
func isInfoHealthy(info: Info) -> Bool
}
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"
신속하게 작동하는 선택적 프로토콜을 선언하려면 함수를 func 대신 변수로 선언하십시오.
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
그런 다음 다음과 같이 프로토콜을 구현하십시오.
class Human: Health {
var isInfoHealthy: (Info) -> (Bool)? = { info in
if info.weight < 200 && info.height > 72 {
return true
}
return false
}
//Or leave out the implementation and declare it as:
//var isInfoHealthy: (Info) -> (Bool)?
}
그런 다음 “?”를 사용할 수 있습니다. 기능 구현 여부 확인
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
답변
다음은 위임 패턴이있는 구체적인 예입니다.
프로토콜 설정 :
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
델리게이트를 클래스로 설정하고 프로토콜을 구현하십시오. 선택적 메소드를 구현할 필요가 없음을 참조하십시오.
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
한 가지 중요한 점은 선택적 방법이 선택적이며 “?”가 필요하다는 것입니다. 전화 할 때. 두 번째 물음표를 언급하십시오.
delegate?.optionalMethod?()
답변
에서 스위프트 3.0
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
시간을 절약 할 수 있습니다.
답변
optional
각 방법 전에 키워드 를 추가해야합니다 .- 그러나 이것이 작동 하려면 프로토콜에 @objc 속성이 표시되어 있어야합니다.
- 이것은이 프로토콜이 클래스에는 적용 가능하지만 구조에는 적용되지 않음을 의미합니다.