Современный способ изменить имя файла в каталоге документов в Swift

Каков современный способ Swift изменить имя файла в каталоге документов, когда вам нужно заменить существующий файл с целевым именем, если он существует?

(По этой причине я не использую moveItem... а использую replaceItem

Есть много вопросов по этому поводу, возникающих много лет назад, например, здесь, но я не могу найти ни одного, который бы работал на меня.

Например:

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)
    }

Компилируется и не выдает ошибку, но когда я потом проверяю файл, он не существует.

Мэтт в приведенной выше ссылке предлагает следующее:

var rv = URLResourceValues()
rv.name = newname
try? url.setResourceValues(rv)

Это дает ряд ошибок, которые я не могу устранить, в том числе невозможно использовать мутирующий член для неизменяемого значения.

Примечание. Я могу сделать это в Objective-C с помощью следующего кода:

- (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
        }
    }
}

Спасибо за любые предложения.

Уверяю вас, что мой подход к изменению имени файла работает. Однако я вовсе не уверен, что вы этого хотите; вы вроде бы говорите, что хотите заменить сам файл, а это другое дело.

matt 20.06.2024 01:50

У вас есть все, что нужно, чтобы изменить имя файла. Используйте try FileManager.default.replaceItemAt(destinationPath, withItemAt: originPath). Обратите внимание: не ставьте try перед print("try to replace file"), только перед FileManager.default.....

workingdog support Ukraine 20.06.2024 03:52

вам нужно объявить свой URL как var

Leo Dabus 20.06.2024 07:48

у меня работает с let

workingdog support Ukraine 20.06.2024 09:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У меня это работает, чтобы изменить имя файла, используя исходный код с небольшими изменениями.

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)
    }
}

Альтернативно, без NSSearchPathForDirectoriesInDomains проверка существования файла и использование 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")
    }
}

Другие вопросы по теме