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

发布于 2024-09-04 20:19:08 字数 2784 浏览 5 评论 0原文

我正在为 iPhone 开发应用程序,但遇到问题...
我有一个带有一些文本字段的视图,其中写入的信息保存在 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;
}

I'm developing an app for iPhone but I've a problem...
I've a view with some textField and the informations writed in them are saved in a plist file. With @class and #import declarations I import this view controller in another controller that manage a table view.
The code I've just wrote appear to be right but my table is filled up with 3 same row...
I don't know why the row are 3...

Can anyone help me?

This is the code for add info:

@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];
}

And this control the table:

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

攒眉千度 2024-09-11 20:19:08

您的第一个问题是 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 did] 中保存一次“完成”操作的结果。将每个字典添加到一个数组中。然后在表视图控制器中,返回表中行数的数组计数。然后在cellForRowAtIndexPath:中,您应该在indexpath.row的数组元素中获取字典。然后从字典中的每个条目获取单元格 UI 元素的文本。

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

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

Your first problem is that NSArray writeToFile: doesn't append to an existing file. It just writes the complete contents of the array to the file. If a file by the same name already exist, then the function overwrites it.

This means that in your code at present, you only ever save an array with three elements. No matter how many times the user saves in the AddWishController's view, only the last three pieces of information captured are ever preserved on disk.

Secondly, your WishlistController is misconfigured.

This:

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

Will always return a count of three because the array in the file always has three elements. However, even that is wrong because you don't want to display each element in separate cell. Your cellForRowAtIndexPath: very clearly puts the first and last elements of the array into each and every cell.

At the very least here, you need a two-dimensional array. Better yet you need an array of dictionaries. Each dictionary will hold the results of one "done" operation in -[AddWishController done]. Put add each dictionary to an array. Then in your tableview controller, return the count of the array for the number of rows in the table. Then in cellForRowAtIndexPath: you should get the dictionary in array element of indexpath.row. Then get the text for the cell UI elements from each entry in the dictionary.

Usually, you also would not save to file until the app quits. Instead, put the array in an property of the app delegate. In AddWishController create a property to refers to the app delegates property. Do the same in the tableview controller. Now you can populate the array in the first controller and read it from the second.

Basically, you need to start over from scratch.

甜尕妞 2024-09-11 20:19:08

在 WishController# load 中,您将三个不同的项目放入数组中,因此,当然,如果在 WishlistController# tableView: numberOfRowsInSection: 中返回 [data count] 作为行数,您将获得三行。
另一方面,您在 WishlistController# tableView: cellForRowAtIndexPath: 中不看应该显示哪个条目,因此它将始终仅显示唯一的单元格。

如果你只想在表格中显示一个单元格,你可以将你的 WishlistController# tableView: numberOfRowsInSection: 替换为

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

如果你想显示多个愿望,你最好制作一个真实的对象,或者至少使用 NSDictionary,其中一个条目在字典表示一个具有多个属性(标题、链接、描述)的对象(=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。真的。

还有两件事:

[data release]; 

-在 WishlistController#tableView:numberOfRowsInSection 中: return 之后的 永远不会被调用。您可能希望

[data autorelease];

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

In WishController# load, you put three different items into the Array, So of course, if in WishlistController# tableView: numberOfRowsInSection: you return [data count] as the number of rows, you get three rows.
On the other Hand, you in WishlistController# tableView: cellForRowAtIndexPath: you do not look, which entry should be presented, so it will always show only the one and only cell.

If you want to present only one cell in your table, you replace your WishlistController# tableView: numberOfRowsInSection: with

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

If you want to show multiple Wishes, you better make a real object of it, or at least use NSDictionary, where one entry in the Dictionary represents one object (=Wish) with multiple attributes (title, link, desc).



If for your first steps in Cocoa/Objective-C you really really want not to look into NSDictionary yet, you could also

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

and then in #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;
}

But this definitly is only for prototyping-to-get-something-displayed. You soon want to look into NSDictionary and before releasing anything, you better learn the use of proper objects for your Data Model, for instance with Core Data. Really.

two more things:
-In WishlistController#tableView:numberOfRowsInSection: the line

[data release]; 

after the return never gets called. You probably want to

[data autorelease];

before the return-statement.
- You do not want to read a file // look for your objects each time a row in your table gets displayed. Create an array as an instance-variable of your controller and use it as your datasource.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文