通过 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 语句中归档对象的代码。