将NSMutableArray写入我的文档目录失败

时间:2010-12-28 18:05:48

标签: iphone objective-c persistence nsmutablearray writetofile

我正在尝试缓存网络请求。基本上我有一个使用Facebook用户的朋友列表的应用程序,但我不想每次登录时都抓住它。也许每月刷新一次。在文档目录中的plist中缓存朋友列表似乎对此功能有意义。我这样做如下:

- (void)writeToDisk {
    NSLog(@"writing cache to disk, where cache = %@", cache);
    BOOL res = [cache writeToFile:[FriendCache persistentPath] atomically:YES];
    NSLog(@"reading cache from disk immediately after writing, res = %d", res);
    NSMutableArray *temp = [[NSMutableArray alloc] initWithContentsOfFile:[FriendCache persistentPath]];
    NSLog(@"cache read in = %@", temp);
}

+ (NSString *)persistentPath {
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:@"FriendCache.plist"];
}

这些是我正在使用的FriendCache单例的成员,它基本上包装了一个NSMutableArray。我已经验证peristentPath方法返回一个有效的路径。正如您在writeToDisk方法中看到的那样,我验证缓存中是否有数据然后我打印写入的结果并检查是否可以读回任何数据。从来没有数据读回来,因为结果文件写入为0。

缓存打印的输出很长,但这里是缩写版本:

2010-12-28 13:35:23.006 AppName[51607:207] writing cache to disk, where cache = (
        {
        birthday = "<null>";
        name = "Some Name1";
        pic = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs1324.snc4/7846385648654.jpg";
        "pic_big" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs442.snc4/784365789465746.jpg";
        "pic_square" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs1324.snc4/7846357896547.jpg";
        sex = female;
        status = "<null>";
        uid = 892374897165;
    },
        {
        birthday = "<null>";
        name = "Some Name2";
        pic = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs625.ash1/54636536547_s.jpg";
        "pic_big" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs170.ash2/65465656365666_n.jpg";
        "pic_square" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs625.ash1/654635656547_q.jpg";
        sex = female;
        status = "<null>";
        uid = 7658436;
    },

...

我检查的一件事是在使用writeToFile时,我必须确保我正在编写的对象具有有效的plist对象。我确实检查了这一点,这是我如何构建缓存对象:

- (void)request:(FBRequest*)request didLoad:(id)result{
    NSMutableArray *friendsInfo = [[[NSMutableArray alloc] init] autorelease];

    for (NSDictionary *info in result) {
        NSString *friend_id = [NSString stringWithString:[[info objectForKey:@"uid"] stringValue]];
        NSString *friend_name = nil;
        NSString *friend_sex = nil;
        NSString *friend_relationship_status = nil;
        NSString *friend_current_location = nil;
        if ([info objectForKey:@"name"] != [NSNull null]) {
            friend_name = [NSString stringWithString:[info objectForKey:@"name"]];
        }
        if ([info objectForKey:@"relationship_status"] != [NSNull null]) {
            friend_relationship_status = [NSString stringWithString:[info objectForKey:@"relationship_status"]];
        }
        if ([info objectForKey:@"sex"] != [NSNull null]) {
            friend_sex = [NSString stringWithString:[info objectForKey:@"sex"]];
        }
        if ([info objectForKey:@"current_location"] != [NSNull null]) {
            friend_current_location = [[info objectForKey:@"current_location"] objectForKey:@"name"];
        }
        NSString *friend_pic_square = [info objectForKey:@"pic_square"];
        NSString *friend_status = [info objectForKey:@"status"];
        NSString *friend_pic = [info objectForKey:@"pic"];
        NSString *friend_pic_big = [info objectForKey:@"pic_big"];
        NSString *friend_birthday = [info objectForKey:@"birthday"];
        NSDictionary *friend_info = [NSDictionary dictionaryWithObjectsAndKeys:
                                            friend_id,@"uid",
                                            friend_name, @"name", 
                                            friend_pic_square, @"pic_square", 
                                            friend_status, @"status",
                                            friend_sex, @"sex",
                                            friend_pic, @"pic",
                                            friend_pic_big, @"pic_big",
                                            friend_birthday, @"birthday",
                                            friend_relationship_status, @"relationship_status",
                                            friend_current_location, @"current_location",
                                            nil];

        // If the friend qualifies as a single of your gender, add to the friend cache
        if ( [AppHelpers friendQualifies:friend_info] == YES) {
            [[FriendCache sharedInstance] push:friend_info];
        }
    }
    [[FriendCache sharedInstance] writeToDisk];

}

我的推送方法只包装了NSMutableArray push:

- (void)push:(id)o {
    [cache addObject:o];
}

您能想到写入失败的原因吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

正如我们已经指出的那样,这是因为使用了NSNull个对象。

避免这种情况的最佳方法是创建一个具有所有必需属性的对象Friend。然后,您可以轻松设置nil值,这是NSDictionary个对象无法实现的(嗯,您必须删除密钥,这不是很好的做法)。

然后,通过实施NSCoding协议,您可以轻松归档(序列化)自定义对象。

这是一种更好的数据处理方式,将来会变得更加容易。您可以在Friend对象上调用消息,这是NSDictionary无法实现的。

答案 1 :(得分:1)

为NSPropertyListSerialization使用NSError-aware API来获取数据和NSData NSError感知写入API,以便您收到有意义的错误,帮助您了解问题所在。