代码之家  ›  专栏  ›  技术社区  ›  matteodv

读取用于填充表的plist文件时出错

  •  1
  • matteodv  · 技术社区  · 16 年前

    我正在为iPhone开发一个应用程序,但我有一个问题…
    我有一个带有文本字段的视图,其中写入的信息保存在一个plist文件中。通过@class和import声明,我将这个视图控制器导入到另一个管理表视图的控制器中。
    我刚写的代码似乎是正确的,但我的表中有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 回复  |  直到 16 年前
        1
  •  1
  •   TechZen    16 年前

    你的第一个问题是不安全 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控制器中,返回表中行数的数组计数。然后在 行索引路径的单元格: 应该在indexPath.row的数组元素中获取字典。然后从字典中的每个条目中获取单元UI元素的文本。

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

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

        2
  •  0
  •   Mullzk    16 年前

    在wishcontroller load中,您将三个不同的项放入数组中,因此,当然,如果在wishlistcontroller tableview:numberofrowspeagon:返回[数据计数]作为行数,则会得到三行。 另一方面,您在wishListController TableView:cellForRowatindexPath中:您不查看,应该显示哪个条目,因此它始终只显示一个且唯一的单元格。

    如果只想在表中显示一个单元格,则将wishListController TableView:NumberOfRowsPreagon:替换为

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

    如果你想显示多个愿望,你最好把它做成一个真正的对象,或者至少使用nsdictionary,其中字典中的一个条目代表一个具有多个属性(标题、链接、描述)的对象(=愿望)。



    如果你在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,在发布任何内容之前,您最好了解如何为数据模型使用适当的对象,例如核心数据。真正地。

    还有两件事: -在wishListController TableView:NumberOfRowsPreagon:行中

    [data release]; 
    

    回程后再也没有接到电话。你可能想

    [data autorelease];
    

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