What is the modern Swift way to change a filename in the documents directory when you need to replace an existing file of the target name if one exists?
(For this reason, I am not using moveItem... but rather replaceItem
There are a lot of questions on this going back many years such as here but I cannot get any to work for me.
For example:
let oldpicname = "22_contactpic.png"
let newpicname = "9213_contactpic.png"
do {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let documentDirectory = URL(fileURLWithPath: path)
let originPath = documentDirectory.appendingPathComponent(oldpicname)
let destinationPath = documentDirectory.appendingPathComponent(newpicname)
try
print("try to replace file")
FileManager.default.replaceItemAt(originPath, withItemAt: destinationPath)
} catch {
print("FIRST TRY FAILED TO RENAME FILE")
print(error)
}
Compiles and does not throw an error but when I check for the file afterwards it does not exist.
Matt in the above link suggests the following:
var rv = URLResourceValues()
rv.name = newname
try? url.setResourceValues(rv)
This gives a number of errors I can not resolve including you cannot use mutating member on immutable value.
Note I am able to do this in Objective-C with the following code:
- (void)renameWithReplaceFileWithName:(NSString *)beforeName toName:(NSString *)afterName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePathBefore = [documentsDirectory stringByAppendingPathComponent:beforeName];
NSString *filePathAfter = [documentsDirectory stringByAppendingPathComponent:afterName];
NSLog(@"filepath after is%@. This will be the new name of this file",filePathAfter);
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePathBefore]) {
NSError *error = nil;
NSURL *previousItemUrl = [NSURL fileURLWithPath: filePathBefore];/
NSURL *currentItemUrl = [NSURL fileURLWithPath:filePathAfter];
[[NSFileManager defaultManager] replaceItemAtURL:previousItemUrl withItemAtURL:currentItemUrl backupItemName:nil options:0 resultingItemURL:nil error:&error];
if (error) {
// handle error
}
}
}
Thank you for any suggestions.
This works for me, to change the name of a file, using the original code with minor change.
func replace() {
let oldpicname = "22_contactpic.png"
let newpicname = "9213_contactpic.png"
do {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let documentDirectory = URL(fileURLWithPath: path)
let originPath = documentDirectory.appendingPathComponent(oldpicname)
let destinationPath = documentDirectory.appendingPathComponent(newpicname)
// -- here, note the change
let results = try FileManager.default.replaceItemAt(destinationPath, withItemAt: originPath)
print("----> results: \(results)")
} catch {
print("FIRST TRY FAILED TO RENAME FILE")
print(error)
}
}
Alternatively, without NSSearchPathForDirectoriesInDomains, checking that the file exists and using moveItem(...)
:
func renameFile(from oldName: String, to newName: String) {
let docDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let oldFilePath = docDir.appendingPathComponent(oldName)
let newFilePath = docDir.appendingPathComponent(newName)
// check that the file exist first
if FileManager.default.fileExists(atPath: oldFilePath.path) {
do {
try FileManager.default.moveItem(at: oldFilePath, to: newFilePath)
print("---> File renamed \n from: \(oldFilePath) \n to: \(newFilePath)")
} catch {
print("---> Error renaming file: \(error)")
}
} else {
print("----> \(oldFilePath) does not exist")
}
}