42

カスタム オブジェクトをアプリの iCloud Docs フォルダーにファイルとして保存する iOS 7 アプリケーションがあります。このために、NSCoding プロトコルを利用します。

@interface Person : NSObject <NSCoding>

    @property (copy, nonatomic) NSString *name
    @property (copy, nonatomic) NSString *lastName

@end

オブジェクトのシリアル化は、アプリの iOS 7 バージョンで完全に機能します。

  1. initWithCoderencodeWithCoder

  2. [NSKeyedArchiver archivedDataWithRootObject:person]

  3. person = NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)theData]

しかし、このアプリを iOS 8 に移行する必要があり、このクラスは迅速にコーディングされ、この新しい iOS 8 バージョンのアプリ用に「名前が変更」されます。

class PersonOldVersion: NSObject, NSCoding {
    var name = ""
    var lastName = ""
}

オブジェクトを解凍しようとすると、次のエラーが発生しました。

*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (Person)'

Swift クラス 'PersonOldVersion' の名前を元のクラス名 ('Person') に変更しようとしましたが、それでも失敗します。

元のクラスが利用できないオブジェクトをデコードするにはどうすればよいですか?

4

5 に答える 5

27

Objective-C のクラスの名前が重要な場合は、名前を明示的に指定する必要があります。それ以外の場合、Swift はマングルされた名前を提供します。

@objc(Person)
class PersonOldVersion: NSObject, NSCoding {
    var name = ""
    var lastName = ""
}
于 2014-09-01T06:04:32.703 に答える
17

上記の Ferran Maylinch の回答を Swift に翻訳したものを次に示します。

製品の 2 つのビルドを作成するために元のターゲットを複製した後、Swift プロジェクトで同様の問題が発生しました。2 つのビルドは、互換的に使用できる必要がありました。

つまり、myapp_light.app と myapp_pro.app のようなものがありました。クラスを設定すると、この問題が修正されました。

NSKeyedUnarchiver.setClass(MyClass1.classForKeyedUnarchiver(), forClassName: "myapp_light.MyClass1")
NSKeyedUnarchiver.setClass(MyClass1.classForKeyedUnarchiver(), forClassName: "myapp_pro.MyClass1")



if let object:AnyObject = NSKeyedUnarchiver.unarchiveObjectWithFile("\path\...") {
    var myobject = object as! Dictionary<String,MyClass1>
    //-- other stuff here
}
于 2016-01-07T16:27:01.573 に答える