Tôi có ứng dụng iOS dựa trên tài liệu với lớp con UIDocument
. Tôi cần để có thể di chuyển tệp mà nó đại diện trên hệ thống tệp. Tôi đã xem xét di chuyển nó với một số NSFileManager
, nhưng điều này sẽ làm hỏng tài sản fileURL
của UIDocument
. Bất kỳ ý tưởng về cách giải quyết câu hỏi hóc búa này?Cách thích hợp để di chuyển UIDocument đến vị trí mới trên hệ thống tệp
Trả lời
Bạn có thể đổi tên UIDocument bằng cách đóng nó lần đầu tiên, và sau đó trong trình xử lý hoàn thành, di chuyển tệp bằng NSFileManager. Một khi tập tin đã được chuyển thành công, khởi tạo một thể hiện mới của lớp con UIDocument của bạn bằng cách sử dụng URL mới file:
NSURL *directoryURL = [_document.fileURL URLByDeletingLastPathComponent];
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSString *filePath = [directoryURL.path stringByAppendingPathComponent:@"NewFileName"];
[_document closeWithCompletionHandler:^(BOOL success) {
NSError *error;
if (success)
success = [fileManager moveItemAtPath:_document.fileURL.path toPath:filePath error:&error];
if (success) {
NSURL *url = [NSURL fileURLWithPath:filePath];
// I handle opening the document and updating the UI in setDocument:
self.document = [[MyDocumentSubclass alloc] initWithFileName:[url lastPathComponent] dateModified:[NSDate date] andURL:url];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Unable to rename document" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
[alert show];
NSLog(@"Unable to move document: %@", error);
}
}];
Tôi thấy điều này trong đặc tả UIDocument
lớp (5.1):
Thực hiện
NSFilePresenter
Giao thứcLớp
UIDocument
thông qua giao thứcNSFilePresenter
. Khi một khách hàng khác cố gắng đọc tài liệu của ứng dụng dựa trênUIDocument
, việc đọc đó bị tạm ngưng cho đến khi đối tượngUIDocument
được trao cơ hội lưu bất kỳ thay đổi nào được thực hiện cho tài liệu.Mặc dù một số triển khai không làm gì cả,
UIDocument
triển khai tất cả các phương thứcNSFilePresenter
. Cụ thể,UIDocument
:Thực hiện
relinquishPresentedItemToReader:
để chuyển tiếp các khối đến để .Thực hiện
relinquishPresentedItemToWriter:
để kiểm tra xem ngày sửa đổi tệp có thay đổi hay không; nếu tệp mới hơn trước, nó gọirevertToContentsOfURL:completionHandler:
với giá trị của thông sốfileURL
làm thông số URL.Thực hiện
presentedItemDidMoveToURL:
để cập nhật URL tệp của tài liệu (fileURL
).Trong lớp con
UIDocument
của bạn, nếu bạn ghi đè phương thứcNSFilePresenter
, bạn luôn có thể gọi triển khai siêu lớp (super
).
Tôi đã vô vọng tìm kiếm và tôi hy vọng những điều trên sẽ hữu ích. Tôi chưa thử nghiệm nó - Tôi đang nhảy vào nó ngay bây giờ.
Vì vậy, về cơ bản, nếu tôi không bỏ lỡ bất cứ điều gì ở đây, bạn phải di chuyển tài liệu bằng cách sử dụng NSFileManager
và sau đó gọi presentedItemDidMoveToURL:
trên tài liệu của bạn. Bạn có thể di chuyển tệp bằng cách sử dụng NSFileCoordinator
, để đảm bảo bạn không gặp sự cố.
Vui lòng sửa mọi thứ trong câu trả lời này sai. Tôi vẫn là n00b trong tất cả nội dung đó.
Đây là ý tưởng đúng, nhưng tôi không nghĩ bạn nên gọi trực tiếp 'presentationItemDidMoveToURL:', mà đúng hơn là gọi thông báo điều phối tệp. Lý do chính là bạn có thể có nhiều hơn một người trình bày tệp đang mở và việc gọi các phương thức thông báo sẽ đảm bảo tất cả họ đều nhận được nó. – Elland
Điều này có thể cũ nhưng vẫn có liên quan.
Những gì bạn muốn làm là như sau:
Đối với di chuyển: di chuyển tập tin bằng cách sử dụng NSFileCoordinator, bên trong khối của điều phối viên, hãy gọi
[fileCoordinator itemAtURL:URL willMoveToURL:toURL];
[fileManager moveItemAtURL:newURL toURL:toURL error:&moveError];
[fileCoordinator itemAtURL:URL didMoveToURL:toURL];
Đối với xóa: ghi đè lên lớp con UIDocument của bạn hoặc thực hiện các tập tin phương thức giao thức người trình bày accommodatePresentedItemDeletionWithCompletionHandler:
để đóng tài liệu.
- (void)accommodatePresentedItemDeletionWithCompletionHandler:(void (^)(NSError *))completionHandler;
{
[self closeWithCompletionHandler:^(BOOL success) {
NSError *err;
if (!success)
err = [NSError error]; // implement your error here if you want
completionHandler(err);
}];
}
Do đó đảm bảo nó sẽ xử lý chính xác việc di chuyển.
Mặc dù điều này sẽ hoạt động, bạn không phải lúc nào cũng có thể đóng tài liệu trước khi di chuyển mà không vi phạm đóng gói. – Elland