- 投稿日:2020-01-23T22:41:31+09:00
チェインオブレスポンシビリティをSwift5で実装する
※この記事は「全デザインパターンをSwift5で実装する」https://qiita.com/satoru_pripara/items/3aa80dab8e80052796c6 の一部です。
The Chain Of Responsibility(チェインオブレスポンシビリティ)
0. チェインオブレスポンシビリティの意義
あるリクエストを処理する複数のオブジェクト(レシーバーまたはレスポンダーという)がある場合、レシーバーを線形リストで繋げてリクエストを処理させるパターンをChain of Responsibilityという。
各レシーバーは次のレシーバーへの参照を持っており、あるリクエストを処理するのに適切なレシーバーが見つかるまで(あるいはレシーバーがなくなるまで)リクエストを次のレシーバーへ渡していく。
このレシーバーを組み合わせた「鎖」をプログラム実行時に動的に作ることもでき、柔軟な処理が可能となる。
例えばiOSにおいては、画面をタップした時の処理がこのパターンによって処理されている。
リクエストを処理するレシーバが1, 2個しかない場合などは、わざわざこのパターンを使っても徒労なだけであまり意味がないことに注意。
1. 実装
まずリクエストハンドラ(レシーバー)に必要な実装の形式をプロトコル
RequestHandling
で定義する。イニシャライザで同じ型
RequestHandling
を渡す。これが「鎖」上の次のレシーバーを表すことになる。もしnilを渡した場合は、次のレシーバーがない(最後のレシーバーに到達した)事を意味する。RequestHandling.swiftpublic protocol RequestHandling { //リクエストを処理する関数 func handle(request: Any) //自分の次のレシーバーを渡して初期化する init(next: RequestHandling?)
自分の次に来るレシーバーを変数で保持するようにする。
ここでは、ジェネリクスを用いて様々な型を処理するレシーバーを表せるようにする。
RequestHandling.swiftpublic final class Handler<T>: RequestHandling, CustomStringConvertible { //自分の次のレシーバー。nilの場合は、このレシーバーが最後のレシーバーとなる private var nextHandler: RequestHandling? public init(next: RequestHandling?) { self.nextHandler = next } //ジェネリクスで渡した型Tを処理する関数 public func handle(request: Any) { if request is T { //Tが処理された場合 print("Request is processed by \(self)") } else { //処理が行われずレスポンダーチェインの最後まで到達した場合 guard let handler = self.nextHandler else { print("Reached the end of the responder chain.") return } //次のレシーバーに送る場合 print("\(self) can't handle \(type(of: request)) requests - forwarding to \(handler)") handler.handle(request: request) } }2.実行
以下のように、実行時にレスポンダーチェインを動的に生成することができる。
まず、「鎖」の最後に位置するレスポンダーから生成し、前のレスポンダーのイニシャライザに次々と渡していくことでレスポンダーチェインを作成する。
TheChainOfResposibilityMessageProcessingDemo.playgroundlet dataHandler = Handler<Data>(next: nil)//最後のレスポンダー let stringHandler = Handler<String>(next: dataHandler)//2番目のレスポンダー let dateHandler = Handler<Date>(next: stringHandler)//最初のレスポンダー鎖の最初のレスポンダーにリクエストを渡すと、適切に処理されるまで次々とリクエストがレスポンダー間を手渡されていくことがわかる。
TheChainOfResposibilityMessageProcessingDemo.playgroundlet data = Data(repeating: 8, count: 10) dateHandler.handle(request: data) /* 出力結果: Date Handler can't handle Data requests - forwarding to String Handler String Handler can't handle Data requests - forwarding to Data Handler Request is processed by Data Handler */どのレスポンダーもリクエストを処理できないと、レスポンダーチェインの最後まで到達してしまうことがわかる。
TheChainOfResposibilityMessageProcessingDemo.playgrounddateHandler.handle(request: 42) /* 出力結果: Date Handler can't handle Int requests - forwarding to String Handler String Handler can't handle Int requests - forwarding to Data Handler Reached the end of the responder chain. */https://github.com/Satoru-PriChan/ChainOfResponsiblityMessageProcessingDemo
参考文献: https://www.amazon.com/Design-Patterns-Swift-implement-Improve-ebook/dp/B07MDD3FQJ
- 投稿日:2020-01-23T18:55:36+09:00
appiumをiOSの実機で使うまでの手順・方法
appiumをiOSの実機で動かすまでの手順です。
使用環境
使用環境は以下の通りです。
Xcode, command line toolsはインストール済とします。Mac OS Catalina(10.15.2)
Xcode 11.2.1
appium v1.15.1Appiumのダウンロード
公式サイトより環境にあった物をDLする。
http://appium.io/Appium側の設定
ダウンロードしたら起動をし、Start Serverをクリック
Start Serverをクリックするとログが出る画面になるので虫眼鏡ボタンをクリック
Automatic Server(1)を選択し、以下のJSONを(3)のところから入力入力し保存する。(JSONを入力する画面にも保存ボタンがあるので注意)
1度保存した設定は Saved Capability Sets(2)からロードが可能です。
{ "deviceName": "iPhone", "udid": "hogehogehogehoge", "platformName": "iOS", "automationName": "XCUITest", "useSimpleBuildTest": false, "platformVersion": "13.3", "bundleId": "hogehoge.hoge.hoge", "xcodeSigningId": "iPhone Developer", "xcodeOrgId": "hogehogehogehoge" }重要なのはudid、xcodeOrgIdになります。
udidはXcodeのdeviceからxcodeOrgIdはdeveloper.appleから自身のteam IDを入力します。
bundleIdを入力したアプリを起動します。
また変更した際はsaveをするのを忘れずに。あとは実行
右下のStart Session(4)を押せば完了!!
うまくいかない場合に確認する箇所
・xcodeOrgIdで入力したteam IDでXcodeで設定からログインできているか
・deriverd dataを削除してみる