NSFilePresenter — είναι ένα πρωτόκολλο Foundation που επιτρέπει σε ένα αντικείμενο να λαμβάνει ειδοποιήσεις για αλλαγές αρχείων και καταλόγων στο σύστημα αρχείων iOS και macOS. Η κλάση υλοποιεί τις μεθόδους του πρωτοκόλλου και καταχωρείται μέσω του NSFileCoordinator, μετά το οποίο το σύστημα καλεί αυτόματα αυτές τις μεθόδους σε κάθε λειτουργία με το παρακολουθούμενο αρχείο. Σύμφωνα με το Apple Developer Documentation (2025), το NSFilePresenter χρησιμοποιείται σε εφαρμογές με πολυνηματική πρόσβαση σε έγγραφα για την αποφυγή συγκρούσεων εγγραφής. Το πρωτόκολλο χρησιμοποιείται υποχρεωτικά σε συνδυασμό με το NSFileCoordinator — μόνο έτσι εξασφαλίζεται ασφαλής συντονισμός πρόσβασης.
Κύρια σημεία
NSFilePresenter — είναι ένα πρωτόκολλο Foundation σχεδιασμένο για την παρακολούθηση αλλαγών αρχείων και καταλόγων στα λειτουργικά συστήματα Apple. Το πρωτόκολλο ορίζει ένα σύνολο μεθόδων που το αντικείμενο-παρατηρητής υλοποιεί για να λαμβάνει ειδοποιήσεις για γεγονότα του συστήματος αρχείων.
Η κύρια αποστολή του πρωτοκόλλου είναι η εξασφάλιση ασφαλούς πρόσβασης σε αρχεία σε πολυνηματικά σενάρια. Σε iOS και macOS, πολλαπλές διεργασίες και νήματα μπορούν ταυτόχρονα να έχουν πρόσβαση στο ίδιο αρχείο μέσω του NSFileCoordinator, και το NSFilePresenter εγγυάται ότι κάθε συμμετέχων λαμβάνει την ενημερωμένη κατάσταση δεδομένων.
Το πρωτόκολλο συμπεριλαμβάνεται στο Foundation από το iOS 5.0 και macOS 10.7. Χρησιμοποιείται σε εφαρμογές που εργάζονται με έγγραφα, βάσεις δεδομένων και οποιαδήποτε αρχεία που μπορεί να αλλάζουν ταυτόχρονα από διαφορετικές πηγές — για παράδειγμα, κατά το συγχρονισμό μέσω iCloud ή τη συνεργατική επεξεργασία.
Εφαρμογές προσανατολισμένες σε έγγραφα — ο κύριος τομέας χρήσης του NSFilePresenter. Οι εφαρμογές που εργάζονται με UIDocument ή NSDocument καταχωρούνται αυτόματα ως παρουσιαστές μέσω του NSFileCoordinator. Αυτό επιτρέπει τον σωστό χειρισμό συγκρούσεων κατά την επεξεργασία του ίδιου αρχείου από πολλαπλά παράθυρα ή συσκευές.
Συγχρονισμός iCloud — το δεύτερο βασικό σενάριο. Όταν ένα αρχείο αλλάζει σε μια συσκευή, το iCloud το συγχρονίζει σε όλες τις συνδεδεμένες συσκευές. Το 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, και ο παρουσιαστής πρέπει να ενημερώσει την αναφορά στο αρχείο. Χωρίς υλοποίηση αυτής της μεθόδου, ο παρουσιαστής θα συνεχίσει να δείχνει στην παλιά, ανύπαρκτη διαδρομή.
NSFileCoordinator και NSFilePresenter — αχώριστο ζευγάρι. Το NSFileCoordinator διαχειρίζεται την πρόσβαση σε αρχεία και καλεί τις μεθόδους του παρουσιαστή. Ο παρουσιαστής δεν εργάζεται άμεσα με το σύστημα αρχείων — όλες οι λειτουργίες περνούν μέσω του συντονιστή, ο οποίος εγγυάται την ατομικότητα των αλλαγών.
Ο συντονιστής καταχωρεί τον παρουσιαστή μέσω της μεθόδου addFilePresenter της κλάσης NSFileCoordinator. Μετά την προσθήκη, ο παρουσιαστής αρχίζει να λαμβάνει ειδοποιήσεις. Η αφαίρεση γίνεται μέσω της removeFilePresenter. Το σύστημα διατηρεί αδύναμη αναφορά στον παρουσιαστή, επομένως το αντικείμενο πρέπει να παραμένει ζωντανό καθ' όλη τη διάρκεια παρακολούθησης.
Σύμφωνα με το Apple WWDC 2022, το NSFileCoordinator χρησιμοποιεί μηχανισμό συντονισμού σε επίπεδο πυρήνα, εξασφαλίζοντας ελάχιστη καθυστέρηση στα μπλοκαρίσματα. Στις νεότερες εκδόσεις iOS, ο συντονιστής είναι βελτιστοποιημένος για εργασία με Sandbox και επεκτάσεις εφαρμογών.
Intention — κάθε λειτουργία ανάγνωσης ή εγγραφής πρέπει να είναι τυλιγμένη σε μπλοκ συντονισμού: ανάγνωση μέσω coordinateReadingItemAtURL, εγγραφή μέσω coordinateWritingItemAtURL. Ο συντονιστής μπλοκάρει αυτόματα το αρχείο για άλλους συμμετέχοντες κατά τη διάρκεια εκτέλεσης του μπλοκ.
Συντονισμός παρτίδας — για λειτουργίες με πολλαπλά αρχεία χρησιμοποιείται συντονισμός παρτίδας. Ο συντονιστής μπλοκάρει ατομικά όλα τα καθορισμένα αρχεία, εκτελεί τη λειτουργία και αφαιρεί τα μπλοκαρίσματα. Αυτό είναι κρίσιμο κατά τη μετακίνηση ή αντιγραφή συνόλων εγγράφων.
Ας δημιουργήσουμε την κλάση DocumentPresenter που υλοποιεί το πρωτόκολλο NSFilePresenter και παρακολουθεί τις αλλαγές του αρχείου εγγράφου. Η κλάση περιέχει αναφορά στο αρχείο, εσωτερικά δεδομένα και σημαία επικαιρότητας.
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. Εάν ο παρουσιαστής δεν υλοποιεί αυτή τη μέθοδο και δεν επιστρέφει σφάλμα, το αρχείο μπορεί να διαγραφεί χωρίς αποθήκευση της τρέχουσας κατάστασης. Αποθηκεύετε πάντα δεδομένα σε αυτή τη μέθοδο εάν δεν έχουν ακόμα εγγραφεί στο δίσκο.
Το τέταρτο σφάλμα — κυκλικός συντονισμός. Όταν ο παρουσιαστής μέσα στη μέθοδο ειδοποίησης καλεί ξανά τον συντονιστή για το ίδιο αρχείο, προκύπτει deadlock. Ελέγξτε τη σημαία isCoordinatedOperation πριν ξεκινήσετε συντονισμό μέσα στον χειριστή.
| Σφάλμα | Συνέπεια | Λύση |
|---|---|---|
| Χωρίς ουρά λειτουργιών | Ανταγωνισμός δεδομένων σε πολυνηματικό | Καθορισμός OperationQueue |
| Μπλοκάρισμα σε μεθόδους | Πάγωμα συντονιστή | Μεταφορά σε νήμα παρασκηνίου |
| Αγνόηση deletion | Απώλεια δεδομένων κατά διαγραφή | Υλοποίηση αποθήκευσης |
| Κυκλικός συντονισμός | Deadlock εφαρμογής | Σημαία isCoordinatedOperation |
Συχνές Ερωτήσεις
NSFileHandle — είναι μια διεπαφή χαμηλού επιπέδου για ανάγνωση και εγγραφή δεδομένων που δεν παρέχει μηχανισμούς ειδοποίησης για αλλαγές από άλλες διεργασίες. Το NSFilePresenter λειτουργεί σε επίπεδο συντονισμού: λαμβάνει συμβάντα από το σύστημα σε κάθε αλλαγή αρχείου, ανεξάρτητα από την πηγή — άλλο νήμα, διεργασία ή iCloud.
Ναι. Το NSFilePresenter δεν έχει νόημα χωρίς το NSFileCoordinator. Ο παρουσιαστής ορίζει μόνο τις μεθόδους χειρισμού, ενώ ο συντονιστής διαχειρίζεται τα μπλοκαρίσματα και καλεί αυτές τις μεθόδους. Εάν χρησιμοποιείτε το NSFilePresenter χωρίς συντονιστή, οι ειδοποιήσεις δεν θα παραδίδονται.
Μπορεί, αλλά με περιορισμούς. Η ιδιότητα presentedItemURL επιστρέφει μόνο ένα URL, επομένως για παρακολούθηση πολλαπλών αρχείων χρησιμοποιείται το πρωτόκολλο NSFilePresenter με πρόσθετες μεθόδους για υποστοιχεία. Εναλλακτική — δημιουργία ξεχωριστού στιγμιότυπου παρουσιαστή για κάθε αρχείο.
NSFilePresenter είναι πλήρως συμβατό με το sandbox του iOS. Η εφαρμογή μπορεί να παρακολουθεί μόνο αρχεία εντός του δικού της container. Για πρόσβαση σε αρχεία άλλων εφαρμογών χρησιμοποιούνται App Groups ή Security-Scoped Bookmark. Ο συντονιστής λειτουργεί εντός των δικαιωμάτων του sandbox.
Χρησιμοποιήστε debounce ή throttle μέσα στη μέθοδο presentedItemDidChange. Δημιουργήστε ένα χρονόμετρο με καθυστέρηση 0,3-0,5 δευτερολέπτων και επαναφέρετέ το σε κάθε νέα κλήση. Μετά τη σταθεροποίηση, εκτελέστε επαναφόρτωση δεδομένων. Αυτό αποτρέπει την πολλαπλή επεξεργασία του ίδιου πακέτου αλλαγών.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης