プロキシデザインパターン

この投稿では、Proxyデザインパターンと、この場合はiOSアプリケーションでそれを使用して、効果的かつクリーンな方法で保持サイクルを防ぐ方法の簡単な例について説明します。

プロキシデザインパターンとは何ですか?

ガンマ、ジョンソン、ブリシディーズ、ヘルム、および共同研究者による本「デザインパターン」で定義されているように、プロキシデザインパターンは次のように定義されています。

別のオブジェクトへのアクセスを制御するための代理またはプレースホルダーを提供します。それは消費者に彼らが実際の実装と話していると信じさせます。

そして、その図は次のようになります。

ウィキペディアの図

このデザインパターンについて初めて耳にする場合は、少し混乱する可能性があり、その傾向はまったく明確ではありません。しかし、このデザインパターンをどこで使用できるかを説明するための例を挙げましょう。

MVPUIデザインパターンでプロキシを使用する

iOSアプリケーションでMVPのようなUIデザインパターンを使用している場合、との間の双方向通信チャネルのためにView Controllerを弱めないと、保持サイクルが作成される可能性があることに気付きます。図を見てみましょう:ViewPresenter

例えば:

// MARK: - UI 

class ViewController: UIViewController, View {
    var presenter: Presenter?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        presenter?.didRequestMessage()
    }

    func display(_ viewModel: ViewModel) {
        print(viewModel.message)
    }
}

// MARK: - Presenter

struct ViewModel {
    let message: String
}

protocol View {
    func display(_ viewModel: ViewModel)
}

class Presenter {
    private let fetcher: FetchMessage
    private let view: View

    init(fetcher: FetchMessage, view: View) {
        self.fetcher = fetcher
        self.view = view
    }

    func didRequestMessage() {
        fetcher.get { [weak self] message in
            self?.view.display(ViewModel(message: message))
        }
    }
}

// MARK: - Business logic

class FetchMessage {
    func get(completion: @escaping (String) -> Void) {
        completion("Hello, World!")
    }
}

private weak var view: View?

'weak'は、クラスにバインドされていない 'View'には適用しないでください。クラスがバインドされているプロトコル適合性を追加することを検討してください

このコンパイルエラーは、プロトコルをクラス専用にすることで簡単に解決できます(classキーワードを使用してプロトコルをクラス専用にします)。この制約は次のThe protocol to which all classes implicitly conform.ように定義されます。

protocol View: class {
    func display(_ viewModel: ViewModel)
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo _: UISceneSession, options _: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: scene)
        window?.rootViewController = Composer.composeWith(fetcher: FetchMessage())
        window?.makeKeyAndVisible()
    }
}

class Composer {
    static func composeWith(fetcher: FetchMessage) -> ViewController {
        let controller = ViewController()
        let presenter = Presenter(fetcher: fetcher, view: controller)
        controller.presenter = presenter
        return controller
    }
}

class WeakRefProxy: View {
    weak var view: (View & AnyObject)?

    init(_ view: View & AnyObject) {
        self.view = view
    }

    func display(_ viewModel: ViewModel) {
        view?.display(viewModel)
    }
}

protocol View { // Remove class constraint
    func display(_ viewModel: ViewModel)
}

class Presenter {
    private let fetcher: FetchMessage
    private let view: View // Restore to a let

    init(fetcher: FetchMessage, view: View) {
        self.fetcher = fetcher
        self.view = view
    }

    func didRequestMessage() {
        fetcher.get { [weak self] message in
            self?.view.display(ViewModel(message: message))
        }
    }
}

ここでWeakRefProxyは、実際の実装をweak参照して代理します。保持サイクルを回避したいのはそれだけです。そして今、私たちComposition Rootはこのように見えます:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo _: UISceneSession, options _: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: scene)
        window?.rootViewController = Composer.composeWith(fetcher: FetchMessage())
        window?.makeKeyAndVisible()
    }
}

class Composer {
    static func composeWith(fetcher: FetchMessage) -> ViewController {
        let controller = ViewController()
        let presenter = Presenter(fetcher: fetcher, view: WeakRefProxy(controller))
        controller.presenter = presenter
        return controller
    }
}

ジェネリックをWeakRefプロキシにする

もちろん、aの作成はWeakRefProxy非常に面倒な場合があるため、一般的なものを作成してView、次のようにメソッドを拡張機能に実装できます。

class WeakRefProxy<T: AnyObject> {
    weak var object: T?

    init(_ object: T) {
        self.object = object
    }
}
extension WeakRefProxy: View where T: View {
    func display(_ viewModel: ViewModel) {
        object?.display(viewModel)
    }
}

提案された投稿

アプリのライフサイクル

アプリのライフサイクル

: アプリ起動からシャットダウンまでのサイクル: メモリやデータの管理による使いやすさ ⬆️ セキュリティ処理が可能 UIApplication、AppDelegate 状況: UIApplication オブジェクトから送信されたメッセージを AppDelegate オブジェクトが受信し、それぞれを実行する関数を定義 Not Running: アプリが実行されていない状態Inactive:アプリが実行されているがイベントが受信されていない状態Active: アプリが実行されており、イベントが発生している状態Background: アプリがバックグラウンドにあるがコードが実行されている状態Suspened: アプリが実行されている状態AppDelegate.swift ファイルでデリゲート関数となるコードをバックグラウンドで実行していません。 SceneDelegate iOS 13 以降でサポートされるマルチシーン機能にうまく対応するため、AppDelegate / SceneDelegate AppDelegate 1.

iOS アプリのライフサイクル

iOS アプリのライフサイクル

⭐ アプリの起動時 アプリが最初にタップされて起動されたときに AppDelegate が呼び出される順序。func application(_:willFinishLaunchingWithOptions) func application(_:didFinishLaunchingWithOptions:) func applicationDid becomeActive(UIApplication) ⭐ バックグラウンド アプリ これは、アプリがバックグラウンドに移動されるときに AppDelegate が呼び出される順序です。

関連記事

アートは政治的ではないのでしょうか?

アートは政治的ではないのでしょうか?

昨日、私たちは今年のユーロビジョン・ソング・コンテストの幕を閉じました。きらびやかでカオスなグランドフィナーレでスウェーデンの歌手ローリーンがトロフィーを持ち帰り、女性として初めて2回優勝し、ABBAがコンテストで優勝してから50年目にその栄冠をスウェーデンに持ち帰りました。 「ワーテルロー」で。彼らはポップ ミュージックの規範において最大のアーティストの 1 つになりました。

ドメイン名に関する情報の検索

Brian P. Hogan 著『Small, Sharp Software Tools』からの抜粋

ドメイン名に関する情報の検索

facebook.com にリクエストを送信すると、コンピュータはドメイン名を検索してそのドメイン名を IP アドレスに変換し、コンピュータが接続できるようにします。

「マリアナ海溝の公開: 深淵の恐るべき隠された真実を明らかにする」

「マリアナ海溝の公開: 深淵の恐るべき隠された真実を明らかにする」

はじめに:勇敢な読者の皆さん、地球の最も暗い深みへ私たちを導く旅へようこそ。このブログでは、マリアナ海溝の謎に満ちた世界を掘り下げ、その隠された秘密を明らかにし、その表面の下にある骨も凍るような真実を明らかにします。

脅威ハンティングのための OSINT の収集

脅威ハンティングのための OSINT の収集

サイバー愛好家の皆さん、こんにちは!OSINT for Threat Hunting シリーズへようこそ。最初の記事では、OSINT の概要と脅威ハンティングにおけるその重要性について説明しました。