2009-08-03 9 views
7

Jestem całkiem nowy dla obiektywu c i staram się stworzyć małą aplikację dla iPhone'a.
Już prawie skończyłem z tym małym błędem. Właściwie przeszukano godziny w google, aby znaleźć właściwe rozwiązanie, ale niestety nie jestem w stanie znaleźć rozwiązania, które działa.
Używam tego samouczka tutaj, aby przyczyniać się do UITableView: UITableView Tutorial Pełny komunikat o błędzie wygląda następująco:obiekt-c "metoda mutacji wysłana do niezmiennego obiektu" błąd

* Zakończenie aplikację spowodowane nieprzechwyconego wyjątku „NSInternalInconsistencyException”, powód: „* - [ NSCFArray insertObject: atIndex:]: mutacji sposób przesyłane do niezmiennej obiekt”

to nagłówek Sterownik danych: MyLinksDataController.h

@interface MyLinksDataController : NSObject { 

NSMutableArray *tableList; //<---important part 

} 

- (unsigned)countOfList; 
- (id)objectInListAtIndex:(unsigned)theIndex; 
- (void)addData:(NSString *)data; //<---important part 
- (void)removeDataAtIndex:(unsigned)theIndex; 

@property (nonatomic, copy, readwrite) NSMutableArray *tableList; //<---important part 

..... 

i metoda kontrolera danych: MyLinksDataController.m

#import "MyLinksDataController.h" 

@implementation MyLinksDataController 

@synthesize tableList; 

- (id)init { 

    if (self = [super init]) { 

     NSLog(@"Initilizing DataController"); 
     //Instantiate list 
     NSMutableArray *localList = [[NSMutableArray alloc] init]; 
     self.tableList = [localList copy]; 
     [localList release]; 

     //Add initial Data 
     [self addData:@"AAAAAAAAAAAAAA"]; 
     [self addData:@"BBBBBBBBBBBBBB"]; 

    } 

    return self; 

} 

----------------------------- - dalej w kodzie źródłowym ---------------------------------

- (void)addData:(NSString*)data; { 

    [tableList addObject:data]; //<---- here the app crashes 

} 

Chciałbym bardzo doceniam każdą pomoc.

Dziękujemy za wsparcie z góry.

Daniel

Odpowiedz

27

Wysyłanie kopiowania wiadomość do NSMutableArray - jak w poniższym oświadczeniem w init, - zwraca niezmienna kopię.

self.tableList = [localList copy]; 

dokumentacja Cocoa używa słowa niezmienny odnieść tylko do odczytu, can not-be-changed-po-inicjalizacji obiektów. W związku z tym kolejne wywołanie do addObject: kończy się niepowodzeniem z komunikatem o błędzie.

Należy zauważyć, że powyższa instrukcja przypisania nie wyzwala żadnego ostrzeżenia kompilatora. copy zwraca wartość id, która mieści się wygodnie - w odniesieniu do kompilatora - w tabeli tabeli NSMutableArray *. Nie ma tu również błędu runtime, ponieważ żadne wiadomości nie są przekazywane; wskaźnik NSArray jest właśnie umieszczany w zmiennej wskaźnika NSMutableArray.

Aby uzyskać zmienną kopię, należy zamiast tego użyć zmiennego kroju.

Należy zauważyć, że zarówno kopia i mutableCopy utworzyć nową tablicę i skopiuj zawartość oryginalnego do niego. Zmiana kopii nie zostanie odzwierciedlona w oryginale. Jeśli potrzebujesz tylko odniesienia do oryginalnej tablicy, użyj zamiast tego zachowaj.

Możesz znaleźć więcej szczegółów w sekcji dyskusyjnej copyWithZone reference oraz w NSMutableCopying protocol reference.

5

Zasadniczo stosujesz zasady zarządzania pamięcią kakao (specifically, these details). Jeśli istnieje obiekt z immutable version i wersją zmienną, wysłanie -copy do obiektu spowoduje zwrócenie obiektu niezmiennego.

Przejdźmy przez odpowiednią część.

NSMutableArray *localList = [[NSMutableArray alloc] init]; 

To tworzy nową, pustą zmienną tablicę, którą posiadasz. W porządku.

self.tableList = [localList copy]; 

Stwarza to niezmienny kopię pustą tablicę. Ponadto jesteś właścicielem tej świeżo utworzonej kopii. To dwa obiekty, które posiadasz w danym momencie.

Powoduje to również przypisanie skopiowanego obiektu do właściwości tableList. Spójrzmy na deklaracji własności:

@property (nonatomic, copy, readwrite) NSMutableArray *tableList; 

Ta właściwość jest zadeklarowana z copy attribute, więc gdy nowa wartość jest przypisany do niego inna metoda -copy zostanie wysłana do niego. Trzecia kopia nie należy jednak do Ciebie - jest własnością obiektu.

[localList release]; 

To powoduje zwolnienie oryginalnej pustej tablicy zmiennych. W porządku, ale wciąż jest ta, którą utworzyłeś w drugiej linii, nieopublikowana. To przeciek pamięci.

Jeśli rzeczywiście potrzebujesz wymienialnej kopii czegoś, potrzebujesz metody -mutableCopy. (Dokumentacja dla tych metod znajduje się pod NSCopying i NSMutableCopying.) Jednak nigdy nie dostaniesz niepoprawnej wersji czegoś do właściwości z atrybutem copy, ponieważ wyśle ​​ona -copy do tego, co jest przypisane. Twoja nieruchomość należy użyć atrybutu zamiast atrybutu copyretain, a kod do zainicjowania powinno to wyglądać mniej więcej tak:

NSMutableArray *localList = [[NSMutableArray alloc] init]; 
self.tableList = localList; 
[localList release]; 

Lub wersja skrócona:

self.tableList = [NSMutableArray array]; 

Nie ma potrzeby, aby skopiować cokolwiek w tej sytuacji, właśnie tworzysz nowy obiekt.

+1

Jeśli właściwość kopia jest naprawdę wezwał do, a następnie przez zastąpienie zachowują właściwość będzie słabe rozwiązanie. Ponieważ nie ma słowa kluczowego mutablecopy, zadeklaruj właściwość jako kopię, ale wpisz swój własny akcesor zamiast używać syntezowanych akcesorów. –

+0

Dobra uwaga. Dodałbym także, że prawie nigdy nie widzę obiektów, które reklamują właściwość 'NSMutableArray'. Purysta we mnie chciałby zobaczyć niestandardowy seter, który przechowuje zmienną kopię obiektu i niestandardowy getter, który zwraca autoreleased niezmienną kopię. –

0

Cześć zamiast mutableCopy Wierzę, że "strong" może być również używany do rozwiązania tego problemu. Miałem podobny problem w moim kodzie, ponieważ użyłem "copy" zamiast "strong." Tak więc poniżej linii:

@property (copy, nonatomic) NSMutableArray *computers; 

Powinno być:

@property (strong, nonatomic) NSMutableArray *computers; 

nadzieję, że będzie z ogromną pomoc dla początkujących popełniania błędów jak ja.

1

Jeśli przypisujesz localList z innego obiektu, może to nie być Mutable, w takim przypadku może to nastąpić poprzez tego rodzaju błąd.

Mam nadzieję, że będzie to pomocne.

self.tableList = [localList mutableCopy]; 
0

To rozwiąże problem:

NSMutableArray *localList = [[NSMutableArray alloc] init]; 
self.localList = [[NSMutableArray alloc]initWithArray:localList]; 
Powiązane problemy