Работа с файловой системой в Swift: практическое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение

Работа с файловой системой — одна из ключевых задач при разработке приложений под iOS и macOS. Независимо от того, пишете ли вы приложение для сохранения пользовательских данных, кэширования изображений или экспорта документов, понимание основ работы с файлами в Swift является обязательным навыком. В этой статье мы разберем практические примеры работы с файловой системой: создание, чтение, запись, удаление файлов и управление директориями.

Apple предоставляет мощный API FileManager, который позволяет взаимодействовать с файловой системой как на iOS, так и на macOS. Мы рассмотрим его на реальных примерах с готовым кодом.

1. Получение путей к системным директориям

Прежде чем начать работу с файлами, нужно получить доступ к правильным директориям. В iOS и macOS каждое приложение работает в изолированной песочнице (sandbox). Для хранения данных используйте следующие пути:

Директория Documents

Используется для хранения пользовательских данных, которые должны сохраняться при обновлениях приложения и резервном копировании.

import Foundation

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}

// Пример использования
let documentsURL = getDocumentsDirectory()
print("Documents path: \(documentsURL.path)")

Директория Caches

Для временных файлов, которые можно пересоздать (например, кэш изображений).

func getCachesDirectory() -> URL {
    let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
    return paths[0]
}

Директория Library/Application Support

Для хранения данных, которые не должны быть доступны пользователю напрямую, но должны сохраняться.

func getApplicationSupportDirectory() -> URL {
    let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    let directory = paths[0]
    // Убедимся, что директория существует
    try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
    return directory
}

2. Создание и запись файлов

Теперь, когда мы знаем, где хранить файлы, научимся их создавать и записывать данные.

Запись текстовых данных

Самый простой способ — использовать метод write(to:) у строки или Data.

func writeTextFile() {
    let fileName = "example.txt"
    let documentsURL = getDocumentsDirectory()
    let fileURL = documentsURL.appendingPathComponent(fileName)
    
    let content = "Hello, Swift! Это тестовый файл."
    
    do {
        try content.write(to: fileURL, atomically: true, encoding: .utf8)
        print("Файл успешно создан: \(fileURL.path)")
    } catch {
        print("Ошибка записи файла: \(error.localizedDescription)")
    }
}

Запись бинарных данных (изображения, JSON)

Для работы с бинарными данными используем Data.

func writeJSONFile() {
    let fileName = "data.json"
    let documentsURL = getDocumentsDirectory()
    let fileURL = documentsURL.appendingPathComponent(fileName)
    
    let dictionary: [String: Any] = [
        "name": "Swift Developer",
        "age": 30,
        "skills": ["iOS", "macOS", "SwiftUI"]
    ]
    
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
        try jsonData.write(to: fileURL, options: .atomic)
        print("JSON файл сохранен")
    } catch {
        print("Ошибка: \(error)")
    }
}

Создание директорий

Иногда нужно создать вложенные папки для организации файлов.

func createSubdirectories() {
    let documentsURL = getDocumentsDirectory()
    let subDirURL = documentsURL.appendingPathComponent("Images/Thumbnails")
    
    do {
        try FileManager.default.createDirectory(
            at: subDirURL,
            withIntermediateDirectories: true,
            attributes: nil
        )
        print("Директория создана: \(subDirURL.path)")
    } catch {
        print("Не удалось создать директорию: \(error)")
    }
}

3. Чтение и проверка существования файлов

Умение читать данные так же важно, как и записывать их.

Проверка существования файла

Всегда проверяйте, существует ли файл, прежде чем пытаться его прочитать.

func fileExists(at url: URL) -> Bool {
    return FileManager.default.fileExists(atPath: url.path)
}

// Проверка
let testFileURL = getDocumentsDirectory().appendingPathComponent("example.txt")
if fileExists(at: testFileURL) {
    print("Файл существует")
} else {
    print("Файл не найден")
}

Чтение текстового файла

func readTextFile(at url: URL) -> String? {
    do {
        let content = try String(contentsOf: url, encoding: .utf8)
        return content
    } catch {
        print("Ошибка чтения файла: \(error)")
        return nil
    }
}

// Использование
if let content = readTextFile(at: testFileURL) {
    print("Содержимое файла:\n\(content)")
}

Чтение JSON файла

func readJSONFile(at url: URL) -> [String: Any]? {
    do {
        let data = try Data(contentsOf: url)
        let json = try JSONSerialization.jsonObject(with: data, options: [])
        return json as? [String: Any]
    } catch {
        print("Ошибка чтения JSON: \(error)")
        return nil
    }
}

Получение списка файлов в директории

Часто нужно перечислить все файлы в папке.

func listFilesInDirectory(at url: URL) -> [URL] {
    do {
        let fileURLs = try FileManager.default.contentsOfDirectory(
            at: url,
            includingPropertiesForKeys: nil,
            options: .skipsHiddenFiles
        )
        return fileURLs
    } catch {
        print("Ошибка получения списка файлов: \(error)")
        return []
    }
}

// Пример
let files = listFilesInDirectory(at: getDocumentsDirectory())
for fileURL in files {
    print("Найден файл: \(fileURL.lastPathComponent)")
}

4. Удаление и перемещение файлов

Управление файлами включает также их удаление и перемещение.

Удаление файла

func deleteFile(at url: URL) {
    do {
        try FileManager.default.removeItem(at: url)
        print("Файл удален: \(url.lastPathComponent)")
    } catch {
        print("Ошибка удаления файла: \(error)")
    }
}

// Использование
deleteFile(at: testFile                

Блоги

Рекомендаций по книгам