Proxy-Entwurfsmuster

In diesem Beitrag sprechen wir über das ProxyEntwurfsmuster und ein einfaches Beispiel, wie es in diesem Fall in iOS-Anwendungen verwendet wird, um Aufbewahrungszyklen auf effektive und saubere Weise zu verhindern.

Was ist das Proxy-Entwurfsmuster?

Wie im Buch Design Patterns von Gamma, Johnson, Vlissides, Helm und Mitarbeitern definiert, ist das Proxy-Designmuster definiert:

Stellen Sie einen Ersatz oder Platzhalter für ein anderes Objekt bereit, um den Zugriff darauf zu steuern. Es lässt die Verbraucher glauben, dass sie mit der tatsächlichen Implementierung sprechen.

Und das Diagramm sieht folgendermaßen aus:

Diagramm aus Wikipedia

Wenn Sie zum ersten Mal von diesem Entwurfsmuster hören, kann es ein wenig verwirrt sein, und ihre Vorgehensweise kann überhaupt nicht klar sein. Aber lassen Sie mich ein Beispiel geben, um zu erklären, wo dieses Entwurfsmuster verwendet werden kann.

Verwenden eines Proxys im Entwurfsmuster der MVP-Benutzeroberfläche

Wenn wir in iOS-Anwendungen mit einem UI-Entwurfsmuster wie MVP arbeiten, stellen wir fest, dass ein Aufbewahrungszyklus erstellt werden kann, wenn der Ansichtscontroller aufgrund eines bidirektionalen Kommunikationskanals zwischen Viewund nicht geschwächt wirdPresenter . Sehen wir uns das Diagramm an:

Zum Beispiel:

// 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?

'schwach' darf nicht auf nicht klassengebundene 'Ansicht' angewendet werden; Erwägen Sie das Hinzufügen einer Protokollkonformität, an die eine Klasse gebunden ist

Wir können diesen Kompilierungsfehler leicht beheben, indem das Protokoll nur für Klassen erstellt wird (mit dem classSchlüsselwort wird das Protokoll nur für Klassen erstellt ). Diese Einschränkung ist The protocol to which all classes implicitly conform.wie folgt definiert :

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))
        }
    }
}

In der WeakRefProxySurrogat wir die reale Umsetzung mit einem weakVerweis darauf, dass wir alle Zyklen behalten vermeiden wollen ist. Und jetzt Composition Rootsieht unser so aus:

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
    }
}

Generisches machen unseren WeakRef Proxy

Natürlich kann das Erstellen eines WeakRefProxysehr langwierig sein, daher können wir ein generisches erstellen und die ViewMethoden wie folgt in eine Erweiterung implementieren :

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)
    }
}

Suggested posts

App-Lebenszyklus

App-Lebenszyklus

: Zyklus vom App-Start bis zum Herunterfahren: Benutzerfreundlichkeit durch Speicher- oder Datenverwaltung ⬆️ Sicherheit kann verarbeitet werden UIApplication, AppDelegate-Situation: Definiert Funktionen, die das AppDelegate-Objekt vom UIApplication-Objekt gesendete Nachrichten empfängt und jeweils ausführt. Nicht ausgeführt: Der Status, in dem die App nicht ausgeführt wird. Inaktiv: Der Status, in dem die App ausgeführt wird, aber keine Ereignisse empfangen werden. Aktiv: Der Status, in dem die App ausgeführt wird und ein Ereignis auftritt. Hintergrund: Der Status, in dem sich die App im Hintergrund befindet, der Code jedoch ausgeführt wird. Gesperrt: Der Status, in dem sich die App befindet Im Hintergrund ausgeführt und kein Code ausgeführt, um Delegate-Funktionen in der AppDelegate.swift-Datei SceneDelegate auszuführen, um gut auf die ab iOS 13 unterstützte Funktion für mehrere Szenen zu reagieren, AppDelegate / SceneDelegate AppDelegate 1.

iOS-App-Lebenszyklus

iOS-App-Lebenszyklus

⭐ wann die App startet Die Reihenfolge, in der AppDelegate aufgerufen wird, wenn die App zum ersten Mal angetippt und gestartet wird. func application(_:willFinishLaunchingWithOptions) func application(_:didFinishLaunchingWithOptions:) func applicationDidBecomeActive(UIApplication) ⭐ Hintergrund-App Dies ist die Reihenfolge, in der AppDelegate aufgerufen wird, wenn die App in den Hintergrund verschoben wird.

Related posts

Informationen zu Domänennamen finden

Ein Auszug aus Small, Sharp Software Tools von Brian P. Hogan

Informationen zu Domänennamen finden

Wenn Sie eine Anfrage an facebook.com stellen, sucht Ihr Computer nach dem Domänennamen, um diesen in eine IP-Adresse zu übersetzen, damit Ihr Computer diese Verbindung herstellen kann.

Dieses Bedrohungsarchiv: Band 7 Black Basta

Dieses Bedrohungsarchiv: Band 7 Black Basta

In der heutigen vernetzten Welt ist die Bedrohung durch Cyberangriffe größer denn je. Cyberkriminelle und nationalstaatliche Akteure versuchen ständig, Schwachstellen auszunutzen und wertvolle Daten zu stehlen, was ein erhebliches Risiko für Unternehmen jeder Größe darstellt.

Finanzierung der CO2-Entfernung im Geschäftsjahr 24

Die Aufschlüsselung der Mittelanträge von Carbon180 nach Pfaden

Finanzierung der CO2-Entfernung im Geschäftsjahr 24

Von Alyson Lee, geschäftsführende Beraterin für Regierungsangelegenheiten Der jährliche Bewilligungsprozess der Bundesregierung ist von zentraler Bedeutung für unsere Bemühungen zur Finanzierung der Kohlendioxidentfernung (CDR). Jedes Jahr reicht Carbon180 Anfragen an verschiedene Kongressbüros ein, um zu bestimmen, wohin die Dollars im nächsten Jahr fließen werden.

Medien neu denken: McChesneys fünf Wahrheiten und die Zukunft der Kommunikation

In der heutigen hypervernetzten Welt spielen Mediensysteme eine entscheidende Rolle bei der Bildung der öffentlichen Meinung und damit bei der demokratischen Entscheidungsfindung. In seiner tiefgreifenden Analyse der politischen Ökonomie der Kommunikation stellt der Wissenschaftler Robert McChesney die herkömmliche Meinung in Frage und präsentiert die „fünf Wahrheiten“ über die Medien, wie er sie nennt.