Ошибка чтения файла plist для заполнения таблицы - PullRequest
1 голос
/ 06 июня 2010

Я разрабатываю приложение для iPhone, но у меня проблема ...
У меня есть представление с некоторыми textField, и информация, записанная в них, сохраняется в файле 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 ]

1 голос
/ 06 июня 2010

Ваша первая проблема - 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]. Поместите добавить каждый словарь в массив. Затем в вашем контроллере таблиц верните количество массивов для количества строк в таблице. Тогда в cellForRowAtIndexPath: вы должны получить словарь в элементе массива indexpath.row. Затем получите текст для элементов интерфейса ячейки из каждой записи в словаре.

Обычно вы также не сохраняете файл, пока приложение не закроется. Вместо этого поместите массив в свойство делегата приложения. В AddWishController создайте свойство, которое ссылается на свойство делегатов приложения. Сделайте то же самое в контроллере таблицы. Теперь вы можете заполнить массив в первом контроллере и прочитать его со второго.

По сути, вам нужно начать все заново.

0 голосов
/ 06 июня 2010

При загрузке WishController # вы помещаете три различных элемента в массив, поэтому, конечно, если в WishlistController # tableView: numberOfRowsInSection: вы возвращаете [количество данных] как количество строк, вы получаете три строки. С другой стороны, вы в WishlistController # tableView: cellForRowAtIndexPath: вы не смотрите, какая запись должна быть представлена, поэтому она всегда будет показывать только одну-единственную ячейку.

Если вы хотите представить только одну ячейку в своей таблице, вы замените свой WishlistController # tableView: numberOfRowsInSection: на

- (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: numberOfRowsInSection: строка

[data release]; 

после возврата никогда не вызывается. Вы, вероятно, хотите

[data autorelease];

до оператора возврата. - Вы не хотите читать файл // искать ваши объекты каждый раз, когда отображается строка в вашей таблице. Создайте массив как переменную экземпляра вашего контроллера и используйте его в качестве источника данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...