I'm using the FileManager for edit, move and delete files in my App. But how can be sure that the method moveItem is completed? Is there any possible callback? I read something about a FileManagerDelegate but I didn't find enough information how to use it. Thanks
Asked
Active
Viewed 3,875 times
2 Answers
6
The moveItem(at:to:)
method is synchronous, which means that it won't move on to any lines of code afterwards until the operation is completed. In Swift, it also throws
, so you know that something went wrong if it gives you an error, and everything is fine if it moves on. You should call it like this:
do{
try FileManager.default.moveItem(at: origURL, to: newURL)
}
catch let error{
// Handle any errors here
dump(error)
}
In Objective-C, it returns a BOOL
that specifies if the operation succeeded, and takes a pass-by-reference NSError
that it will configure if something went wrong. For example:
NSError *error = nil;
BOOL success = [[NSFileManager defaultManager] moveItemAtURL:origURL toURL:newURL error:&error];
if(!success || error){
// Something went wrong, handle the error here
}
else{
// Everything succeeded
}

Michael Hulet
- 3,253
- 1
- 16
- 33
-
It's synchronous but you can still dispatch the work to another queue and dispatch your completion back to the main one. Check my answer. – Au Ris Jul 31 '18 at 09:33
-
You could do this, but ultimately it'd be easier/clearer/more configurable imo if you just handle the queues and whatever code afterwards at the call site – Michael Hulet Jul 31 '18 at 09:36
-
1The point I am trying to make is this kind of work doesn't belong to the main thread (in my option). Where you handle your queues it's up to the developer. – Au Ris Jul 31 '18 at 09:38
2
You could extend your FileManager
to add a few methods for more convenience:
extension FileManager {
func moveItem(at url: URL, toUrl: URL, completion: @escaping (Bool, Error?) -> ()) {
DispatchQueue.global(qos: .utility).async {
do {
try self.moveItem(at: url, to: toUrl)
} catch {
// Pass false and error to completion when fails
DispatchQueue.main.async {
completion(false, error)
}
}
// Pass true to completion when succeeds
DispatchQueue.main.async {
completion(true, nil)
}
}
}
}
And call it like this:
FileManager.default.moveItem(at: atUrl, toUrl: toUrl) { (succeeded, error) in
if succeeded {
// Success
} else {
// Something went wrong
}
}