我有一个iOS 7应用程序,可以将自定义对象作为文件保存到应用程序的iCloud Docs文件夹中。为此,我使用了NSCoding协议。
@interface Person : NSObject <NSCoding>
@property (copy, nonatomic) NSString *name
@property (copy, nonatomic) NSString *lastName
@end
对象序列化在iOS 7版本的应用程序中完美运行:
initWithCoder
和encodeWithCoder
[NSKeyedArchiver archivedDataWithRootObject:person]
person = NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)theData]
但我需要将此应用程序移至iOS 8,此类将以swift编码并重命名为&#39;这个新的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 class&#39; PersonOldVersion&#39;到原始班级名称(&#39; Person&#39;)但仍然失败。
如何解码原始类不可用的对象?
答案 0 :(得分:57)
这可能是另一种解决方案,而且它是我所做的(因为我不使用Swift)。
就我而言,我存档了一个班级&#34; City&#34;但后来将课程重命名为&#34; CityLegacy&#34;因为我创造了一个全新的城市&#34;类。
我必须这样做才能取消旧的&#34; City&#34;对象作为&#34; CityLegacy&#34;对象:
// Tell the NSKeyedUnarchiver that the class has been renamed
[NSKeyedUnarchiver setClass:[CityLegacy class] forClassName:@"City"];
// Unarchive the object as usual
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"city"];
CityLegacy *city = [NSKeyedUnarchiver unarchiveObjectWithData:data];
答案 1 :(得分:27)
如果Objective-C中类的名称很重要,则需要明确指定名称。否则,Swift将提供一些错误的名称。
@objc(Person)
class PersonOldVersion: NSObject, NSCoding {
var name = ""
var lastName = ""
}
答案 2 :(得分:12)
这是Ferran Maylinch上面的答案的Swift翻译。
在我复制原始目标以获得我的产品的2个版本后,在Swift项目中出现了类似的问题。 2个版本需要可互换使用。
所以,我有像myapp_light.app和app_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
}
答案 3 :(得分:1)
newacct's answer帮助我修改了类名,但是我也遇到了一个问题,我从我的Objective-C类中更改了Swift类中的变量名。使用@objc()
修复了它:
旧班:
@interface JALProgressData : NSObject <NSCoding>
@property (nullable, nonatomic, strong) NSString *platformID;
@property (nonatomic, assign) NSTimeInterval secondsPlayed;
@property (nonatomic, assign) NSTimeInterval totalDuration;
@property (nullable, nonatomic, strong) NSDate *lastUpdated;
@end
新课程:
@objc(JALProgressData)
class VideoProgress: NSObject, NSCoding {
@objc(platformID) var videoId: String?
var secondsPlayed: NSTimeInterval?
var totalDuration: NSTimeInterval?
var lastUpdated: NSDate?
}
我还意识到我正在使用encodeObject
decodeObjectForKey
作为值类型,这导致我的Swift类出现问题。切换为encodeDouble
和decodeDoubleForKey
类型的NSTimeInterval
类型固定aDecoder
,返回nil
这些值。
答案 4 :(得分:1)
我认为您可以按照以下方式解决问题:
@implementation PersonOldVersion
+ (void)load
{
[NSKeyedUnarchiver setClass:[PersonOldVersion class] forClassName:@"Person"];
}