NSFilePresenter: що це, протокол NSFileCoordinator та методи відстеження

Автор: IT Sectr Опубліковано: 2026-07-12 Час читання: 7 хв

NSFilePresenter — це протокол Foundation, який дозволяє об’єкту отримувати сповіщення про зміни файлів та каталогів у файловій системі iOS та macOS. Клас реалізує методи протоколу та реєструється через NSFileCoordinator, після чого система автоматично викликає ці методи під час будь-яких операцій з відстежуваним файлом. Згідно з документацією розробників Apple (2025), NSFilePresenter застосовується в додатках з багатопотоковим доступом до документів для запобігання конфліктів запису. Протокол обов’язково використовується в зв’язці з NSFileCoordinator — тільки так забезпечується безпечна координація доступу.

Головне

  • NSFilePresenter — протокол Foundation для відстеження змін файлів та каталогів в iOS та macOS.
  • NSFileCoordinator — обов’язковий парний клас, який керує доступом та викликає методи делегата.
  • accommodatePresentedItemDeletion — метод для обробки видалення відстежуваного файлу з можливістю скасування.
  • presentedItemDidChange — викликається при будь-якій зміні вмісту файлу або каталогу.
  • presentedItemURL — обов’язкова властивість, що повертає URL відстежуваного файлу.

Що таке NSFilePresenter?

NSFilePresenter — це протокол Foundation, призначений для відстеження змін файлів та каталогів в операційних системах Apple. Протокол визначає набір методів, які об’єкт-спостерігач реалізує для отримання сповіщень про події файлової системи.

Основне завдання протоколу — забезпечити безпечний доступ до файлів у багатопотокових сценаріях. В iOS та macOS кілька процесів та потоків можуть одночасно звертатися до одного файлу через NSFileCoordinator, і NSFilePresenter гарантує, що кожен учасник отримає актуальний стан даних.

Протокол включено до Foundation починаючи з iOS 5.0 та macOS 10.7. Він застосовується в додатках, які працюють з документами, базами даних та будь-якими файлами, які можуть змінюватися одночасно з різних джерел — наприклад, під час синхронізації iCloud або спільного редагування.

Де застосовується NSFilePresenter

Додатки орієнтовані на документи — основна область застосування NSFilePresenter. Додатки, які працюють з UIDocument або NSDocument, автоматично реєструють себе як презентерів через NSFileCoordinator. Це дозволяє коректно обробляти конфлікти при редагуванні одного файлу з кількох вікон або пристроїв.

Синхронізація iCloud — другий ключовий сценарій. Коли файл змінюється на одному пристрої, iCloud синхронізує його на всіх підключених пристроях. NSFilePresenter сповіщає додаток про ці зміни, дозволяючи своєчасно оновити інтерфейс.

Багатопотокові редактори — третій сценарій. У додатках, де фонові черги завантажують та зберігають дані одночасно з роботою користувача, NSFilePresenter запобігає станам гонки при запису та читанні файлів.

Як працює NSFilePresenter?

Механізм роботи NSFilePresenter базується на моделі делегування: об’єкт реалізує методи протоколу, реєструється через NSFileCoordinator і отримує виклики при кожній зміні відстежуваного файлу. Система сама визначає, коли відбулася зміна та які методи потрібно викликати.

Процес починається з того, що об’єкт створює екземпляр NSFileCoordinator та викликає метод координатора, передаючи URL файлу. Координатор перевіряє, чи є для цього URL зареєстровані презентери. Якщо так, він блокує доступ на читання або запис та сповіщає презентерам про майбутню зміну через методи протоколу.

Після завершення операції координатор знімає блокування та викликає фінальні сповіщення. Важливо, що презентер не керує потоком виконання — він лише реагує на події. За координацію повністю відповідає NSFileCoordinator.

Життівий цикл сповіщення

Фаза підготовки — перед виконанням операції координатор викликає accommodatePresentedItemDeletion або accommodatePresentedSubitemDeletion. Презентер може обробити ситуацію або скасувати операцію, повернувши помилку. Ця фаза дозволяє додатку коректно завершити роботу з файлом перед його зміною.

Фаза сповіщення — після завершення операції координатор викликає presentedItemDidChange або presentedSubitemDidChange. Презентер отримує сигнал про те, що файл змінився, і може перечитати його вміст. Для переміщення файлу викликається presentedItemDidMoveToURL з новим розташуванням.

Фаза завершення — координатор знімає всі блокування та звільняє ресурси. Презентер може продовжувати роботу з оновленими даними. Усі три фази виконуються синхронно в одному потоці, тому методи протоколу повинні виконуватися швидко, без тривалих операцій вводу-виведення.

Основні методи протоколу

Протокол NSFilePresenter містить кілька обов’язкових та опційних методів. Єдина обов’язкова властивість — presentedItemURL, що повертає URL відстежуваного файлу або каталогу. Без цієї властивості об’єкт не може бути зареєстрований як презентер.

Обов’язкові методи

presentedItemURL — властивість типу URL?, яка повинна повертати шлях до відстежуваного файлу. Якщо об’єкт відстежує кілька файлів, властивість повертає URL основного елемента. Для каталогів повертається URL самого каталогу.

presentedItemDidChange — викликається після зміни вмісту відстежуваного файлу. У цьому методі презентер оновлює свій внутрішній стан та перезавантажує дані. Цей метод не отримує інформацію про те, що саме змінилося — лише факт зміни.

Опційні методи

accommodatePresentedItemDeletion — викликається перед видаленням файлу. Презентер може зберегти поточний стан, закрити файлові дескриптори або скасувати операцію, повернувши NSError. Якщо метод повертає помилку, операція видалення не виконується.

presentedItemDidMoveToURL — викликається після переміщення або перейменування файлу. Метод отримує новий URL, і презентер повинен оновити посилання на файл. Без реалізації цього методу презентер продовжуватиме вказувати на старий, неіснуючий шлях.

NSFilePresenter та NSFileCoordinator

NSFileCoordinator та NSFilePresenter — нерозривна пара. NSFileCoordinator керує доступом до файлів та викликає методи презентера. Презентер не працює безпосередньо з файловою системою — усі операції проходять через координатора, який гарантує атомарність змін.

Координатор реєструє презентера через метод addFilePresenter класу NSFileCoordinator. Після додавання презентер починає отримувати сповіщення. Видалення відбувається через removeFilePresenter. Система зберігає слабке посилання на презентера, тому об’єкт повинен бути живим протягом всього періоду відстеження.

За даними Apple WWDC 2022, NSFileCoordinator використовує механізм координації на рівні ядра, що забезпечує мінімальну затримку при блокуванні. У новітніших версіях iOS координатор оптимізований для роботи з Sandbox та розширеннями додатків.

Правила координації

Intention — кожна операція читання або запису повинна бути обгорнута в блок координації: читання через coordinateReadingItemAtURL, запис через coordinateWritingItemAtURL. Координатор автоматично блокує файл для інших учасників на час виконання блоку.

Batch coordination — для операцій з кількома файлами використовується пакетна координація. Координатор атомарно блокує всі зазначені файли, виконує операцію та знімає блокування. Це критично важливо при переміщенні або копіюванні наборів документів.

Приклад реалізації

Створимо клас DocumentPresenter, який реалізує протокол NSFilePresenter та відстежує зміни файлу документа. Клас містить посилання на файл, внутрішні дані та прапорець актуальності.

swift
import Foundation

class DocumentPresenter: NSObject, NSFilePresenter {
    var presentedItemURL: URL? {
        return self.fileURL
    }

    var presentedItemOperationQueue: OperationQueue {
        return self.queue
    }

    private let fileURL: URL
    private let queue = OperationQueue()

    func presentedItemDidChange() {
        self.reloadData()
    }

    func accommodatePresentedItemDeletion() throws {
        try self.saveCurrentState()
    }

    private func reloadData() {
        let coordinator = NSFileCoordinator(filePresenter: self)
        var error: NSError?
        coordinator.coordinate(readingItemAt: self.fileURL,
                               options: [],
                               error: &error)
        { readURL in
            guard let data = try? Data(contentsOf: readURL)
            else { return }
            self.processData(data)
        }
    }

    private func processData(_: Data) {
        // Обробка даних документа
    }
}

Клас реалізує presentedItemDidChange для перезавантаження даних при зміні файлу та accommodatePresentedItemDeletion для збереження стану перед видаленням. Черга операцій гарантує, що всі сповіщення обробляються послідовно.

Реєстрація презентера виконується через NSFileCoordinator.addFilePresenter при відкритті документа. Важливо передати координатору правильні опції читання — withoutChanges для операцій без модифікації або immediatelyAvailable для сценаріїв з негайним доступом.

Типові помилки

Перша поширена помилка — відсутність реалізації presentedItemOperationQueue. Якщо не вказати чергу, сповіщення можуть надходити в довільному потоці, спричиняючи гонку даних. Завжди використовуйте послідовну OperationQueue для обробки сповіщень.

Друга помилка — блокування в методах презентера. Методи протоколу викликаються синхронно з координатора. Якщо презентер виконує тривалу операцію (запис у БД, мережевий запит), він блокує координатор для всіх інших учасників. Виносьте важкі операції в фонові черги.

Третя помилка — ігнорування accommodatePresentedItemDeletion. Якщо презентер не реалізує цей метод та не повертає помилку, файл може бути видалений без збереження поточного стану. Завжди зберігайте дані в цьому методі, якщо вони ще не записані на диск.

Четверта помилка — циклічна координація. Коли презентер всередині методу сповіщення знову викликає координатора для того ж файлу, виникає взаємне блокування. Перевіряйте прапорець isCoordinatedOperation перед початком координації всередині обробника.

ПомилкаНаслідокРішення
Немає черги операційГонка даних у багатопотоціВказати OperationQueue
Блокування в методахЗависання координатораВинести в фоновий потік
Ігнорування видаленняВтрата даних при видаленніРеалізувати збереження
Циклічна координаціяВзаємне блокування додаткаПрапорець isCoordinatedOperation

Часто запитувані питання

Навіщо потрібен NSFilePresenter, якщо є NSFileHandle?

NSFileHandle — це низькорівнений інтерфейс для читання та запису даних, який не надає механізмів сповіщення про зміни від інших процесів. NSFilePresenter працює на рівні координації: він отримує події від системи при будь-якій зміні файлу, незалежно від джерела — іншого потоку, процесу або iCloud.

Чи обов’язково використовувати NSFileCoordinator з NSFilePresenter?

Так. NSFilePresenter не має сенсу без NSFileCoordinator. Презентер лише визначає методи-обробники, а координатор керує блокуваннями та викликає ці методи. Якщо ви використовуєте NSFilePresenter без координатора, сповіщення не будуть доставлятися.

Чи може один об’єкт бути презентером для кількох файлів?

Може, але з обмеженнями. Властивість presentedItemURL повертає лише один URL, тому для відстеження кількох файлів використовується протокол NSFilePresenter з додатковими методами для піделементів. Альтернатива — створити окремий екземпляр презентера для кожного файлу.

Як NSFilePresenter працює з Sandbox в iOS?

NSFilePresenter повністю сумісний з пісочницею iOS. Додаток може відстежувати файли лише всередині свого контейнера. Для доступу до файлів інших додатків використовуються App Groups або Security-Scoped Bookmarks. Координатор працює в межах дозволів пісочниці.

Що робити, якщо presentedItemDidChange викликається занадто часто?

Використовуйте debounce або throttle всередині методу presentedItemDidChange. Створіть таймер з затримкою 0,3–0,5 секунди та скидайте його при кожному новому виклику. Після стабілізації виконайте перезавантаження даних. Це запобігає багаторазовій обробці одного пакета змін.

Підсумки

  • NSFilePresenter — протокол Foundation для отримання сповіщень про зміни файлів в iOS та macOS, який працює виключно в зв’язці з NSFileCoordinator.
  • Обов’язкова властивість presentedItemURL — без неї об’єкт не може бути зареєстрований як презентер та не отримуватиме сповіщень.
  • Основний метод presentedItemDidChange викликається після будь-якої зміни вмісту файлу — використовуйте його для перезавантаження даних.
  • accommodatePresentedItemDeletion дозволяє коректно обробити видалення файлу та зберегти поточний стан додатка.
  • NSFileCoordinator керує блокуваннями та гарантує атомарність операцій — без координатора презентер не потрібний.
  • Типові помилки включають відсутність черги операцій, блокування в методах та циклічну координацію — їх важливо уникати проектуванням.
  • Debounce presentedItemDidChange при частих викликах — використовуйте таймер для групування змін перед перезавантаженням.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також