sourcetip

Swift 프로토콜에서 선택적 메서드는 어떻게 선언합니까?

fileupload 2023. 4. 18. 23:16
반응형

Swift 프로토콜에서 선택적 메서드는 어떻게 선언합니까?

스위프트에서 가능한가요?그렇지 않은 경우 이를 수행할 수 있는 해결 방법이 있습니까?

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 */
            }
        }
    }
    

    이러한 최적화를 실장하는 방법은 없습니다.대리인이 메서드를 실장하고 있는지 아닌지는 알 수 없습니다.

    이 문제를 해결하는 방법은 여러 가지가 있지만(선택적인 폐쇄, 여러 작업을 위해 다른 위임 개체를 사용), 이 예는 문제를 명확하게 보여줍니다.


사용법 2. 사용방법@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 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?()

옵션 요구 프로토콜을 정의하기 위해 옵션 수식자 @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" 표시를 포함하는 다른 답변은 swift-specific 유형을 사용하는 경우 작동하지 않습니다.

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"

swift에서 잘 작동하는 선택적 프로토콜을 선언하려면 함수를 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

Swift 3.0의 경우

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

그러면 시간이 절약됩니다.

  • 때 더해야 요.optional키워드를 지정합니다.
  • 단, 이 기능이 작동하려면 프로토콜에 @objc 속성이 표시되어야 합니다.
  • 이는 또한 이 프로토콜이 클래스에는 적용 가능하지만 구조에는 적용되지 않음을 의미합니다.

swift protocol에서 옵션 메서드를 생성할 수 있는 방법은 두 가지가 있습니다.

1 - 첫 번째 옵션은 @objc 속성을 사용하여 프로토콜을 마킹하는 것입니다.이는 클래스에서만 채택할 수 있음을 의미하지만 다음과 같이 개별 메서드를 선택사항으로 표시해야 함을 의미합니다.

@objc protocol MyProtocol {
    @objc optional func optionalMethod()
}

2 - 보다 빠른 방법:이 옵션이 더 좋습니다.아무것도 하지 않는 옵션의 메서드의 디폴트 실장을 다음과 같이 기술합니다.

protocol MyProtocol {
    func optionalMethod()
    func notOptionalMethod()
}

extension MyProtocol {

    func optionalMethod() {
        //this is a empty implementation to allow this method to be optional
    }
}

Swift에는 옵션인 메서드에 기본 구현을 제공할 수 있는 확장이라는 기능이 있습니다.

프로토콜 상속을 통한 순수한 Swift 접근 방식:

//Required methods
protocol MyProtocol {
    func foo()
}

//Optional methods
protocol MyExtendedProtocol: MyProtocol {
    func bar()
}

class MyClass {
    var delegate: MyProtocol
    func myMethod() {
        (delegate as? MyExtendedProtocol).bar()
    }
}

Antoine의 답변 메커니즘을 설명하려면:

protocol SomeProtocol {
    func aMethod()
}

extension SomeProtocol {
    func aMethod() {
        print("extensionImplementation")
    }
}

class protocolImplementingObject: SomeProtocol {

}

class protocolImplementingMethodOverridingObject: SomeProtocol {
    func aMethod() {
        print("classImplementation")
    }
}

let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()

noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"

옵션인 프로토콜 방식을 어떻게 구현할 수 있는지 묻기 전에 왜 구현해야 하는지 물어봐야 한다고 생각합니다.

만약 우리가 swift protocols를 고전적인 객체 지향 프로그래밍의 인터페이스로 생각한다면, 선택적인 방법은 별로 의미가 없으며, 아마도 더 나은 해결책은 기본 구현을 만드는 것일 것이다.또는 프로토콜에서 가능한 메서드의 조합을 나타내기 위해 프로토콜을 프로토콜 집합(이들 간의 상속 관계 포함)으로 분리합니다.

자세한 내용은 https://useyourloaf.com/blog/swift-optional-protocol-methods/,을 참조하십시오.이 문제에 대한 개요는 다음과 같습니다.

원래 질문과는 조금 다른 주제지만 앙투안의 아이디어를 바탕으로 한 것이어서 누군가에게 도움이 될 것 같았습니다.

프로토콜 확장이 있는 구조물에 대해 계산된 속성을 선택적으로 만들 수도 있습니다.

프로토콜의 속성을 선택적으로 만들 수 있습니다.

protocol SomeProtocol {
    var required: String { get }
    var optional: String? { get }
}

프로토콜 확장에서 더미 계산 속성 구현

extension SomeProtocol {
    var optional: String? { return nil }
}

이제 옵션 속성을 구현하거나 구현하지 않은 구조를 사용할 수 있습니다.

struct ConformsWithoutOptional {
    let required: String
}

struct ConformsWithOptional {
    let required: String
    let optional: String?
}

또한 Swift 프로토콜에서 옵션 속성을 수행하는 방법을 블로그에 적어두었습니다. Swift 2 릴리즈를 통해 상황이 변경될 경우를 대비해 최신 정보를 제공합니다.

옵션 및 필수 위임 메서드를 만드는 방법.

@objc protocol InterViewDelegate:class {

    @objc optional func optfunc()  //    This is optional
    func requiredfunc()//     This is required 

}

다음은 구조나 열거가 아닌 swift 클래스 전용의 매우 간단한 예입니다.프로토콜 메서드는 선택 사항이며, 두 가지 수준의 선택적 체인이 있습니다.또한 프로토콜을 채택하는 클래스에서는 선언에 @objc 속성이 필요합니다.

@objc protocol CollectionOfDataDelegate{
   optional func indexDidChange(index: Int)
}


@objc class RootView: CollectionOfDataDelegate{

    var data = CollectionOfData()

   init(){
      data.delegate = self
      data.indexIsNow()
   }

  func indexDidChange(index: Int) {
      println("The index is currently: \(index)")
  }

}

class CollectionOfData{
    var index : Int?
    weak var delegate : CollectionOfDataDelegate?

   func indexIsNow(){
      index = 23
      delegate?.indexDidChange?(index!)
    }

 }

완전 스위프트로 하고 싶은 경우, 가장 좋은 방법은 Swift 타입의 structure와 같은 Swift 타입을 반환하는 경우 기본 구현 항목을 제공하는 것입니다.

예:

struct magicDatas {
    var damagePoints : Int?
    var manaPoints : Int?
}

protocol magicCastDelegate {
    func castFire() -> magicDatas
    func castIce() -> magicDatas
}

extension magicCastDelegate {
    func castFire() -> magicDatas {
        return magicDatas()
    }

    func castIce() -> magicDatas {
        return magicDatas()
    }
}

모든 기능을 정의하지 않고 프로토콜을 구현할 수 있습니다.

우선 그 차이를 이해하자

번째 예 - 다음과 같은 경우UITableViewDataSource두 가지 메서드를 강제로 작성해야 합니다.그것이 swift way default protocol 입니다.

번째 예 - 글을 쓰는 경우UITableViewDelegate빨간색 오류는 표시되지 않으므로 위임 방법을 모두 추가하십시오.어떤 방법을 사용할지는 당신에게 달려 있습니다.라고 부를 수 있다optional method!

예를 들어 이것을 이해합시다.

First Swift Way 기본 프로토콜 접근법

class ContactModel{
    var firstname: String?
    var lastname: String?
}

protocol ContactDataSource: AnyObject{
    func contactConfiguration(contact: ContactModel)
}

class ViewController: ContactDataSource{
    func contactConfiguration(contact: ContactModel) {
        print(contact)
    }
}

두 번째 접근법 - 옵션 프로토콜

@objc
class UserModel: NSObject{
    var firstname: String = ""
}

@objc protocol UserDataSource{
    func contactConfiguration(user: UserModel)
   @objc optional func userInfo(user: UserModel)
}

class ViewController: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}

주의: 옵션 protocal에서 볼 수 있는 경우 userInfo 메서드는 작성하지 않았기 때문에 사용자에게 달려 있습니다.즉, 클래스에 메서드를 추가하든 추가하지 않든 상관없습니다. - 프로토콜에서 선택적 메서드로 호출됩니다.

클래스 및 프로토콜은 @objc 속성을 사용하여 선언해야 하며 구조가 아닌 클래스에서만 작동합니다.

세 번째 접근법 - Extension을 사용하는 선택적 프로토콜

주의: Structure 또는 Class를 수강할 수 있습니다.

class UserModel{
    var firstname: String = ""
}

또는

struct UserModel{
    var firstname: String = ""
}

그리고.

protocol UserDataSource{
    func contactConfiguration(user: UserModel)
}

extension UserDataSource{
    func userInfo(user: UserModel){}
}

class myview: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}

옵션 함수 변수로 저장하는 것도 하나의 옵션입니다.

struct MyAwesomeStruct {
    var myWonderfulFunction : Optional<(Int) -> Int> = nil
}

let squareCalculator =
    MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)

protocol에서 함수를 정의하고 해당 프로토콜에 대한 확장을 만든 다음 옵션으로 사용할 함수에 대한 빈 구현을 만듭니다.

정의하려면Optional Protocol빨리 사용하세요.@objc키워드 전Protocol선언과attribute/method선언문을 작성해야 합니다.다음은 프로토콜의 Optional Property 샘플입니다.

@objc protocol Protocol {

  @objc optional var name:String?

}

// 코드에 해당 프로토콜을 구현하려고 하면 해당 함수를 클래스에 포함시키지 않습니다.

class MyClass: Protocol {

   // No error

}

또 다른 방법은 프로토콜 확장을 사용하는 것입니다. 프로토콜의 기본 구현을 제공할 수도 있습니다.그러면 그 프로토콜의 기능이 선택사항이 될 수 있습니다.

언급URL : https://stackoverflow.com/questions/24032754/how-does-one-declare-optional-methods-in-a-swift-protocol

반응형