2010-11-14 2 views
0

Я танцевал с тамбурином какое-то время, но до сих пор не знаю, в чем причина этой ошибки. У меня есть таблицаView с историей пользовательских запросов данных из базы sqlite. Я новичок в разработке iPhone, поэтому мой код может быть немного чрезмерным. Иерархия:таблица прокрутки: сообщение отправлено на освобожденный экземпляр

  • HistoryModel модель-объект с некоторыми методами инициализации

  • HistoryDataController получает данные из базы данных и представляет собой массив HistoryModel объектов

  • HistoryViewController подкласс UITableView отображает данные

  • AppDelegate там я изначально хранить массив объектов HistoryModel (получая его от HistoryDataController) для HistoryViewController доступа к нему.

Проблема заключается в том, когда я прокручивать таблицу или открыть вкладку с ним во второй раз - он выходит из строя с - [CFString сохранить]: сообщение, отправленное высвобождены например

код :

HistoryModel.h довольно ненужный класс для этого случая, но я хочу, что работал, чтобы повторить в нескольких одинаковых случаях, но немного сложнее

@interface HistoryModel : NSObject { 
    int entry_id; 
    NSString *word; 
} 

- (id)initWithWord:(NSString *)word; 
- (id)initWithWord:(NSString *)word andId:(int)entry_id; 

@property int entry_id; 
@property (retain) NSString *word; 

@end 

HistoryModel.m

@implementation HistoryModel 

@synthesize entry_id, word; 

- (id)initWithWord:(NSString *)_word { 
    [super init]; 
    word = _word; 
    return self; 
} 

- (id)initWithWord:(NSString *)_word andId:(int)_entry_id { 
    entry_id = _entry_id; 
    return [self initWithWord:_word]; 

@end 

HistoryDataController.h я использовать объект этого класса в качестве геттера данных и хранилище для объектов HistoryModel (в historyEntries собственности)

@interface HistoryDataController : NSObject { 
    NSMutableArray *historyEntries; 
    int limit; 
} 

@property (nonatomic, retain) NSMutableArray *historyEntries; 
@property int limit; 

- (id)initWithHistoryData; 
- (id)initWithHistoryDataLimitedBy:(int)limit; 

ИсторияDataController.m

@implementation HistoryDataController 
@synthesize historyEntries, limit; 

- (id)initWithHistoryDataLimitedBy:(int)_limit { 
    [super init]; 

    // Getting data from database 
    {some DB stuff} 

    NSMutableArray *tmp_historyEntries = [[NSMutableArray alloc] init]; 
    while(result == SQLITE_ROW) 
    { 
     HistoryModel *currentHistoryEntry = [[HistoryModel alloc] initWithWord:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)] ]; 
     [tmp_historyEntries addObject:currentHistoryEntry]; 
     result = sqlite3_step(statement); 
    } 
    historyEntries = tmp_historyEntries; 

    {some DB stuff} 
    return self; 
} 
@end 

HistoryViewController.h подкласс UITableViewController, получает данные, хранящиеся в свойстве AppDelegate и отображает в таблице

@interface HistoryViewController : UITableViewController { 
    IBOutlet UITableView *historyTable; 
    SynonymsAppDelegate *appDelegate; 
} 

@property (retain) UITableView *historyTable; 

@end 

HistoryViewController.m

@implementation HistoryViewController 
@synthesize historyTable, historyEntriesToShow; 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    appDelegate = (SynonymsAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    [appDelegate initHistoryList]; 
    [self.tableView reloadData]; 
} 

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

    {standart cell stuff} 

    HistoryModel *historyEntry = [appDelegate.historyList objectAtIndex:indexPath.row]; 
    cell.textLabel.text = historyEntry.word; 
    return cell; 
} 

@end 

SynonymsAppDelegate.ч при открытии вкладки истории, она получает данные historyList имущества, которое было сформировано по HistoryDataController :)

@interface SynonymsAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> { 
    ... 
    NSMutableArray *historyList; 
} 
... 
@property (retain) NSMutableArray *historyList; 

- (void)initHistoryList; 

@end 

SynonymsAppDelegate.m

@implementation SynonymsAppDelegate 
@synthesize window, tabBarController, historyList; 

- (void)initHistoryList { 
    HistoryDataController *historyDataController = [[HistoryDataController alloc] initWithHistoryData]; 
    historyList = historyDataController.historyEntries; 
} 

@end 

Фуф. Извините за столько кода, но я считаю, что все это необходимо. В результате половины дня, потраченного на этот вопрос, я могу догадаться, эта проблема каким-то образом связана с объектом HistoryModel, потому что когда я удаляю «сохранить» для слово @property, ошибка переключается на - [CFString isEqualToString: ]: сообщение, отправленное высвобождены например

Я не очень опытный в управлении памятью, но я предполагаю, что это HistoryModel объекты внутри historyEntry в HistoryViewController или historyList в AppDelegateвыпускает как-то, прокручивая стол или открывая вкладку во второй раз. Но это только мои догадки. Действительно оцените помощь.

+0

Довольно длинные, но важные части отсутствуют. Для свойств NSString вы почти всегда хотите (копировать) вместо сохранения. Может оказаться полезным дополнительный код для вашей HistoryModel. Вероятно, код находится в другом месте, хотя, возможно, релиз для автореализованной NSString. – Eiko

+0

Не знаю, если это проблема, но я думаю, вам нужно сохранить в appDelegate: historyList = [historyDataController.historyEntries сохранить]; – Rengers

+0

Спасибо, я попробовал все, что вы предложили, но это не решило проблему. Для Eiko: это все код HistoryModel, который у меня есть, за исключением методов init, которые, как я уже упоминал, все равно не используются. Rengers, я попробовал ваше решение, это не помогло, но я постараюсь сохранить другие объекты. На самом деле, я еще не занимался управлением памятью, потому что я не знаком с этим, и это только начало программы. – nikans

ответ

1

У вас определенно есть проблема в вашем - [HistoryModel initWithWord] Вы должны сохранить (или еще лучше скопировать) строку, которая передается.

Я бы написал так:

- (id)initWithWord:(NSString *)_word { 
    [super init]; 
    self.word = _word; // this is same as [self setWord:_word] 
    return self; 
} 

Там будут некоторые, кто бы сказал, используя метод установки в вашей инициализации не является хорошей практикой. Я не из этого лагеря. Но в любом случае вам нужно сохранить или скопировать эту строку.

Тогда у вас есть аналогичная проблема в делетете приложения, в котором вы протекаете каждый HistoryDataController при создании нового. (и это происходит каждый раз, когда появляется табличное представление). И вы действительно должны сохранить этот массив (хотя это еще не вызвало проблемы, поскольку вы просачиваете HistoryDataControllers и, следовательно, маскируете эту проблему до сих пор.)

Мой общий совет вам не будет отложить управление памятью. Чтобы вернуться позже и попытаться понять, что это сложно, он подвержен ошибкам даже для опытного разработчика. Гораздо проще создавать правильные методы управления памятью в коде при его написании. Это означает, что стоит потратить время, чтобы прочитать руководство по управлению памятью, прежде чем начинать кодировать что-то вроде этого. Вы сэкономите много времени и разочарований.

+0

Большое спасибо. Теперь, когда он работает относительно стабильно, я прочитаю некоторую информацию об управлении памятью и попытаюсь исправить эти проблемы. Но могу ли я спросить, что это значит: «у вас есть аналогичная проблема в делетете приложения, где вы протекаете каждый HistoryDataController при создании нового». Я не полностью понял концепцию утечки). Что я должен сделать, чтобы исправить эту проблему? – nikans

+0

Если он протекает, он не работает. Это просто работает временно. :) Если вы посмотрите в свой [SynonymAppDelegate initHistoryList], вы каждый раз создаете новый HistoryDataController. Но тогда вы его не выпускаете. Если все, что требуется от этого контроллера, это массив, вы должны сохранить этот массив и затем освободить контроллер. Надеюсь, это поможет. –

+0

Спасибо, я постараюсь применить это :) – nikans

Смежные вопросы