Outra resposta tardia, mas nenhuma das respostas existentes nesta pergunta realmente responde à pergunta do OP, que é: por que diabos você precisaria usar @objc
em um private
membro da classe, se @objc
existe para interação com Objective-C e o membro em questão é privado, o que significa que mesmo se você tiver o código Objective-C em seu projeto, ele não deverá ser capaz de ver o membro de qualquer maneira?
A razão é que, como muitos dos frameworks são escritos em Objective-C, às vezes os recursos do Objective-C são necessários para interagir com certas APIs.
Por exemplo, suponha que eu queira me registrar para receber uma notificação por meio de DistributedNotificationCenter
:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
Para que isso funcione, precisamos ser capazes de obter o seletor para o somethingHappened
método. No entanto, os seletores são um conceito do Objective-C, portanto, se o método não for visível para o Objective-C, ele não terá um seletor. Portanto, mesmo que o método seja privado e não deva ser chamado por um código externo arbitrário, ele precisará de um @objc
in para que o DistributedNotification
código, que está escrito em Objective-C, seja capaz de chamá-lo por meio de seu seletor.
Outro caso comum em que @objc
é necessário é oferecer suporte a Key-Value Coding (KVC), especialmente no macOS, onde KVC e KVO são usados para implementar vinculações Cocoa. KVC é, como muitos outros sistemas em Cocoa, implementado em Objective-C, o que tem o efeito de exigir que as propriedades compatíveis com KVC sejam expostas ao tempo de execução Objective-C. Às vezes, faz sentido que as propriedades compatíveis com KVC sejam privadas. Um exemplo é quando você tem uma propriedade que afeta outras propriedades:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
Neste caso, a nossa propriedade real armazenado é privado, mas a propriedade dependente, o que nós não expor para o código fora, precisa enviar suas notificações quando a propriedade privada é atualizado. Ao marcar a propriedade privada como @objc
, podemos fazer isso facilmente configurando uma dependência KVC - caso contrário, teríamos que escrever código para enviar manualmente as notificações na propriedade privada willSet
e nos didSet
manipuladores. Além disso, a propriedade estática que informa o sistema KVC de que dependentProperty
depende originalProperty
precisa ser exposta ao Objective-C para que o sistema KVC o encontre e o chame, mas não é relevante para os clientes do nosso código.
Além disso, um controlador de visualização em um aplicativo macOS que atualiza os controles em sua visualização usando Cocoa Bindings como um detalhe de implementação pode tornar certas propriedades privadas compatíveis com KVC para vincular esses controles a elas.
Como você pode ver, há momentos em que um método ou propriedade pode precisar ser exposto ao Objective-C para interagir com os frameworks, sem necessariamente precisar estar visível para os clientes do seu código.