2009-08-30 20 views
5

Próbuję napisać do pliku plist przy użyciu writeToFile, zanim napiszę, sprawdzam, czy plik istnieje.Błąd podczas sprawdzania, czy plik istnieje

Jest to kod:

#import "WindowController.h" 

@implementation WindowController 

@synthesize contacts; 

NSString *filePath; 
NSFileManager *fileManager; 

- (IBAction)addContactAction:(id)sender { 

    NSDictionary *dict =[NSDictionary dictionaryWithObjectsAndKeys: 
         [txtFirstName stringValue], @"firstName", 
         [txtLastName stringValue], @"lastName", 
         [txtPhoneNumber stringValue], @"phoneNumber", 
         nil]; 

    [arrayContacts addObject:dict]; 

    [self updateFile]; 
} 

- (void)awakeFromNib { 
    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    filePath = [rootPath stringByAppendingPathComponent:@"Contacts.plist"]; 
    fileManager = [NSFileManager defaultManager]; 

    contacts = [[NSMutableArray alloc] init]; 

    if ([fileManager fileExistsAtPath:filePath]) { 

     NSMutableArray *contactsFile = [[NSMutableArray alloc] initWithContentsOfFile:filePath]; 
     for (id contact in contactsFile) { 
      [arrayContacts addObject:contact]; 
     } 
    } 
} 

- (void) updateFile { 
    if (![fileManager fileExistsAtPath:filePath] || [fileManager isWritableFileAtPath:filePath]) { 
     [[arrayContacts arrangedObjects] writeToFile:filePath atomically:YES]; 
    } 
} 

@end 

Gdy addContactAction jest wykonywany nie dostanę żadnego błędu, ale program zatrzymuje się i doprowadza mnie do debuggera. Po naciśnięciu przycisku kontynuacji w debugerze otrzymuję:

Program received signal: “EXC_BAD_ACCESS”. 

Ale to chyba nie jest ważne.

PS: Jestem nowy w programowaniu w mac i nie wiem, co jeszcze można wypróbować, ponieważ nie pojawia się komunikat o błędzie informujący, co się dzieje.

Ścieżka do pliku jest:

/Users/andre/Documents/Contacts.plist

ja wcześniej próbowałem (z takim samym skutkiem), ale czytałem, że można tylko napisać do folderu dokumenty:

/Users/andre/Desktop/NN/NSTableView/build/Debug/NSTableView.app/Contents/Resources/Contacts.plist

Czy ktoś ma pomysł, a nawet wyjaśnienie, dlaczego tak się dzieje?

Odpowiedz

2

Ustawiasz filePath metodą stringByAppendingPathComponent:. Ta metoda zwraca obiekt autoreleased. (Object autoreleased służy po to został (automatycznie) zwolniony, co może spowodować błąd dostępu złe.)

myślę zmieniając

[rootPath stringByAppendingPathComponent:@"Contacts.plist"]; 

do

[[rootPath stringByAppendingPathComponent:@"Contacts.plist"] retain]; 

rozwiąże swoje problemy.

+0

Wow, to naprawił mój problem, dzięki! Czy możesz powiedzieć mi coś więcej na temat problemu? Jestem pewien, że skopiowałem tę linię z oficjalnego źródła. Wielkie dzięki! –

+0

Polecam zapoznać się z tym poradnikiem: http://cocoadevcentral.com/d/learn_objectivec/. Ma linię mówiącą: "W tym samouczku można założyć, że automatyczny obiekt zniknie na końcu bieżącej funkcji." (Obiekt automatyczny będący autoreleased obiektem).Ciąg, który ustawiłeś "znika" po funkcji awakeFromNib, więc zmienna filePath odwołuje się do czegoś, co już nie istnieje, powodując błędy. Zachowanie go nie zatrzyma go przed autoodtwarzaniem, ale spowoduje wykonanie dodatkowej kopii, która nie zostanie wydana, dopóki jej nie przekażesz. (Które prawdopodobnie powinieneś zrobić w -dealloc.) –

+0

André Hoffmann: Apple ma dobrze ukryty, ale bardzo dobry samouczek dotyczący zarządzania pamięcią kakao na stronie ADC. http://developer.apple.com/mac/library/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html –

7

Po pierwsze, myślę, że nie powinieneś tworzyć instancji obiektu NSFileManager. Zamiast używać domyślnego menedżera plików, na przykład:

[[NSFileManager defaultManager] fileExistsAtPath: filePath]; 

Następnie można określić, w którym linia program łamie do debuggera?

+0

Gdzie mogę zobaczyć, w której linii się on psuł? Pokazuje tylko kod zespołu. Dzięki za podpowiedź z menedżerem plików .. Usunięto instancję, ale niczego nie zmieniłem. –

+0

Po awarii wewnątrz kodu Cocoa, zobaczysz tylko zespół. Po lewej stronie okna debuggera znajduje się lista ramek stosów; wybierz taki, który znajduje się we własnym kodzie, a zobaczysz kod źródłowy, a odpowiednia linia zostanie podświetlona na czerwono. –

+0

Dziękuję Peter. –

Powiązane problemy