2017-12-20 21 views
0

1(Xcode 9.2、Swift 4)から呼び出されると、次の놀え場コードが行2でクラッシュ(EXC_BAD_ACCESS)します。私の考えでは、これは完全に有効なコードです。Swift EXC_BAD_ACCESSプロトコル拡張で定義されているデフォルトの実装

Observable拡張が削除され、addObserverメソッドが代わりに実装クラス(TestObservableImpl)で定義されていると、クラッシュが消えます。

プロトコルTestObservableListenerが削除され、代わりにTestObserverImplがプロトコルTestObservableのObserverでタイプ制約として使用されていると、クラッシュが消えます。

誰かが手がかりを持っているのはなぜですか、これはちょうどスウィフトバグですか?

public protocol Observable: class { 
    associatedtype Observer: AnyObject 
    var observers: [Observer] { get set } 
    func addObserver(_ observer: Observer) -> Void 
} 

public extension Observable { 
    public func addObserver(_ observer: Observer) -> Void { 
     observers.append(observer) 
    } 
} 

protocol TestObservableListener: class { 
    func bla() 
} 

protocol TestObservable: Observable where Observer == TestObservableListener { 
} 

class TestObservableImpl: TestObservable { 
    typealias Observer = TestObservableListener 
    public var observers = [Observer]() 
    func broadcast() { 
     for observer in observers { 
      //2 
      observer.bla() 
     } 
    } 
} 

class TestObserverImpl: TestObservableListener { 
    func bla() { 
     print("bla") 
    } 
} 

let observable = TestObservableImpl() 
let observer = TestObserverImpl() 
observable.addObserver(observer) 
//1 
observable.broadcast() 
+1

これは問題を解決します: '(observer as!TestObserverImpl).bla()'これは、貧弱な古いランタイムがオブザーバオブジェクトの実際の型を判別するのが難しいように見えます。 –

+0

実際のシナリオでは、具体的なタイプはTestObservableImplでは使用できません(プロトコルで作業する必要があります)が、クラッシュを修正するのは間違いありません。 –

+0

私はそれがおそらく解決策ではないことを理解しています。なぜなら、私はこれをコメントとして追加しました。 –

答えて

1

あなたはこのようassociatedtype ObserverAnyObjectを削除しようとしています:

public protocol Observable: class { 
    associatedtype Observer 
    var observers: [Observer] { get set } 
    func addObserver(_ observer: Observer) -> Void 
} 

を私がテストし、それが仕事です。

Observer == TestObservableListenerAnyObjectProtocolの間で比較します。原因は間違いです。

+1

これはいいですが、私の実装ではObserverはAnyObjectに制約される必要があります。参照等価演算子を定義する必要があります(===) –

+0

@WernerAltewischer私はあなたの答えを完全に理解していません。 'observer'は' TestObservableListener'の型です。それを比較することができます: 'observer in observers { print(observer === observer)}' – motbantuangiauten

+0

実際の実装はObservableプロトコルにしか関係しません。サンプルの残りの部分は私の要点を明確にするためのものです。一般的に、オブザーバは弱参照可能である必要があるため、オブジェクトである必要があります(サンプルオブザーバは単なる配列ですが、実際にオブジェクトを弱く参照するシーケンス実装です) –

関連する問題