拡張機能のSwiftプロトコルクラス/ AnyObject制限
私には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
?
回答
私は最終的に解決策を見つけました。この投稿によると、私はこれを行うことができます:
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
呼び出しているため、コンパイラーが文句を言います。仕事は、周りしかし、適切な解決策を得るために、私の使用のための罰金ですが、私は取り除く必要があるでクラスのみの最初の場所でそれを作るために私を強制的にすべての理由で、そして契約。:class
Syncable