NSFilePresenter: co to jest, protokół NSFileCoordinator i metody śledzenia

Autor: IT Sectr Opublikowano: 2026-07-12 Czas czytania: 7 min

NSFilePresenter — to protokół Foundation, który pozwala obiektowi otrzymywać powiadomienia o zmianach plików i katalogów w systemie plików iOS i macOS. Klasa implementuje metody protokołu i rejestruje się przez NSFileCoordinator, po czym system automatycznie wywołuje te metody przy każdej operacji na śledzonym pliku. Według Apple Developer Documentation (2025), NSFilePresenter jest stosowany w aplikacjach z wielowątkowym dostępem do dokumentów w celu zapobiegania konfliktom zapisu. Protokół jest obowiązkowo używany w parze z NSFileCoordinator — tylko w ten sposób zapewnione jest bezpieczne koordynowanie dostępu.

Najważniejsze

  • NSFilePresenter — protokół Foundation do śledzenia zmian plików i katalogów w iOS i macOS.
  • NSFileCoordinator — obowiązkowa klasa partnerska, która zarządza dostępem i wywołuje metody delegata.
  • accommodatePresentedItemDeletion — metoda do obsługi usunięcia śledzonego pliku z możliwością anulowania.
  • presentedItemDidChange — wywoływana przy każdej zmianie zawartości pliku lub katalogu.
  • presentedItemURL — obowiązkowa właściwość zwracająca URL śledzonego pliku.

Co to jest NSFilePresenter?

NSFilePresenter — to protokół Foundation przeznaczony do śledzenia zmian plików i katalogów w systemach operacyjnych Apple. Protokół określa zestaw metod, które obiekt-obserwator implementuje, aby otrzymywać powiadomienia o zdarzeniach systemu plików.

Głównym zadaniem protokołu jest zapewnienie bezpiecznego dostępu do plików w scenariuszach wielowątkowych. W iOS i macOS wiele procesów i wątków może jednocześnie uzyskiwać dostęp do tego samego pliku przez NSFileCoordinator, a NSFilePresenter gwarantuje, że każdy uczestnik otrzymuje aktualny stan danych.

Protokół jest zawarty w Foundation od iOS 5.0 i macOS 10.7. Jest stosowany w aplikacjach pracujących z dokumentami, bazami danych i wszelkimi plikami, które mogą być zmieniane jednocześnie z różnych źródeł — na przykład podczas synchronizacji przez iCloud lub wspólnego edytowania.

Gdzie stosuje się NSFilePresenter

Aplikacje zorientowane na dokumenty — główny obszar zastosowania NSFilePresenter. Aplikacje pracujące z UIDocument lub NSDocument automatycznie rejestrują się jako prezenterzy przez NSFileCoordinator. Pozwala to poprawnie obsługiwać konflikty podczas edytowania jednego pliku z wielu okien lub urządzeń.

Synchronizacja iCloud — drugi kluczowy scenariusz. Gdy plik zmienia się na jednym urządzeniu, iCloud synchronizuje go na wszystkich podłączonych urządzeniach. NSFilePresenter powiadamia aplikację o tych zmianach, umożliwiając terminową aktualizację interfejsu.

Edytory wielowątkowe — trzeci scenariusz. W aplikacjach, gdzie kolejki tła ładują i zapisują dane jednocześnie z pracą użytkownika, NSFilePresenter zapobiega stanom wyścigu przy zapisie i odczycie plików.

Jak działa NSFilePresenter?

Mechanizm działania NSFilePresenter opiera się na modelu delegowania: obiekt implementuje metody protokołu, rejestruje się przez NSFileCoordinator i otrzymuje wywołania przy każdej zmianie śledzonego pliku. System sam określa, kiedy nastąpiła zmiana i które metody należy wywołać.

Proces rozpoczyna się od utworzenia przez obiekt instancji NSFileCoordinator i wywołania metody koordynatora z przekazaniem URL pliku. Koordynator sprawdza, czy dla tego URL zarejestrowani są jacyś prezenterzy. Jeśli tak, blokuje dostęp do odczytu lub zapisu i powiadamia prezenterów o nadchodzącej zmianie przez metody protokołu.

Po zakończeniu operacji koordynator zdejmuje blokadę i wywołuje końcowe powiadomienia. Ważne, że prezenter nie zarządza przepływem wykonania — tylko reaguje na zdarzenia. Za koordynację w pełni odpowiada NSFileCoordinator.

Cykl życia powiadomienia

Faza przygotowania — przed wykonaniem operacji koordynator wywołuje metodę accommodatePresentedItemDeletion lub accommodatePresentedSubitemDeletion. Prezenter może obsłużyć sytuację lub anulować operację, zwracając błąd. Ta faza pozwala aplikacji poprawnie zakończyć pracę z plikiem przed jego zmianą.

Faza powiadomienia — po zakończeniu operacji koordynator wywołuje presentedItemDidChange lub presentedSubitemDidChange. Prezenter otrzymuje sygnał, że plik się zmienił, i może ponownie odczytać jego zawartość. Dla przeniesienia pliku wywoływana jest presentedItemDidMoveToURL z nową lokalizacją.

Faza zakończenia — koordynator zdejmuje wszystkie blokady i zwalnia zasoby. Prezenter może kontynuować pracę ze zaktualizowanymi danymi. Wszystkie trzy fazy są wykonywane synchronicznie w jednym wątku, dlatego metody protokołu muszą działać szybko, bez długotrwałych operacji wejścia-wyjścia.

Główne metody protokołu

Protokół NSFilePresenter zawiera kilka obowiązkowych i opcjonalnych metod. Jedyną obowiązkową właściwością jest presentedItemURL, zwracająca URL śledzonego pliku lub katalogu. Bez tej właściwości obiekt nie może być zarejestrowany jako prezenter.

Metody obowiązkowe

presentedItemURL — właściwość typu URL?, która musi zwracać ścieżkę do śledzonego pliku. Jeśli obiekt śledzi wiele plików, właściwość zwraca URL głównego elementu. Dla katalogów zwracany jest URL samego katalogu.

presentedItemDidChange — wywoływana po zmianie zawartości śledzonego pliku. W tej metodzie prezenter aktualizuje swój stan wewnętrzny i przeładowuje dane. Ta metoda nie otrzymuje informacji o tym, co dokładnie się zmieniło — tylko fakt zmiany.

Metody opcjonalne

accommodatePresentedItemDeletion — wywoływana przed usunięciem pliku. Prezenter może zapisać bieżący stan, zamknąć deskryptory plików lub anulować operację, zwracając NSError. Jeśli metoda zwróci błąd, operacja usunięcia nie zostanie wykonana.

presentedItemDidMoveToURL — wywoływana po przeniesieniu lub zmianie nazwy pliku. Metoda otrzymuje nowy URL, a prezenter musi zaktualizować referencję do pliku. Bez implementacji tej metody prezenter będzie nadal wskazywał starą, nieistniejącą ścieżkę.

NSFilePresenter i NSFileCoordinator

NSFileCoordinator i NSFilePresenter — nierozłączna para. NSFileCoordinator zarządza dostępem do plików i wywołuje metody prezentera. Prezenter nie pracuje bezpośrednio z systemem plików — wszystkie operacje przechodzą przez koordynatora, który gwarantuje atomowość zmian.

Koordynator rejestruje prezentera przez metodę addFilePresenter klasy NSFileCoordinator. Po dodaniu prezenter zaczyna otrzymywać powiadomienia. Usunięcie następuje przez removeFilePresenter. System przechowuje słabą referencję do prezentera, dlatego obiekt musi być żywy przez cały okres śledzenia.

Według Apple WWDC 2022, NSFileCoordinator używa mechanizmu koordynacji na poziomie jądra, co zapewnia minimalne opóźnienie przy blokadach. W najnowszych wersjach iOS koordynator jest zoptymalizowany do pracy z Sandbox i rozszerzeniami aplikacji.

Zasady koordynacji

Intention — każda operacja odczytu lub zapisu musi być owinięta w blok koordynacji: odczyt przez coordinateReadingItemAtURL, zapis przez coordinateWritingItemAtURL. Koordynator automatycznie blokuje plik dla innych uczestników na czas wykonania bloku.

Batch coordination — dla operacji na wielu plikach stosuje się koordynację wsadową. Koordynator atomowo blokuje wszystkie wskazane pliki, wykonuje operację i zdejmuje blokady. Jest to krytycznie ważne przy przenoszeniu lub kopiowaniu zestawów dokumentów.

Przykład implementacji NSFilePresenter

Stwórzmy klasę DocumentPresenter, która implementuje protokół NSFilePresenter i śledzi zmiany pliku dokumentu. Klasa zawiera referencję do pliku, dane wewnętrzne i flagę aktualności.

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) {
        // Przetwarzanie danych dokumentu
    }
}

Klasa implementuje presentedItemDidChange do przeładowania danych przy zmianie pliku oraz accommodatePresentedItemDeletion do zapisania stanu przed usunięciem. Kolejka operacyjna gwarantuje, że wszystkie powiadomienia są przetwarzane sekwencyjnie.

Rejestracja prezentera odbywa się przez NSFileCoordinator.addFilePresenter przy otwieraniu dokumentu. Ważne jest przekazanie koordynatorowi poprawnych opcji odczytu — withoutChanges dla operacji bez modyfikacji lub immediatelyAvailable dla scenariuszy z natychmiastowym dostępem.

Typowe błędy przy pracy

Pierwszym częstym błędem jest brak implementacji presentedItemOperationQueue. Jeśli nie określisz kolejki, powiadomienia mogą przychodzić w dowolnym wątku, powodując wyścig danych. Zawsze używaj sekwencyjnej OperationQueue do obsługi powiadomień.

Drugim błędem jest blokowanie w metodach prezentera. Metody protokołu są wywoływane synchronicznie z koordynatora. Jeśli prezenter wykonuje długotrwałą operację (zapis do bazy danych, żądanie sieciowe), blokuje koordynatora dla wszystkich pozostałych uczestników. Przenoś ciężkie operacje do kolejek tła.

Trzecim błędem jest ignorowanie accommodatePresentedItemDeletion. Jeśli prezenter nie implementuje tej metody i nie zwraca błędu, plik może zostać usunięty bez zapisania bieżącego stanu. Zawsze zapisuj dane w tej metodzie, jeśli nie zostały jeszcze zapisane na dysk.

Czwartym błędem jest koordynacja cykliczna. Gdy prezenter wewnątrz metody powiadomienia ponownie wywołuje koordynatora dla tego samego pliku, powstaje deadlock. Sprawdzaj flagę isCoordinatedOperation przed uruchomieniem koordynacji wewnątrz handlera.

BłądKonsekwencjaRozwiązanie
Brak kolejki operacjiWyścig danych w wielowątkowościOkreślić OperationQueue
Blokowanie w metodachZawieszenie koordynatoraPrzenieść do wątku tła
Ignorowanie deletionUtrata danych przy usunięciuZaimplementować zapis
Koordynacja cyklicznaDeadlock aplikacjiFlaga isCoordinatedOperation

Często zadawane pytania

Po co potrzebny jest NSFilePresenter, skoro istnieje NSFileHandle?

NSFileHandle — to niskopoziomowy interfejs do odczytu i zapisu danych, który nie zapewnia mechanizmów powiadamiania o zmianach z innych procesów. NSFilePresenter działa na poziomie koordynacji: otrzymuje zdarzenia od systemu przy każdej zmianie pliku, niezależnie od źródła — inny wątek, proces lub iCloud.

Czy obowiązkowe jest używanie NSFileCoordinator z NSFilePresenter?

Tak. NSFilePresenter nie ma sensu bez NSFileCoordinator. Prezenter tylko określa metody obsługi, a koordynator zarządza blokadami i wywołuje te metody. Jeśli używasz NSFilePresenter bez koordynatora, powiadomienia nie będą dostarczane.

Czy jeden obiekt może być prezenterem dla wielu plików?

Może, ale z ograniczeniami. Właściwość presentedItemURL zwraca tylko jeden URL, dlatego do śledzenia wielu plików używa się protokołu NSFilePresenter z dodatkowymi metodami dla subelementów. Alternatywą jest utworzenie osobnej instancji prezentera dla każdego pliku.

Jak NSFilePresenter działa z Sandbox w iOS?

NSFilePresenter jest w pełni kompatybilny z piaskownicą iOS. Aplikacja może śledzić pliki tylko wewnątrz swojego kontenera. Do dostępu do plików innych aplikacji używa się App Groups lub Security-Scoped Bookmark. Koordynator działa w ramach uprawnień piaskownicy.

Co zrobić, gdy presentedItemDidChange jest wywoływana zbyt często?

Użyj debouce'a lub throttla wewnątrz metody presentedItemDidChange. Utwórz timer z opóźnieniem 0,3-0,5 sekundy i resetuj go przy każdym nowym wywołaniu. Po stabilizacji wykonaj przeładowanie danych. Zapobiega to wielokrotnemu przetwarzaniu jednego pakietu zmian.

Podsumowanie

  • NSFilePresenter — protokół Foundation do otrzymywania powiadomień o zmianach plików w iOS i macOS, działający wyłącznie w parze z NSFileCoordinator.
  • Obowiązkowa właściwość presentedItemURL — bez niej obiekt nie może być zarejestrowany jako prezenter i nie będzie otrzymywać powiadomień.
  • Główna metoda presentedItemDidChange wywoływana po każdej zmianie zawartości pliku — używaj jej do przeładowania danych.
  • accommodatePresentedItemDeletion pozwala poprawnie obsłużyć usunięcie pliku i zapisać bieżący stan aplikacji.
  • NSFileCoordinator zarządza blokadami i gwarantuje atomowość operacji — bez koordynatora prezenter jest bezużyteczny.
  • Typowe błędy obejmują brak kolejki operacji, blokowanie w metodach i koordynację cykliczną — ważne jest, aby ich unikać poprzez projektowanie.
  • Debounce presentedItemDidChange przy częstych wywołaniach — używaj timera do grupowania zmian przed przeładowaniem.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również