2009-07-07 16 views
5

Ok, also habe ich eine UIViewTable und eine UISearchBar mit zwei Scope-Buttons. Die Idee ist, dass, wenn ich eine Scope-Taste drücke die Datenquelle für UIViewTable geändert wird, aber ich bekomme EXC_BAD_ACCESS Fehler.iphone EXC_BAD_ACCESS mit NSMutableArray

Ich habe den folgenden Code in meinem UIViewController SearchViewController.m:

- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange: (NSInteger) selected scope 
{ 
    MyAppDelegate *delegate = (MyAppDelegate *) [[UIApplicationsharedApplication] delegate]; 
    if (self.listData != nil) { 
     [self.listData release]; 
    } 
    if (selectedScope == 0) { 
     self.listData = [delegate.data getListOne]; 
    } 
    else { 
     self.listData = [delegate.data getListTwo]; 
    } 
} 

- (void) viewDidLoad { 
    MyAppDelegate *delegate = (MyAppDelegate*) [[UIApplication sharedApplication] delegate]; 
    self.listData = [delegate.data getListOne]; 

    //some other unrelated code 
} 

in meinem SearchViewController.h ich habe:

@property (nonatomic,retain) NSMutableArray *listData; 

in meinem Data.m ich habe:

-(NSMutableArray *) getListOne { 
    NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:@"test1", 
                    @"test2", 
                    nil]; 
    [list autorelease]; 
    return list; 
} 

-(NSMutableArray *) getListTwo { 
    NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:@"test3", 
                    @"test4", 
                    nil]; 
    [list autorelease]; 
    return list; 
} 

Es stürzt ab:

self.listData = [delegate.data getListTwo]; 

Ich habe überprüft, dass es ist, wenn ich die Eigenschaft einstellen, dass es abstürzt. Mein Verständnis ist, dass ich, wenn ich das neue NSMutableArray in Data.m erstelle, es Autorelease wie ich sollte zuweisen.

Wenn die Ansicht geladen wird, weise ich sie meinem listData zu, und da ich auf die Eigenschaft zugreife, die beibehalten wurde, wird der Referenzzähler erhöht (also jetzt 2 ausstehende automatische Freigabe).

Wenn ich den Knopf drücke, um die Datenquelle zu ändern, überprüfe ich auch, ob listData existiert (was immer der Fall ist), lasse ihn los, so dass der alte NSMutableArray-Zähler 0 ist (angenommen, dass Autorelease aufgetreten ist).

Dann bekomme ich ein neues NSMutableArray und setze es auf diese Eigenschaft ... ist mein Verständnis korrekt? Ich habe viel zu lange auf dieses einfache Problem verbracht :(

oh auch ich habe eine andere NSMutableArray, die nicht mit der TableView verbunden war und immer noch das gleiche Problem, auch wenn ich es nicht in meiner If-Anweisung die Problem existiert nicht, aber ich werde dann ein Speicherleck haben ?? ich konnte immer nur das Array halten und entfernen/Objekte hinzufügen, aber ich möchte wissen, warum dies nicht funktioniert :) prost

+0

Nur als Stiltipp können Sie Ihre Methoden getListOne/getListTwo auf verschiedene Arten vereinfachen. Zum Beispiel könnten Sie die letzten 2 Zeilen von jedem in return [list autorelease] kombinieren. Sie können es in eine einzelne Zeile zusammenfassen, indem Sie ein automatisches Array mit + arrayWithObjects anstelle von + alloc und -initWithObjecs zurückgeben: - Es bedeutet dasselbe, ist aber etwas kürzer. :-) –

Antwort

7

das ist Ihr Problem:

if (self.listData !=nil) 
{ 
    [self.listData release]; 
} 

Sie müssen diese Prüfung nicht durchführen - aufgrund der Tatsache, dass Sie diedeklariert haben 210 Eigenschaft mit der retain Eigenschaft, kümmert sich der synthetisierte Setter automatisch um release den alten Wert. Die synthetisierte Setter würde wie folgt aussehen:

- (void) setListData:(NSMutableArray *)listData 
{ 
    [listData retain]; 
    [self->listData release]; 
    self->listData = listData; 
} 

Hinweis ein paar Dinge, hier: der alte Wert freigegeben wird, und der neue Wert wird beibehalten. Weiterhin tritt die Retain vor der Freigabe auf, im Fall der Selbstzuweisung: Wenn Sie den gleichen Wert zuweisen, möchten Sie nicht, dass es vorzeitig freigegeben wird. Beachten Sie auch, dass, wenn der neue oder alte Wert nil ist, nichts Schlimmes passiert, da Objective-C explizit erlaubt, Nachrichten an nil zu senden, ohne Wirkung.

Das bedeutet also, dass Sie bei der Festlegung der Eigenschaft keine Bedenken haben müssen, den alten Wert freizugeben - der Setter erledigt das für Sie. Da Sie eine zusätzliche Version erstellen, wird das Objekt freigegeben, bevor Sie es tatsächlich verwenden. Sobald Sie es also nach der Zuweisung verwenden, erhalten Sie die EXC_BAD_ACCESS.

+0

+1 - Sie können diesen Codeblock vollständig entfernen, da Sie self.listData im Zweig if oder sonst setzen. Dem Fragesteller: Sei nicht frustriert über die Zeit, die du damit verbracht hast, dies zu klären; Es ist ein ehrlicher Fehler und eine gute Lernerfahrung. Jeder macht irgendwann einmal so etwas, und zu verstehen, wie synthetisierte Eigenschaften funktionieren, kann manchmal schwierig sein. :-) –

+0

ah ja jetzt sehe ich =) Ich wusste nicht, was der Synthesizer hinter den Kulissen gemacht hat. Prost! – Allan

Verwandte Themen