簡體   English   中英

Swift - 另一個協議中協議功能的默認實現

[英]Swift - Default Implementation of protocol functions in another protocol

以下代碼只是一個示例:我需要在我的 ViewController class 中實現MapProtocol ViewController 本身有一個MKMapView類型的變量。 但是在我的情況下, MKMapViewDelegate需要通過協議的擴展來實現,並且不能由 ViewController class 實現,但這不起作用。 委托 function 根本不會被調用(僅當由 ViewController 實現時)

我是否缺少 swift 限制以在另一個協議中添加協議的默認實現? 如果是,是否有適當的解決方法?

真實案例:我有兩個 ViewController,它們共享一些冗余代碼(MKMapViewDelegate 等)。 所以我想外包這段代碼。 我不能使用超類,因為兩個視圖控制器已經是兩種不同類型的子類。 我的第一種方法是使用擴展協議。

import UIKit
import MapKit

class ViewController: UIViewController, MapProtocol {

    var mapView: MKMapView = MKMapView()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setupMapView()
    }

    private func setupMapView() {
        self.view.addSubview(mapView)

        mapView.mapType = MKMapType.standard
        mapView.isZoomEnabled = true
        mapView.isScrollEnabled = true
        mapView.delegate = self

        mapView.translatesAutoresizingMaskIntoConstraints = false
        mapView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
        mapView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
        mapView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
        mapView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true
    }
}

/** Works if uncommented */
//extension ViewController: MKMapViewDelegate {
//    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
//        NSLog("test")
//    }
//}

protocol MapProtocol: MKMapViewDelegate {
    var mapView: MKMapView { set get }
}

extension MapProtocol {
    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        NSLog("test")
    }
}

這有點奇怪,但我認為委托的調度查找不會在協議添加時“看到”委托方法。 協議擴展是靜態綁定的,而不是動態查找方案的一部分。

如果我正確理解了這個問題,您希望避免在不同的視圖控制器中重復“地圖相關代碼”。

在這種情況下,為什么不使用“數據源”方法,創建一個額外的 class ViewControllerMapInjector或任何名稱,並在初始化時傳遞 vc 並執行您喜歡的任何方法

class ViewControllerMapInjector: MKMapViewDelegate {
    private let vc: UIViewController
    init(vc: UIViewController) {
       self.vc = vc
    }

    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        NSLog("test") // or use the vc as you want. 
    }
}

然后在 viewController setup()

self.mapView.delegate = ViewControllerMapInjector(vc: self)

最終,您可能需要對視圖 controller 應用其他模式,以便在需要時讓提供者可以看到其他方法(最后最簡單的解決方案是 go 完整的 OO 和子類 ViewController)。 這有點令人費解,但我能想到的替代方案並不簡單。

如果您認為func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool)是一個 MKMapViewDelegate 協議方法,那就錯了。 它只是您創建的方法,而不是 MKMapViewDelegate 方法。

extension MapProtocol {

    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        NSLog("test")
    }
}

這也是您的委托方法沒有調用的原因。 viewController 收到回調,因為mapView.delegate = self 這里沒有 MapProtocol 的作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM