Un'altra risposta tardiva, ma nessuna delle risposte esistenti su questa domanda risponde davvero alla domanda dell'OP, che è: perché diamine dovresti usare @objc
su un private
membro della classe, se @objc
è lì per l'interazione con Objective-C e il membro in questione è privato, il che significa che anche se hai codice Objective-C nel tuo progetto, non dovrebbe comunque essere in grado di vedere il membro?
Il motivo è che, poiché molti dei framework sono scritti in Objective-C, a volte sono necessarie funzionalità Objective-C per interagire con determinate API.
Ad esempio, supponiamo che io voglia registrarmi per una notifica tramite DistributedNotificationCenter
:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
Affinché funzioni, dobbiamo essere in grado di ottenere il selettore per il somethingHappened
metodo. Tuttavia, i selettori sono un concetto Objective-C, quindi se il metodo non è visibile a Objective-C, non dispone di un selettore. Pertanto, anche se il metodo è privato e non deve essere chiamato da codice esterno arbitrario, avrà bisogno di una @objc
affinché il DistributedNotification
codice, che è scritto in Objective-C, possa chiamarlo tramite il suo selettore.
Un altro caso comune in cui @objc
è necessario è supportare KVC (Key-Value Coding), specialmente su macOS, dove KVC e KVO vengono utilizzati per implementare Cocoa Bindings. KVC è, come molti altri sistemi in Cocoa, implementato in Objective-C, che ha l'effetto di richiedere che le proprietà conformi a KVC siano esposte al runtime Objective-C. A volte, ha senso che le proprietà conformi a KVC siano private. Un esempio è quando hai una proprietà che influisce su altre proprietà:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
In questo caso, la nostra proprietà effettivo memorizzato è privata, ma la proprietà dipendente, che noi facciamo esponiamo al codice esterno, ha bisogno di inviare le sue notifiche quando la proprietà privata viene aggiornato. Contrassegnando la proprietà privata come @objc
, possiamo farlo facilmente impostando una dipendenza KVC, altrimenti dovremmo scrivere il codice per inviare manualmente le notifiche nella proprietà privata willSet
e nei didSet
gestori. Inoltre, la proprietà statica che informa il sistema KVC da cui dependentProperty
dipende originalProperty
deve essere esposta a Objective-C in modo che il sistema KVC lo trovi e lo chiami, ma non è rilevante per i client del nostro codice.
Inoltre, un controller di visualizzazione in un'app macOS che aggiorna i controlli nella sua vista utilizzando Cocoa Bindings come dettaglio di implementazione può rendere alcune proprietà private conformi a KVC per associare tali controlli a loro.
Quindi, come puoi vedere, ci sono momenti in cui un metodo o una proprietà potrebbe dover essere esposto a Objective-C per interagire con i framework, senza necessariamente dover essere visibile ai client del tuo codice.