2012-05-22 20 views
8

Tôi gặp sự cố khi lưu tệp chuỗi với NSSavePanel sau khi sandboxing ứng dụng cho Mac App Store. Tôi đặt com.apple.security.files.user-selected.read-write thành YESNSOpenPanel đang hoạt động như mong muốn.NSSavePanel không lưu tệp sau khi sandboxing ứng dụng

Khi tôi cố gắng lưu một tập tin mới, tuy nhiên, có vẻ như mọi thứ đều hoạt động tốt, nhưng sau đó không có tập tin đã lưu, nơi nó nên ....

Đây là mã tôi đang sử dụng để tiết kiệm tệp:

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]; 
} 

Trả lời

10

Trước hết, bộ chọn -[NSSavePanel filename] không được dùng nữa. Sử dụng -[NSSavePanel URL] để thay thế. Thứ hai, cách mà -[NSString writeToFile:atomically:encoding:error] cho bạn biết bạn đang làm gì sai với đối số error:(NSError**).

Bạn cũng nên xử lý lỗi cho tệp I/O nói riêng, vì ngay cả khi mã của bạn chính xác 100%, vẫn có thể có lỗi trên hệ thống của người dùng (không đủ đặc quyền, v.v.) và trình bày lỗi cho người dùng sẽ cho phép họ nhìn thấy nó thất bại (và có một số ý tưởng tại sao). Xử lý lỗi trong mã cũng sẽ cho phép ứng dụng của bạn khôi phục. Ví dụ: nếu bạn cố gắng đọc trong tệp bên dưới mã bạn đã dán (sau khi ghi nó vào đĩa), nhưng người dùng đã cố gắng viết nó vào một mạng chia sẻ mà họ không có quyền truy cập, ứng dụng của bạn có thể gặp sự cố. Nếu bạn biết viết không thành công, bạn có thể tiến hành tương ứng (có thể nhắc cho một vị trí lưu khác).

Trong trường hợp này, tuy nhiên, tôi tin rằng các dòng sau là vấn đề của bạn:

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

Khi ứng dụng của bạn là sandboxed, người sử dụng cần để cung cấp cho bạn phép hoặc là một tập tin cụ thể hoặc một cụ thể thư mục thông qua các bảng mở/lưu để đưa chúng vào hộp cát của bạn. Những gì bạn đang làm là lấy tệp mà người dùng cấp cho bạn quyền viết và nói "điều đó thật tuyệt, nhưng tôi muốn lưu một tệp khác", vi phạm sandbox. Những gì bạn nên làm thay vào đó là thiết lập phần mở rộng trong Save Panel. Giải pháp cố định hoàn chỉnh sẽ là:

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]; 
} 

Nếu trong tương lai có điều gì đó sai, bạn có thể kiểm tra giá trị error khi chạy. Trong khi gỡ lỗi, hãy đặt một điểm ngắt trong câu lệnh if (error) để kiểm tra giá trị của đối tượng error (thực hiện po error trong trình gỡ rối của Xcode). Điều đó sẽ giúp bạn tìm ra điều gì sai.

+0

Cảm ơn bạn rất nhiều! Nó làm việc như một say mê!!! Cảm ơn sự giúp đỡ của bạn! Massy – Blue

+0

Không sao cả. Tôi cũng quên đề cập đến việc xử lý lỗi bất cứ khi nào bạn xử lý tệp I/O, vì ngay cả khi mã của bạn chính xác 100%, có thể có sự cố trên hệ thống của người dùng (không đủ đặc quyền, v.v.). Tôi đã thêm vào câu trả lời. – Dov

+0

Bạn cũng có thể đặt tên tệp lưu được nhắc để nó không lưu dưới dạng tài liệu 'Không có tiêu đề': [lưu setNameFieldStringValue: @ "MySuggestedFilename"] –

Các vấn đề liên quan