来自对象的一些数据要么不保存,要么不加载

时间:2014-09-12 18:30:40

标签: ios uitableview nskeyedarchiver

我正在制作一个简单的应用来追踪我女儿的曲棍球比赛。我的问题是,当我停止并重新启动应用程序时,一些数据不会被重新加载。(我正在检查一个日志语句,只显示零,无论之前有什么。)我不确定是否问题在于加载或保存。

(对不起,很长的帖子,但我不确定在哪里看。)

它使用如下所示的Games类:

#import <Foundation/Foundation.h>

@interface Game : NSObject <NSCoding>//conforms to this protocol so data can be prepared for read/write to file

//used primarily in GameFactsViewController
@property (nonatomic, strong) NSString *opponent;
@property (nonatomic, strong) NSDate *dateOfGame;

//used primarily in PlayerActionsViewController
@property (nonatomic) NSInteger shotsOnGoal;
@property (nonatomic) NSInteger shotsNotOnGoal;
@property (nonatomic) NSInteger passesCompleted;
@property (nonatomic) NSInteger passesNotCompleted;
@property (nonatomic) NSInteger takeaways;
@property (nonatomic) NSInteger giveaways;
@property (nonatomic) NSInteger faceoffsWon;
@property (nonatomic) NSInteger faceoffsLost;
@property (nonatomic) NSInteger shifts;
@property (nonatomic) NSInteger blockedShots;

@end

我的问题是对手和dateOfGame属性,并在我再次启动应用程序时得到保存和加载,但没有其他属性。

Tha主控制器是一个tableview控制器,每个游戏作为一行。对手和dateOfGame属性设置在tableview控制器中,其他属性设置在选项卡栏控制器内的视图控制器中。这些控制器的序列来自第一个的披露指示器,并通过点击第二个行。这些工作正常,使用此代码:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    //check for proper seque
    if ([segue.identifier isEqualToString:@"AddGame"]) {

        //identify the top level view controller holding the GameFactsVC (see storyboard)
        UINavigationController *navigationController = segue.destinationViewController;

        //go down one level to get the GFVC
        GameFactsViewController *controller = (GameFactsViewController *) navigationController.topViewController;

        //set the current controller (the HSVC) as the delegate for the GFVC
        controller.delegate = self;

    } else if ([segue.identifier isEqualToString:@"EditGame"]) {

        //as above to get to the right place
        UINavigationController *navigationController = segue.destinationViewController;
        GameFactsViewController *controller = (GameFactsViewController *) navigationController.topViewController;
        controller.delegate = self;

        //"sender" here is what was clicked, the detail disclosure icon
        //this identifies what game data to load to edit
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
        controller.gameToEdit = _games[indexPath.row];

    } else if ([segue.identifier isEqualToString:@"GameDetails"]) {

        UITabBarController *tabBarController = segue.destinationViewController;
        PlayerActionsViewController *controller = (PlayerActionsViewController *)[[tabBarController viewControllers] objectAtIndex:0];
        controller.delegate = self;

        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

        controller.gameToEditPerformance = _games[indexPath.row];
        NSLog(@"Data passed %ld", (long)controller.gameToEditPerformance.shotsOnGoal);

    }
}

我使用此方法为对手和dateOfGame返回主控制器,我可以记录回来的数据。

-(IBAction) done
{
    //Use delegate to capture entered data and pass to HSVC
    //methods here are delegate methods listed above and defined in the HSVC

    //see if the data was empty when view loaded
    if (self.gameToEdit == nil) {

        Game *game = [[Game alloc] init];
        game.opponent = self.opponentField.text;
        game.dateOfGame = [self convertToDate:self.dateLabel.text withFormat:@"MMM d, yyyy"];


        [self.delegate gameFactsViewController:self didFinishAddingGame:game];

    } else {
        self.gameToEdit.opponent = self.opponentField.text;//updates data model; will update display in delegate method
        self.gameToEdit.dateOfGame = [self convertToDate:self.dateLabel.text withFormat:@"MMM d, yyyy"];

        [self.delegate gameFactsViewController: self didFinishEditingGame:self.gameToEdit];
    }


}

同样地,我在另一个控制器中使用此行传递剩余的数据,该方法在设置数据值的long方法结束时也可以记录回来的正确数据。

[self.delegate playerActionsViewController:self didEditGameData:self.gameToEditPerformance];

我用这两种类似的方法调用Save方法。 (我看到的关键区别是因为我已经更新了另一个表中的显示,而我仍然需要更新主视图。)

- (void) gameFactsViewController:(GameFactsViewController *)controller didFinishEditingGame:(Game *)game
{
    //edit already made in data model in GFVC
    //need to update display

    NSInteger index = [_games indexOfObject: game];//locate the item being edited in the games array
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];//get the right cell

    [self configureDataForCell:cell withGame:game];//puts the game data into the labels in the cell

    [self saveGames];//write the current data to the file

    [self dismissViewControllerAnimated:YES completion:nil];

}

- (void) playerActionsViewController: (PlayerActionsViewController *) controller didEditGameData: (Game *) game
{
    NSLog(@"Paased back shots %ld", (long) game.shotsOnGoal);
    [self saveGames];


}

现在进行数据保存和加载。我正在使用此代码:

- (void) loadGames
{
    NSString *path = [self dataFilePath];//for convenience below

    //if there is already a data file, unarchive/decode and load games array
    //else create an empty arry to hold games
    if ([[NSFileManager defaultManager] fileExistsAtPath: path]) {

        NSData *data = [[NSData alloc] initWithContentsOfFile: path];//data structure created and loaded with file data
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];//archiver created and connected to data

        _games = [unarchiver decodeObjectForKey:@"Games"];

        [unarchiver finishDecoding];//data now in games array

    } else {

        _games = [[NSMutableArray alloc] initWithCapacity:50];
    }
}

- (void) saveGames
{
    NSMutableData *data = [[NSMutableData alloc] init];//data structure to hold the data to be saved after encoding
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

    [archiver encodeObject:_games forKey:@"Games"];//I believe key here needs to match class name that will be saved. It tells archiver how to encode object properly

    [archiver finishEncoding];//finish encoding, with data now in data structure

    [data writeToFile:[self dataFilePath] atomically:YES];//write data structure to file determined above

}

在这里的某个地方,我认为,两种情况之间的_games数组存在差异,但我没有看到它。或者是其他一些问题。

感谢。

1 个答案:

答案 0 :(得分:1)

问题出在我的游戏课上。我忘了使用

包含对NSIntegers进行编码和解码的密钥
[aCoder encodeInteger:self.shotsOnGoal forKey:@"ShotsOnGoal"];
self.shotsOnGoal = [aDecoder decodeIntegerForKey:@"ShotsOnGoal"];