协议扩展无法满足CLLocationManagerDelegate一致性?

Tru*_*an1 6 cllocationmanager ios swift swift2 protocol-extension

我正在尝试CLLocationManagerDelegate通过协议扩展来实现协议要求,但位置管理器在协议扩展中没有看到它并且失败.但是,当移动到类中时,它使用相同的代码.

这是我正在做的事情:

class ViewController: UIViewController, MyLocationProtocol {
    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
        locationManager.distanceFilter = 1000.0
        locationManager.delegate = self

        // Below crashes when implementation in protocol extension
        locationManager.requestLocation()
    }

}

protocol MyLocationProtocol: CLLocationManagerDelegate {
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
}

extension MyLocationProtocol /*where Self: UIViewControll*/ { // Tried using where clause but still no go :(

    // Not being triggered by CLLocationManagerDelegate! :(
    // Move to ViewController class and error goes away
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("MyLocationProtocol: locationManager: didUpdateLocations")
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("MyLocationProtocol: locationManager: didFailWithError")
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意extension MyLocationProtocol我在那里放置didUpdateLocationsdidFailWithError实现.他们永远不会触发,实际上崩溃说:'Delegate must respond to locationManager:didUpdateLocations:'.如果我移动相同didUpdateLocationsdidFailWithError代码ViewController,一切都按预期工作.

有什么我不知道为什么这不通过协议扩展工作?该类被认为符合CLLocationManagerDelegate,否则它将失败locationManager.delegate = self.关于如何使这项工作或某处有错误的任何想法?

use*_*734 2

协议扩展是纯粹的 Swift 人员。协议扩展的调度规则是:

\n\n

如果变量的推断类型是协议

\n\n
    \n
  • 并且该方法是在原始协议中定义的,然后调用运行时 type\xe2\x80\x99s 实现无论扩展中是否有默认实现
  • \n
  • 并且原始协议中未定义该方法,则调用默认实现。
  • \n
\n\n

IF 推断的变量类型是 type\nTHEN 调用 type\xe2\x80\x99s 实现。

\n\n

考虑到这一切......

\n\n
import XCPlayground\nXCPlaygroundPage.currentPage.needsIndefiniteExecution = true\n\nimport Foundation\nimport MapKit\n\n\nclass Lm: NSObject, CLLocationManagerDelegate {\n    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {\n        print("\\(locations)")\n    }\n}\n\n\nclass C:Lm {\n    let lm = CLLocationManager()\n    override init() {\n        super.init()\n        lm.delegate = self\n        lm.startUpdatingLocation()\n    }\n\n}\nlet c = C()\n/*\n2016-02-22 08:41:56.506 Untitled Page 10[32000:11547708] ### Failed to load Addressbook class CNContactNameFormatter\n[<+48.71408491,+21.20868516> +/- 65.00m (speed -1.00 mps / course -1.00) @ 22/02/16 08 h 41 min 57 s Central European Standard Time]\n[<+48.71408491,+21.20868516> +/- 65.00m (speed -1.00 mps / course -1.00) @ 22/02/16 08 h 41 min 57 s Central European Standard Time]\n[<+48.71415732,+21.20859246> +/- 65.00m (speed -1.00 mps / course -1.00) @ 22/02/16 08 h 41 min 57 s Central European Standard Time]\n....\n*/\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种选择是做类似的事情...

\n\n
import XCPlayground\nXCPlaygroundPage.currentPage.needsIndefiniteExecution = true\n\nimport Foundation\nimport MapKit\n\nclass MyLocationManager: CLLocationManager, CLLocationManagerDelegate {\n    override init() {\n        super.init()\n        delegate = self\n    }\n}\nextension MyLocationManager {\n    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {\n        print("\\(locations)")\n    }\n}\nclass C {\n    let lm = MyLocationManager()\n    init() {\n        lm.startUpdatingLocation()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果所有类型在编译时都是已知的,并且协议中没有“可选”方法,则它“按预期”工作

\n\n
protocol P { func foo() }\nextension P { func foo() { print("p") } }\nprotocol P1: P {}\nextension P1 { func foo() { print("p1") } }\nclass C: P {}\nclass C1: P1 {}\nlet c = C()\nlet c1 = C1()\nlet p:P = C()\nlet p1:P = C1()\n\nc.foo()  // p\nc1.foo() // p1\np.foo()  // p\np1.foo() // p1\n
Run Code Online (Sandbox Code Playgroud)\n\n

如需进一步阅读,请参阅

\n