LoginSignup
0
1

More than 3 years have passed since last update.

Swift:ProtocolでDelegate作る時のTips

Posted at

基本的な実装

protocol ClassADelegate: AnyObject {
    func call()
}

class ClassA {
    weak var delegate: ClassADelegate?

    func test() {
        delegate?.call()
    }
}

class ClassB {
    let a = ClassA()

    init() {
        a.delegate = self
    }
}

extension ClassB: ClassADelegate {
    func call() {
        Swift.print("Hello World")
    }
}

ポイント

  • 0から自作のDelegateを作る時はAnyObjectをつける
  • delegateのプロパティはweak varにする(強参照によるメモリリーク対策)

すでにDelegateをもつクラスを拡張したDelegateを作る時

protocol CustomeTextViewDelegate: NSTextViewDelegate {
    func call()
}

// NSTextView はすでにdelegateを持っている
class CustomeTextView: NSTextView {

    private var customDelegate: CustomeTextViewDelegate? {
        return self.delegate as? CustomeTextViewDelegate
    }

    func test() {
        customDelegate?.call()
    }

}

class ClassA: NSView {
    let a = CustomeTextView()

    required init?(coder: NSCoder) {
        super.init(coder: coder)

        a.delegate = self
    }
}

extension ClassA: CustomeTextViewDelegate {
    func call() {
        Swift.print("Hello World")
    }
}

ポイント

  • self.delegate as? CustomeTextViewDelegateのようにすでにあるdelegateをキャストする形で使う.キャストできた時だけ発動する仕組み.

実装不要なDelegateメソッドを作りたい場合

パターンA
protocol ClassADelegate: AnyObject {
    func requiredFunc()
    func optionalFunc()
}

extension ClassADelegate {
    func optionalFunc() {}
}

class ClassA {
    weak var delegate: ClassADelegate?

    func callRequire() {
        delegate?.requiredFunc()
    }

    func callOptional() {
        delegate?.optionalFunc()
    }
}

class ClassB {
    let a = ClassA()

    init() {
        a.delegate = self
    }
}

extension ClassB: ClassADelegate {
    func requiredFunc() {
        Swift.print("Hello World")
    }

    // optionalFuncは実装しなくてもコンパイル通る
}

ポイント

  • extensionで一度空っぽの実装をしてしまう.
パターンB
@objc protocol ClassADelegate: AnyObject {

    func requiredFunc()

    @objc optional func optionalFunc()

}

class ClassA {
    weak var delegate: ClassADelegate?

    func callRequire() {
        delegate?.requiredFunc()
    }

    func callOptional() {
        delegate?.optionalFunc?()
    }
}

class ClassB {
    let a = ClassA()

    init() {
        a.delegate = self
    }
}

extension ClassB: ClassADelegate {
    func requiredFunc() {
        Swift.print("Hello World")
    }

    // optionalFuncは実装しなくてもコンパイル通る
}

ポイント

  • @objc修飾詞をつける.

ここによると,パターンAの方がSwiftらしくていいらしい.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1