環境はXcode9+Swift3、iOSアプリです。
以下のようなプロトコル、クラスがあります。
swift
1public protocol Pu { 2 func hogeFunc() -> String 3} 4public class CLS_A : Pu { 5 func hogeFunc() -> String{ return "A" } 6} 7public class CLS_B : Pu { 8 func hogeFunc() -> String{ return "B" } 9} 10 11let kage : [Pu] = [ CLS_A() , CLS_B() ]
このプロトコルPu(を実装したクラスCLS_AとCLS_B)にNSKeyedArchiver.archivedData(withRootObject: instance)
を使ったインスタンスのシリアライズ機能を追加しようとしています。
その為にはNSObject,NSCodingの継承が必要です。
そこで、既定のPuプロトコルにNSObject,NSCodingの継承を追加しようとしたのですが
NSObjectはクラスですので「Non-class type 'Pu' cannot inherit from class 'NSObject'」というエラーが出てしまいました。
Puをプロトコルからクラスに変えるのが本来あるべき対処法かと思うのですが、PuをクラスにするとhogeFuncを実装する強制を持たせる事が出来ませんし、すでにあちこちでPuを参照しているコード、型の変数があり変更箇所を可能な限り少なくしたいです。
修正範囲をなるべく狭くしたいという理由で、PuをプロトコルのままでNSObjectを継承させるにはどうしたらよろしでしょうか。
具体的なコードは以下のような内容です。以下のP_C_BはNSObjectを継承していないので、シリアライズ化の時に落ちてしまいます。
protocol Puで、どうにかして「NSObjectを継承する」という制約を付けれればよいのですが。
swift
1protocol Pu : NSCoding{ 2 func test() -> String 3} 4class P_C_A : NSObject, Pu { 5 private let pca : String 6 func test() -> String { 7 return "T_C_A" 8 } 9 override init(){ 10 self.pca = "a" 11 super.init() 12 } 13 required public init?(coder aDecoder: NSCoder) { 14 self.pca = aDecoder.decodeObject(forKey: "pca") as! String 15 } 16 func encode(with aCoder: NSCoder) { 17 aCoder.encode(self.pca, forKey: "pca") 18 } 19} 20class P_C_B : Pu { 21 private let pcb : String 22 init(){ 23 self.pcb = "b" 24 } 25 func encode(with aCoder: NSCoder) { 26 aCoder.encode(self.pcb, forKey: "pcb") 27 } 28 required init?(coder aDecoder: NSCoder) { 29 self.pcb = aDecoder.decodeObject(forKey: "pcb") as! String 30 } 31 func test() -> String { 32 return "T_C_A" 33 } 34} 35class S_t2 { 36 static func extTest(){ 37 let v1 : [Pu] = [ 38 P_C_A(), 39 P_C_B() 40 ] 41 let v2 : Data = NSKeyedArchiver.archivedData(withRootObject: v1) 42 let v3 : String = v2.base64EncodedString() 43 let v4 : Data = Data(base64Encoded: v3)! 44 let v5 : Any = NSKeyedUnarchiver.unarchiveObject(with: v4)! 45 let v6 : [Pu] = NSKeyedUnarchiver.unarchiveObject(with: v4) as! [Pu] 46 47 v6.forEach { (i) in 48 if let d = i as? P_C_A { 49 print("これはPCAです") 50 }else if let d = i as? P_C_B { 51 print("これはPCBです") 52 }else{ 53 print("型の判定に失敗しました") 54 } 55 } 56 print(v1) 57 print(v2) 58 print(v3) 59 print(v4) 60 print(v5) 61 print(v6) 62 } 63} 64S_t2.extTest()

回答2件
あなたの回答
tips
プレビュー