2012-05-22 16 views
8

Mam problem z zapisaniem pliku z ciągiem znaków NSSavePanel po wykonaniu piaskownicy w aplikacji dla Mac App Store. Ustawiłem com.apple.security.files.user-selected.read-write na YES, a NSOpenPanel działa tak, jak powinien.NSSavePanel nie zapisuje pliku po Sandboxing aplikacji

Gdy próbuję zapisać nowy plik, choć wydaje się, że wszystko działa dobrze, ale to nie ma zapisany plik, gdzie powinno być ....

Jest to kod używam zapisać plik:

NSSavePanel *save = [NSSavePanel savePanel]; 

long int result = [save runModal]; 

if (result == NSOKButton) 
{ 
    NSString *selectedFile = [save filename]; 
    NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile]; 
    NSString *arrayCompleto = [[NSString alloc]initWithFormat:@"bla bla bla"]; 
    [arrayCompleto writeToFile:fileName 
        atomically:NO 
         encoding:NSUTF8StringEncoding 
         error:nil]; 
} 

Odpowiedz

10

Przede wszystkim, selektor -[NSSavePanel filename] została zaniechana. Zamiast tego użyj -[NSSavePanel URL]. Po drugie, sposób, w jaki -[NSString writeToFile:atomically:encoding:error] mówi, co robisz źle, jest z argumentem error:(NSError**).

Powinieneś również obsługiwać błędy w szczególności dla plików I/O, ponieważ nawet jeśli twój kod jest w 100% poprawny, nadal mogą występować błędy w systemie użytkownika (niewystarczające uprawnienia itp.) I zgłaszanie błędu użytkownikowi pozwoli im zobaczyć, że się nie udało (i nie wiadomo dlaczego). Obsługa błędu w kodzie pozwoli również na odzyskanie aplikacji. Na przykład, jeśli próbujesz odczytać plik poniżej wklejonego kodu (po zapisaniu go na dysku), ale użytkownik próbował zapisać go w udziale sieciowym, do którego nie miał dostępu, aplikacja może ulec awarii. Jeśli wiesz, że zapis nie powiódł się, możesz postępować odpowiednio (być może pytając o inną lokalizację zapisu).

W tym przypadku, choć wierzę, że następujący wiersz jest Twój problem:

NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile]; 

Gdy aplikacja jest piaskownicy, użytkownik musi wyrazić zgodę na albo konkretnego pliku lub konkretnego katalog poprzez panele otwórz/zapisz, aby przenieść je do piaskownicy. To, co robisz, to pobranie pliku, który użytkownik dał ci do napisania i powiedzenie "to świetnie, ale chcę zapisać inny plik", który narusza sandbox. Zamiast tego należy ustawić rozszerzenie w panelu zapisywania. Kompletne rozwiązanie stałe byłoby:

NSSavePanel *save = [NSSavePanel savePanel]; 
[save setAllowedFileTypes:[NSArray arrayWithObject:@"dat"]]; 
[save setAllowsOtherFileTypes:NO]; 

NSInteger result = [save runModal]; 

if (result == NSOKButton) 
{ 
    NSString *selectedFile = [[save URL] path]; 
    NSString *arrayCompleto = @"bla bla bla"; 

    NSError *error = nil; 
    [arrayCompleto writeToFile:selectedFile 
        atomically:NO 
         encoding:NSUTF8StringEncoding 
          error:&error]; 
} 

if (error) { 
    // This is one way to handle the error, as an example 
    [NSApp presentError:error]; 
} 

jeśli w przyszłości jeszcze coś jest nie tak, można sprawdzić wartość error przy starcie. Podczas debugowania ustaw punkt przerwania wewnątrz instrukcji if (error), aby sprawdzić wartość obiektu (wykonaj w debugerze Xcode). To powinno pomóc ci dowiedzieć się, co jest nie tak.

+0

Wielkie dzięki! To działało jak urok !!! Dzięki za pomoc! Massy – Blue

+0

Bez problemu. Zapomniałem też wspomnieć, że szczególnie dobrą praktyką jest radzenie sobie z błędami, gdy mamy do czynienia z plikami I/O, ponieważ nawet jeśli kod jest w 100% poprawny, mogą wystąpić problemy w systemie użytkownika (niewystarczające uprawnienia itp.). Dodałem to do odpowiedzi. – Dov

+0

Można również ustawić żądaną nazwę pliku zapisywania, aby nie była zapisywana jako dokument "Bez tytułu": [save setNameFieldStringValue: @ "MySuggestedFilename"] –

Powiązane problemy