[Swift] - Swift로 프로토콜 메서드를 Optional(선택적으로 구현하게)로 만드는 두 가지 방법


프로토콜의 메서드를 Optional로 만드는 두 가지 방법에 대해 알아보자.


https://betterprogramming.pub/2-ways-to-make-protocol-methods-optional-in-swift-f032836a343b

이 글에서는 프로토콜의 메서드를 Optional로 만드는 두 가지 방법에 대해 알아볼 것이다. 그리고 각 방법의 장단점에 대해서도 알아볼 것이다. 참고로 여기에서 말한 optional은 메서드를 필수적으로 구현하는 것이 아닌 선택적으로 구현할 수 있다는 의미에서의 옵셔널을 의미한다.

기본 구현

첫 번째 방법은 프로토콜의 extension을 생성하고 프로토콜의 빈 메서드를 포함시키는 것이다.

import Foundation

protocol PickerViewDelegate {
    func didChooseItem(at index: Int) // Required
    func didDismiss() // Optional
}

extension PickerViewDelegate {
    func didDismiss() {
        // Do nothing.
    }
}

이 방법으로 didDismiss() 메서드를 선택적으로 구현할 수 있게 만들었다. 이제 PickerViewDelegate 프로토콜을 따를 때 어떤 일이 일어나는지를 확인할 것이다.

class Controller: PickerViewDelegate {
    func didChooseItem(at index: Int) {

    }
}

image.png

보다싶이, 컴파일러가 didDismiss() 메서드를 구현하는 것을 요구하지 않는다.

장점

  • 구조체가 프로토콜을 따르게 할 수 있다.
  • 우리가 프로토콜을 따르는 타입 안에서 메서드를 구현하지 않을 때, extension에 구현된 내용이 자동으로 사용된다.

단점

  • 이 옵셔널 메서드가 void가 아닌 값을 리턴하면, 기본 구현에서 특정 값을 생각해서 리턴해야 한다.

Objective-C ‘optional’ 키워드

우리는 프로토콜을 @objc 키워드로 마크하고, @objc optional로 옵셔널 메서드를 표시할 수 있다.

@objc protocol PickerViewDelegate {
    func didChooseItem(at index: Int) // Required
    @objc optional func didDismiss() // Optional
}

이 방법을 사용하면, extension을 만들 필요가 없다. 단지 프로토콜을 다르게 클래스를 만들면 된다.

class Controller: PickerViewDelegate {
    func didChooseItem(at index: Int) {

    }
}

장점

  • Extension을 만들 필요가 없다.

단점

  • 오로지 NSObject의 하위 클래스만이 @objc 프로토콜을 채택할 수 있다. 이 말은 구조체나 열거형이 프로토콜을 따르게 할 수 없다는 것이다.
  • 만약 optional 메서드를 호출해야 한다면, 꼭 메서드의 이름 뒤에 ?!를 붙여줘야 한다.(만약 메서드가 구현되지 않았는데 언래핑을 강행한다면 앱에서 크래시가 날 것이다.)
class PickerView {
    weak var delegate: PickerViewDelegate?

    deinit {
        delegate?.didDismiss?()
    }
}