Swiftの他のクラスに処理してもらう時のアレコレ

# delegate

処理を移譲する仕組み

```swift
protocol MyDelegate: class {
  func tapped(_ button: Button)
}
```

```swift
final class Button: UIView {
  weak var delegate: MyDelegate? = nil

  func touchesEnded() {
    delegate?.tapped(self)
  }
}
```
大体の場合はプロトコルとクラスがセットになる

```swift
class ViewController: UIViewController, MyDelegate {
  @IBOutlet weak var button: Button!

  func viewDidLoad() {
    button.delegate = self
  }

  func tapped(_ button: Button) {
    print("タップされた")
  }
}
```

このように使う。
`delegate?.tapped(self)`が呼ばれると、ViewControllerの`func tapped(_ button: Button)`が呼ばれる。
この例ではButtonとViewControllerという２つのクラスが存在しているが、
**ButtonからViewControllerのメソッドを呼んで実行している**と考えるのが分かりやすいと思う。
これが一番スタンダードなコールバックだと思う。

# Blocks

ObjCの時代によく見たやつ

```swift
class ViewController: UIViewController {
  @IBOutlet weak var button: Button!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    button.closure = { (button) in
      print("タップされた")
    }
  }
}

class Button: UIView {
  var closure: ((Button)->Void)? = nil
  
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    closure?(self)
  }
}
```

これは要するに、`((Button)->Void)`という構造の処理を保持して、タップされた時に実行しているという感じ。
便利だけど、強参照・弱参照とか考えないとヤバい感じになりがち。

# Notification

```swift
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(tapped), name: Notification.Name(rawValue: "tap.action"), object: nil)
  }
  
  func tapped(_ notification: Notification) {
    print("タップされた")
  }
}

class Button: UIView {
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: "tap.action")))
  }
}
```

もはやインスタンスがどこにあろうと処理を別の所で出来る強いやつ。
上の例だとボタンが２つある時とかはどっちが押されたかとか判別するのにはNotificationにタグ情報を入れたりしないといけないので骨が折れる。
基本的には一箇所で起きるイベントに対して多くのクラスでアクションが行われる時に使う。
処理も追いにくいのでなるべく使わないでほしいやつ。

# RxSwift

```swift
class ViewController: UIViewController {
  @IBOutlet weak var button: Button!
  let disposeBag = DisposeBag()

  override func viewDidLoad() {
    super.viewDidLoad()
    button.tapped.subscribe(onNext: {
      print("タップされた")
    }).disposed(by: disposeBag)
  }
}

class Button: UIView {
  let tapped = PublishSubject<Void>()
  
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    tapped.onNext()
  }
}
```

Blocksに似てるけど、RxSwiftというライブラリを使った書き方。
RxSwiftによるオペレータの恩恵が受けれる。（スレッドの変更や、リトライなど）

# やったらダメなやつ

```swift
class ViewController: UIViewController {
  @IBOutlet weak var button: Button!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    button.viewController = self
  }
  
  func tapped() {
    print("タップされた")
  }
}

class Button: UIView {
  var viewController: ViewController?
  
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    viewController?.tapped()
  }
}
```

ButtonにViewControllerを持つパターン。
お互いにお互いのインスタンスを保持してしまうので、メモリから開放されなくなる。

## こういう場合の回避方法

```swift
class ViewController: UIViewController {
  @IBOutlet weak var button: Button!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    button.viewController = self
  }
  
  func tapped() {
    print("タップされた")
  }
}

class Button: UIView {
  weak var viewController: ViewController?
  
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    viewController?.tapped()
  }
}
```

子が親を持つ際にweakにすると、弱参照になるのでViewControllerはButtonに保持されずViewControllerの開放に合わせてButtonも開放される。