拡張機能のSwiftプロトコルクラス/ AnyObject制限

Aug 22 2020

私には2つのプロトコルがあります。1つはオブジェクトにaを与えserverId、もう1つはオブジェクトにaを与えますstatus(別名、サーバーに公開されているかどうか)。それらの2つにより、サーバーモデルとCoreData間の同期を処理できます。

/// By conforming to this protocol, classes AND struct have an identifiable serverid `Int64`
protocol RemoteObject {
    var serverId: ServerId { get set }
}

/// This can only be applied to class
protocol Syncable: class {
    var syncStatus: SyncStatus { get set }

}

enum SyncStatus: Int64 {
    case published
    case local
}

その背後にある考え方は、RemoteObject構造体(つまり、サーバーから返されるJSON構造体)とクラス(NSManagedObject)に適用できるということです。一方、Syncableクラス(NSManagedObject)にのみ適用できます。

次のステップは、syncStatusがに設定されている場合、オブジェクトのfrom RemoteObjectも-1に設定して削除.localする必要がありserverIdますが、試行すると次のエラーが発生します。

extension Syncable where Self: RemoteObject {
    var syncStatus: SyncStatus {
        get {
            SyncStatus(rawValue: syncStatusValue) ?? .local
        }
        set {
            syncStatusValue = newValue.rawValue
            if newValue == .local { serverId = -1 } // 🛑 Cannot assign to property: 'self' is immutable
        }
    }
}

🛑プロパティに割り当てることはできません:「自己」は不変です

RemoteObject不変の構造体に適用できるため、このエラーが発生することを理解しています。

しかし、それSyncableはクラス型にしか適用できないことを考えると、クラスに強制的RemoteObjectに適用するのではないでしょうか。そして、変更可能ですか?

強制する方法があるRemoteObjectようにクラス型を私の延長には?例えばextension Syncable where Self: RemoteObject & class

回答

3 Olympiloutre Aug 22 2020 at 19:06

私は最終的に解決策を見つけました。この投稿によると、私はこれを行うことができます:

extension Syncable where Self: RemoteObject {
    var syncStatus: SyncStatus {
        get {
            SyncStatus(rawValue: syncStatusValue) ?? .local
        }
        set {
            syncStatusValue = newValue.rawValue
            if newValue == .local { 
                var s = self
                s.serverId = -1
            } 
        }
    }
}

これによりエラーが取り除かれ、私が理解している限り、これserverIdは参照型であるクラスに対して変更され、値型である構造体を変更しません(とにかく、これらはこのプロトコルに準拠できません)。


さらに進んで、この投稿が役立つと思う人のために。この問題についての私の理解は正確ではありませんでした。最初はRemoteObject、どのタイプにも適用できるプロトコルに問題があると思いました。

この議論によると、問題は逆のようです。procotol co:classまたはを制限する:AnyObjectと、強制的setter不変になります。

次に、の値を変更しようとすると、不変のセッターから可変のセッターをserverId呼び出しているため、コンパイラーが文句を言います。仕事は、周りしかし、適切な解決策を得るために、私の使用のための罰金ですが、私は取り除く必要があるでクラスのみの最初の場所でそれを作るために私を強制的にすべての理由で、そして契約。:classSyncable