私は数日間追跡しようとしている非常に奇妙なバグがあります。私はゲームの状態データを、アプリケーションのDocumentsディレクトリにあるファイルに保存しています。NSKeyedArchiver TestFlight経由でiTunesからアプリケーションをダウンロードしたときの問題
最新のiOSアップデート(すべてのバージョンは9.0、どこか正確にはわからない)まで、すべてが正常に機能していました。突然、データが正しくアーカイブ/アーカイブ解除されていません。
奇妙な部分は、私のMACに縛られたiPadまたはエミュレータの中で、Xcodeから実行するとコードがうまく動作します。 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'が無効になり、ラベルに割り当てられたNSExceptionの説明は常に' @ finally'ステートメントで上書きされます。だから、あなたはその問題に関する情報を見ることができない、と私は考えている。 – mmtootmm
NSAssertが問題のようです。 NSAssertステートメント内でファイルをアーカイブした関数を呼び出すコードをいくつか見つけました。ありがとう。これは私を夢中にさせている。 – JVC