读取plist文件以填充表时出错

时间:2010-06-06 13:44:34

标签: ios objective-c iphone uitableview plist

我正在开发适用于iPhone的应用程序,但我遇到了问题...... 我有一些textField的视图,其中写入的信息保存在plist文件中。使用@class和#import声明,我将此视图控制器导入另一个管理表视图的控制器中 我刚才写的代码似乎是对的,但我的桌子上装满了3个相同的行...
我不知道为什么这行是3 ...

任何人都可以帮助我吗?

这是添加信息的代码:

@implementation AddWishController

@synthesize titleField, linkField, descField;

-(NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:plistPath];
}

-(IBAction)done {
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:titleField.text];
    [array addObject:linkField.text];
    [array addObject:descField.text];
    [array writeToFile:[self dataFilePath] atomically:YES];

    [array release];

    [self dismissModalViewControllerAnimated:YES];
}

这可以控制表格:

#import "WishlistController.h"
#import "AddWishController.h"

@implementation WishlistController

@synthesize lista;

-(IBAction)newWish {
    AddWishController *add = [[AddWishController alloc] initWithNibName:@"AddWish" bundle:nil];
    [self.navigationController presentModalViewController:add animated:YES];
    [add release];
}

-(NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:plistPath];
}

#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *data = [[NSArray alloc] initWithContentsOfFile:[self dataFilePath]];
    return [data count];
    [data release];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    NSString *filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
        cell.textLabel.text = [array objectAtIndex:0];
        cell.detailTextLabel.text = [array objectAtIndex:2];

        NSLog(@"%@", array);
    }

    return cell;
}

2 个答案:

答案 0 :(得分:1)

您的第一个问题是NSArray writeToFile:未附加到现有文件。它只是将数组的完整内容写入文件。如果已存在同名文件,则该函数将覆盖该文件。

这意味着在您目前的代码中,您只需保存包含三个元素的数组。无论用户在AddWishController的视图中保存了多少次,只有最后三条捕获的信息会保留在磁盘上。

其次,您的WishlistController配置错误。

此:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *data = [[NSArray alloc] initWithContentsOfFile:[self dataFilePath]];
    return [data count];
    [data release];
}

将始终返回三个计数,因为文件中的数组总是有三个元素。但是,即使这是错误的,因为您不希望在单独的单元格中显示每个元素。您的cellForRowAtIndexPath:非常清楚地将数组的第一个和最后一个元素放入每个单元格中。

至少在这里,你需要一个二维数组。更好的是你需要一系列字典。每个字典将保存-[AddWishController done]中一个“完成”操作的结果。将每个字典添加到数组中。然后在tableview控制器中,返回表中行数的数组计数。然后在cellForRowAtIndexPath:中,您应该在indexpath.row的数组元素中获取字典。然后从字典中的每个条目获取单元格UI元素的文本。

通常,在应用退出之前,您也不会保存到文件。相反,将数组放在app委托的属性中。在AddWishController中创建一个属性来引用app delegates属性。在tableview控制器中执行相同的操作。现在,您可以在第一个控制器中填充数组并从第二个控制器中读取它。

基本上,你需要从头开始。

答案 1 :(得分:0)

在WishController #load中,你将三个不同的项放入数组中,当然,如果在WishlistController#tableView:numberOfRowsInSection:你返回[数据计数]作为行数,你得到三行。 另一方面,你在WishlistController#tableView:cellForRowAtIndexPath:你不看,应该呈现哪个条目,所以它将始终只显示唯一的单元格。

如果您只想在表中显示一个单元格,则替换您的WishlistController#tableView:numberOfRowsInSection:with

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

如果你想展示多个愿望,你最好制作一个真实的对象,或者至少使用NSDictionary,其中Dictionary中的一个条目代表一个具有多个属性(title,link,desc)的对象(= Wish)。



如果你在Cocoa / Objective-C中的第一步,你真的不想再研究NSDictionary,你也可以

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return floor([data count]/3);
}

然后在#tableView:cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        int row = indexPath.row * 3;

        NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
        cell.textLabel.text = [array objectAtIndex:row];
        cell.detailTextLabel.text = [array objectAtIndex:row+2];

        NSLog(@"%@", array);
    }

    return cell;
}

但这绝对只是为了展示原型而得到的东西。您很快就会想要查看NSDictionary,在发布任何内容之前,您最好学习使用适当的对象进行数据模型,例如使用Core Data。真。

另外两件事: -In WishlistController#tableView:numberOfRowsInSection:行

[data release]; 
返回之后

永远不会被调用。你可能想要

[data autorelease];
在返回语句之前

。 - 您不希望读取文件//每次显示表中的行时查找对象。创建一个数组作为控制器的实例变量,并将其用作数据源。