【问题标题】:Data loads but won't save iPhone app数据加载但不会保存 iPhone 应用程序
【发布时间】:2013-11-07 07:54:50
【问题描述】:

我已经坚持了大约两个星期。我讨厌张贴那些被问了很多但我真的都经历过的东西。

我使用 Ray Wenderlich 的教程在 iPhone 应用中保存数据。

http://www.raywenderlich.com/tutorials

这就是我在我的应用程序中进行的设置。我正在保存非常简单的对象。 My Card 对象由名称、类型和图像组成。就这样。所以这个教程和我的很接近。这让这更令人沮丧。

问题是,我有一些 NSLog 语句用于加载。我让它显示它用来加载的文件夹以及它加载的对象。现在它正在显示这个。

Loading cards from /Users/zach/Library/Application Support/iPhone Simulator/7.0.3-64/Applications/E3DB01FD-A37E-4A69-840B-43830F2BDE2C/Library/Private Documents
2013-11-04 00:02:50.073 CardMinder[84170:a0b] ()

所以它似乎正在尝试加载它们,但没有任何东西可以加载。这是我保存数据的功能。

- (void)saveData {
    if (_data == nil) return;

    [self createDataPath];

    NSString *dataPath = [_docPath stringByAppendingPathComponent:kDataFile];
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:_data forKey:kDataKey];
    [archiver finishEncoding];

    NSLog(@"%@",dataPath);
    NSLog(@"%@",data);

    [data writeToFile:dataPath atomically:YES];

}

这正是该教程中发布的内容。我知道如果你愿意慷慨地帮助我,我将不得不发布更多代码,但我不想在帖子中充斥着无用的东西,所以请告诉我,我会在这里发布。

非常感谢任何可以提供帮助的人,我最近进入了绝望状态,需要帮助。

谢谢

更新

    NSError *error;
    [data writeToFile:dataPath options:NSDataWritingAtomic error:&error];
    NSLog(@"error: %@", error.localizedFailureReason);

这些是 CardData 类的方法。我在这里填写名称、类型和布尔值。

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_name forKey:kNameKey];
    [aCoder encodeObject:_cardType forKey:kTypeKey];
    [aCoder encodeBool:_checkedOut forKey:kOutKey];

}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    NSString *name = [aDecoder decodeObjectForKey:kNameKey];
    NSString *cardType = [aDecoder decodeObjectForKey:kTypeKey];
    BOOL checkedOut = [aDecoder decodeBoolForKey:kOutKey];
    return [self initWithName:name cardType:cardType _Bool:checkedOut];
}

更新 2

我只是在其中添加了一些 NSLog 语句,我发现当我在我的应用程序中按下“保存卡”按钮时,它似乎根本没有执行 saveData 函数。我在 saveData 函数中有大量的日志语句,当我单击 saveCard 按钮时,它不会显示任何这些日志。为什么会这样?

这是我的保存按钮代码。

- (IBAction)saveNewCard:(id)sender
{
    NSString *cardName = self.nameField.text;

    _cardDoc.data.name = cardName;


    CardDoc *newCard = [[CardDoc alloc] initWithName:cardName cardType:cardTypeString _Bool:NO image:chosenIcon];

    [_cardDoc saveData];
    NSLog(@"Card save button pressed!");

    CardViewController *cardViewController = (CardViewController *)[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2];

    [cardViewController.cards addObject:newCard];
    [self.navigationController popToRootViewControllerAnimated:YES];


}

【问题讨论】:

  • 你应该使用writeToFile:options:error:而不是writeToFile:atomically:;这会给你一个错误信息,应该证明是有帮助的。 (等价于atomically:YES 是选项常量NSDataWritingAtomic。)
  • 我在帖子的更新中添加了我在更新中发布的行,对吗?如果是这样,它不会给我一个错误。这让我觉得这不是这个功能。哪个不好大声笑
  • 检查错误的常用方法是if (![data writeToFile:...]) {,然后在块内登录。我猜如果你没有看到错误,那么data 就是nil。在 Objective-C 中,消息 nil 是有效的。
  • saveNewCard 未触发的可能原因:它未连接到情节提要中的按钮。
  • saveNewCard 正在触发。我已经把它连接起来了,我只是通过拖拽故事板来完成的。 “按下了卡保存按钮!”日志显示。是 saveData 没有触发,因为我没有收到任何这些日志

标签: ios iphone objective-c


【解决方案1】:

您应该使用writeToFile:options:error: 而不是writeToFile:atomically:;这会给你一个错误信息,应该证明是有帮助的。 (等价于atomically:YES 是选项常量NSDataWritingAtomic。)确保你得到了YES 的返回值;如果不是,则应设置错误。

如果您收到 NO 的值但未设置错误,则表示您正在向 nil 发送消息。 Objective-C 的一个怪癖是消息nil 是完全有效的。如果方法被定义为返回一些东西,你甚至会得到一个结果:0 或等价物(NOnil 等)

在这种情况下,您正在向_cardDoc 发送消息。没有返回结果可检测。这有点难以防御性编码,但[_cardDoc saveData] 实际上是[nil saveData]。调试器会轻而易举地越过这条线。

一般来说,如果绝对不应该是nil,你可以使用NSAssert

NSAssert(_cardData, @"_cardData should not be nil");
[_cardData saveData];

但要谨慎使用它;您可能会通常会欣赏这种行为。

【讨论】:

  • 感谢 NSAssert 位。非常感谢您的帮助。
  • 很高兴我能帮上忙。 :)
【解决方案2】:

一些事情。

发布您的日志语句的结果,以便我们了解您所看到的。

为了使您的方法正常工作,您的 _data 对象需要符合 NSCoding 协议。这意味着您需要将协议声明添加到您的接口,并实现方法 encodeWithCoder 和 initWithCoder。

在这些方法中,您需要保存对象的所有状态数据/将状态重新加载到对象中。

这些方法最有可能导致您的代码出现问题。如果您需要帮助,请发布这些方法,并在调试器中遍历它们。

您还可以查看 NSKeyedArchvier 类方法 archivedDataWithRootObject。该方法需要一个对象并一步将其编码为 NSData 对象。方法archiveRootObject:toFile: 更进一步,将数据直接写入文件。

NSKeyedUnarchiver 有相应的方法 unarchiveObjectWithData 和 unarchiveObjectWithFile 来从数据/文件重新创建你的对象。

【讨论】:

  • 好的,我们开始吧。我确实有我的 _data 对象符合 NSCoding 协议,我知道。我已经实现了 encodeWithCoder 和 initWithCoder 方法。我会发布这些,我认为这些相当简单。我一直在阅读 NSKeyedArchiver 但我不确定我是否正确使用它。我想我把它复杂化了。我觉得有比我使用的教程更简单的方法,但我已经设置好了,所以我想让它工作。
猜你喜欢
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多