通过 TestFlight 从 iTunes 下载应用程序时出现 NSKeyedArchiver 问题
NSKeyedArchiver Issue when app downloaded from iTunes via TestFlight
我有一个非常奇怪的错误,几天来我一直在努力寻找它。我将游戏的状态数据保存在应用程序的文档目录中的一个文件中。
一切正常,直到最近的 iOS 更新(不确定具体时间,大约 9.0)。突然间,数据无法正确归档/取消归档。
奇怪的是,当我 运行 从 Xcode 将 iPad 绑定到我的 MAC 或在模拟器中时,代码工作正常。当我使用 TestFlight 从 iTunes 下载应用程序时,它不再有效。这使得调试变得极其困难。
我已经检查并仔细检查了所有内容,我正在使用 URL 路径,添加了错误捕获代码等,但是当应用程序通过 TestFlight 从 iTunes 安装时,存档无法正常工作。
作为最后的手段,我添加了新代码来存档我的对象,立即将其取消存档到另一个变量中,然后在标签中显示一些数据。结果对象包含空数据。
没有抛出异常。
重申一下,只有从 iTunes 安装应用程序时,代码才有效。
这是代码片段;
NSString *documentDirectory = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] path];
NSString* filePath = [documentDirectory stringByAppendingPathComponent:@"playerTest.data"];
LBYPlayerData* pd1 = [[LBYPlayerData alloc ]init];
pd1.currentCountryID = 1;
pd1.lsn = @"123.456";
BOOL success = [NSKeyedArchiver archiveRootObject:pd1 toFile:filePath];
NSAssert(success, @"archiveRootObject failed");
LBYPlayerData* pd2 = nil;
@try {
pd2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
} @catch (NSException *exception) {
playerDataLabel.text = [NSString stringWithFormat:@"%@",exception.name];
playerUndoDataLabel.text = [NSString stringWithFormat:@"%@",exception.description];
} @finally {
NSAssert((pd2 != nil), @"archivePlayerDataUndo failed to unarchive");
playerDataLabel.text = [NSString stringWithFormat:@"path: %@",filePath];
playerUndoDataLabel.text = [NSString stringWithFormat:@"Undo Country:%li LSN:%@",(long)pd2.currentCountryID,pd2.lsn];
}
这是数据模型
//
// LBYPlayerData.h
#import <Foundation/Foundation.h>
@interface LBYPlayerData : NSObject
@property (nonatomic,readonly) BOOL isNewGame;
@property (nonatomic) NSInteger playerID;
@property (nonatomic) NSInteger usCardIdx;
@property (nonatomic) NSInteger drawDeckIdx;
@property (nonatomic) NSInteger discardDeckIdx;
@property (nonatomic) NSInteger removeDeckIdx;
@property (nonatomic) NSInteger currentCountryID;
@property (nonatomic) NSString* lsn;
@property (nonatomic) NSString* build;
@end
//
// LBYPlayerData.m
#import "LBYPlayerData.h"
@implementation LBYPlayerData
-(id)init
{
self = [super init];
_isNewGame = YES;
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
// NSLog(@"Saving Player Data");
_isNewGame = NO;
[aCoder encodeBool:_isNewGame forKey: NSStringFromSelector(@selector(isNewGame))];
[aCoder encodeInt64:_playerID forKey: NSStringFromSelector(@selector(playerID))];
[aCoder encodeInt64:_usCardIdx forKey: NSStringFromSelector(@selector(usCardIdx))];
[aCoder encodeInt64:_drawDeckIdx forKey: NSStringFromSelector(@selector(drawDeckIdx))];
[aCoder encodeInt64:_discardDeckIdx forKey: NSStringFromSelector(@selector(discardDeckIdx))];
[aCoder encodeInt64:_removeDeckIdx forKey: NSStringFromSelector(@selector(removeDeckIdx))];
[aCoder encodeInt64:_currentCountryID forKey: NSStringFromSelector(@selector(currentCountryID))];
[aCoder encodeObject:_lsn forKey: NSStringFromSelector(@selector(lsn))];
[aCoder encodeObject:_build forKey: NSStringFromSelector(@selector(build))];
// NSLog(@"Current Counry: %li",(long)_currentCountryID);
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
// NSLog(@"Loading Player Data");
self = [self init];
if (self) {
_isNewGame =[aDecoder decodeBoolForKey:NSStringFromSelector(@selector(isNewGame))];
[self setPlayerID :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(playerID))]];
[self setUsCardIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(usCardIdx))]];
[self setDrawDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(drawDeckIdx))]];
[self setDiscardDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(discardDeckIdx))]];
[self setRemoveDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(removeDeckIdx))]];
[self setCurrentCountryID:[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(currentCountryID))]];
[self setLsn :[aDecoder decodeObjectForKey :NSStringFromSelector(@selector(lsn))]];
[self setBuild :[aDecoder decodeObjectForKey :NSStringFromSelector(@selector(build))]];
}
return self;
}
@end
问题出在 NSAssert 上。我找到了调用函数以在 NSAssert 语句中归档对象的代码。
我有一个非常奇怪的错误,几天来我一直在努力寻找它。我将游戏的状态数据保存在应用程序的文档目录中的一个文件中。
一切正常,直到最近的 iOS 更新(不确定具体时间,大约 9.0)。突然间,数据无法正确归档/取消归档。
奇怪的是,当我 运行 从 Xcode 将 iPad 绑定到我的 MAC 或在模拟器中时,代码工作正常。当我使用 TestFlight 从 iTunes 下载应用程序时,它不再有效。这使得调试变得极其困难。
我已经检查并仔细检查了所有内容,我正在使用 URL 路径,添加了错误捕获代码等,但是当应用程序通过 TestFlight 从 iTunes 安装时,存档无法正常工作。
作为最后的手段,我添加了新代码来存档我的对象,立即将其取消存档到另一个变量中,然后在标签中显示一些数据。结果对象包含空数据。
没有抛出异常。
重申一下,只有从 iTunes 安装应用程序时,代码才有效。
这是代码片段;
NSString *documentDirectory = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] path];
NSString* filePath = [documentDirectory stringByAppendingPathComponent:@"playerTest.data"];
LBYPlayerData* pd1 = [[LBYPlayerData alloc ]init];
pd1.currentCountryID = 1;
pd1.lsn = @"123.456";
BOOL success = [NSKeyedArchiver archiveRootObject:pd1 toFile:filePath];
NSAssert(success, @"archiveRootObject failed");
LBYPlayerData* pd2 = nil;
@try {
pd2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
} @catch (NSException *exception) {
playerDataLabel.text = [NSString stringWithFormat:@"%@",exception.name];
playerUndoDataLabel.text = [NSString stringWithFormat:@"%@",exception.description];
} @finally {
NSAssert((pd2 != nil), @"archivePlayerDataUndo failed to unarchive");
playerDataLabel.text = [NSString stringWithFormat:@"path: %@",filePath];
playerUndoDataLabel.text = [NSString stringWithFormat:@"Undo Country:%li LSN:%@",(long)pd2.currentCountryID,pd2.lsn];
}
这是数据模型
//
// LBYPlayerData.h
#import <Foundation/Foundation.h>
@interface LBYPlayerData : NSObject
@property (nonatomic,readonly) BOOL isNewGame;
@property (nonatomic) NSInteger playerID;
@property (nonatomic) NSInteger usCardIdx;
@property (nonatomic) NSInteger drawDeckIdx;
@property (nonatomic) NSInteger discardDeckIdx;
@property (nonatomic) NSInteger removeDeckIdx;
@property (nonatomic) NSInteger currentCountryID;
@property (nonatomic) NSString* lsn;
@property (nonatomic) NSString* build;
@end
//
// LBYPlayerData.m
#import "LBYPlayerData.h"
@implementation LBYPlayerData
-(id)init
{
self = [super init];
_isNewGame = YES;
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
// NSLog(@"Saving Player Data");
_isNewGame = NO;
[aCoder encodeBool:_isNewGame forKey: NSStringFromSelector(@selector(isNewGame))];
[aCoder encodeInt64:_playerID forKey: NSStringFromSelector(@selector(playerID))];
[aCoder encodeInt64:_usCardIdx forKey: NSStringFromSelector(@selector(usCardIdx))];
[aCoder encodeInt64:_drawDeckIdx forKey: NSStringFromSelector(@selector(drawDeckIdx))];
[aCoder encodeInt64:_discardDeckIdx forKey: NSStringFromSelector(@selector(discardDeckIdx))];
[aCoder encodeInt64:_removeDeckIdx forKey: NSStringFromSelector(@selector(removeDeckIdx))];
[aCoder encodeInt64:_currentCountryID forKey: NSStringFromSelector(@selector(currentCountryID))];
[aCoder encodeObject:_lsn forKey: NSStringFromSelector(@selector(lsn))];
[aCoder encodeObject:_build forKey: NSStringFromSelector(@selector(build))];
// NSLog(@"Current Counry: %li",(long)_currentCountryID);
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
// NSLog(@"Loading Player Data");
self = [self init];
if (self) {
_isNewGame =[aDecoder decodeBoolForKey:NSStringFromSelector(@selector(isNewGame))];
[self setPlayerID :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(playerID))]];
[self setUsCardIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(usCardIdx))]];
[self setDrawDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(drawDeckIdx))]];
[self setDiscardDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(discardDeckIdx))]];
[self setRemoveDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(removeDeckIdx))]];
[self setCurrentCountryID:[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(currentCountryID))]];
[self setLsn :[aDecoder decodeObjectForKey :NSStringFromSelector(@selector(lsn))]];
[self setBuild :[aDecoder decodeObjectForKey :NSStringFromSelector(@selector(build))]];
}
return self;
}
@end
问题出在 NSAssert 上。我找到了调用函数以在 NSAssert 语句中归档对象的代码。