Цель C - UITableView после вызова reloadData свойства моего объекта имеют значение null/nil

У меня есть ViewController, определенный следующим образом:

@interface SectionController : UITableViewController {
   NSMutableArray *sections;
}
- (void) LoadSections;

Когда вызывается LoadSection, он вызывает NSURLConnection для загрузки URL-адреса, который, в свою очередь, вызывает

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

    [connection release];
    [responseData release];

    NSDictionary *results = [responseString JSONValue];
    NSMutableArray *jSections = [results objectForKey:@"Items"];
    sections = [NSMutableArray array];

    for (NSArray* jSection in jSections)
    {
        Section* section = [Section alloc];
        section.Id = [jSection objectForKey:@"Id"];
        section.Description = [jSection objectForKey:@"Description"];
        section.Image = [jSection objectForKey:@"Image"];
        section.Parent = [jSection objectForKey:@"Parent"];
        section.ProductCount = [jSection objectForKey:@"ProductCount"];
        [sections addObject:section];
        [section release];
    }

    [jSections release];
    [results release];

    [delegate sectionsLoaded];

    [self.view reloadData];
}

Данные обрабатываются правильно, и теперь у меня есть разделы, заполненные множеством элементов.

Вызов [self.view reloadData] вызывает обратный вызов метода делегата cellForRowAtIndexPath, который затем должен представить данные в ячейку, однако в этот момент sections снова равен нулю.

Может кто-нибудь указать на мою ошибку? Я должен признать, что я новичок в объективе c, и это, вероятно, проблема с указателем. Что нужно сделать, так это сохранить значение разделов после вызова reloadData.

Большое спасибо.


person Chris    schedule 09.10.2010    source источник


Ответы (2)


Увидев новый код, проблема очевидна:

sections = [NSMutableArray array];

должен стать

[sections release];
sections = [[NSMutableArray alloc] init];

обратите внимание, что массив не становится снова «нулевым», вместо этого он освобождается, и вы получаете недопустимую ссылку, которая может (должна) вызвать сбой при разыменовании.

Я предлагаю вам прочитать несколько статей об управлении памятью с подсчетом ссылок, так как это может быть неочевидно, если вы новичок в Objective-C, и часто приводит к ошибке (например, автовыпуск — это вовсе не волшебство)

person Bitgamma    schedule 09.10.2010
comment
Извините, я отредактировал пост, чтобы включить реальную функцию, и я выпускал переменную раздела, хотя хорошее место. Проблема по-прежнему остается в том, что после вызова reloadData, разделы равны нулю. Это похоже на сброс всего контроллера просмотра. - person Chris; 09.10.2010
comment
Я обновил ответ, чтобы отразить новый код. Я надеюсь, что это помогает - person Bitgamma; 09.10.2010
comment
Спасибо за ответ, но это ничего не изменило. - person Chris; 09.10.2010
comment
Тогда, возможно, это поможет опубликовать весь класс и подробности о том, как он не работает. - person Bitgamma; 09.10.2010
comment
Проблема возникает из-за того, что я выпускаю [выпуск jSections]; и [обнародование результатов];. Разве это не хорошая привычка убирать за собой? Похоже, что когда я анализирую данные json, он может передавать указатель, и освобождение этих объектов убивает эту ссылку? Итак, как я могу избежать утечек памяти в этом случае? - person Chris; 10.10.2010
comment
Я таких не заметил. Вам не нужно выпускать их на самом деле, потому что вы их не сохраняете. Правило простое: если вы создаете объект с помощью alloc/init, вам нужно освободить его, когда вы закончите с ним. Если вы вручную сохраняете объект, вам нужно освободить его, когда вы закончите с ним. Во всех остальных случаях этого делать не нужно, потому что другие объекты (ответственные по упомянутым выше правилам) сделают это сами по мере освобождения. - person Bitgamma; 10.10.2010
comment
Замечательно. Большое спасибо за Вашу помощь. Я чувствую, что мои знания немного продвинулись вперед в эти выходные. - person Chris; 10.10.2010

лучший способ избежать всех утечек памяти здесь - просто использовать @property (nonatomic, retain) NSMutableArray *sections; с помощью свойства, вы можете быть уверены, что все работы по управлению людьми будут правильно управляться системой. Просто не забывайте, что свойство сохраняет значение, когда вы выполняете setSections:, так что вам нужно передать здесь автоматически выпущенный объект.

self.sections = [NSMutableArray array];

...

[self.sections addObject:section];

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

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];

NSDictionary *results = [responseString JSONValue];
NSMutableArray *jSections = [results objectForKey:@"Items"];
self.sections = [NSMutableArray array];

for (NSArray* jSection in jSections) {
    Section* section = [[[Section alloc] init] autorelease];
    section.Id = [jSection objectForKey:@"Id"];
    section.Description = [jSection objectForKey:@"Description"];
    section.Image = [jSection objectForKey:@"Image"];
    section.Parent = [jSection objectForKey:@"Parent"];
    section.ProductCount = [jSection objectForKey:@"ProductCount"];
    [self.sections addObject:section];
}

[delegate sectionsLoaded];

[self.view reloadData];

}

А также большая часть объекта, который вы пытаетесь освободить, уже автоматически выпущена: все параметры, переданные в ваш метод, не должны быть выпущены вручную, проверьте, я думаю, что JSONValue также должен возвращать автоматически выпущенный объект и все, что вы получаете путем перечисления или вызовом objectForKey:

person iiFreeman    schedule 17.12.2012