我是swift的新手,我看到了一些方法,如:
andThen
我想知道什么时候使用@objc?我读了一些文档,但他们说当你希望它在Objective-C中可以调用时,你应该添加@objc标志
但是,这是swift中的私有函数,@ obj做了什么?
答案 0 :(得分:45)
私人意味着它只在Swift中可见。 所以使用@objc在Objective-C中可见。 如果你有一个func来选择swift中的私有函数,那就是必需的。
@objc属性使您的Swift API在Objective-C和Objective-C运行时可用。
答案 1 :(得分:41)
另一个迟到的答案,但这个问题的现有答案都没有真正回答OP的问题,即:为什么你需要在@objc
课上使用private
成员,如果@objc
与Objective-C进行交互,并且相关成员是私有的,这意味着即使您的项目中有Objective-C代码,它也不应该看到会员呢?
原因在于,由于许多框架都是用Objective-C编写的,因此有时需要Objective-C功能才能与某些API进行交互。
例如,假设我想通过DistributedNotificationCenter
注册通知:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
为此,我们需要能够获得somethingHappened
方法的选择器。但是,选择器是Objective-C概念,因此如果Objective-C看不到该方法,则它没有选择器。因此,即使该方法是私有的并且不应该被任意外部代码调用,它也需要@objc
,以便用Objective-C编写的DistributedNotification
代码能够通过选择器调用它。
需要@objc
的另一个常见情况是支持键值编码(KVC),特别是在macOS上,其中KVC和KVO用于实现Cocoa绑定。与Cocoa中的许多其他系统一样,KVC在Objective-C中实现,其效果是要求将符合KVC的属性暴露给Objective-C运行时。有时,符合KVC标准的属性是私有的。一个例子是当你有一个影响其他属性的属性时:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
在这种情况下,我们的实际存储属性是私有的,但我们做向外部代码公开的依赖属性需要在更新私有属性时发送其通知。通过将私有属性标记为@objc
,我们可以通过设置KVC依赖关系来轻松实现这一点 - 否则,我们必须编写代码以手动在私有属性中发送通知{{1} 1}}和willSet
处理程序。此外,通知KVC系统didSet
依赖于dependentProperty
的静态属性需要暴露给Objective-C,以便KVC系统找到它并调用它,但它是&#39;与我们代码的客户无关。
此外,macOS应用程序中的视图控制器使用Cocoa Bindings作为实现细节更新其视图中的控件可能会使某些私有属性符合KVC,以便将这些控件绑定到它们。
如您所见,有时可能需要向Objective-C公开方法或属性才能与框架进行交互,而无需向代码的客户端显示。
答案 2 :(得分:22)
@objc / 动态
这是为了兼容性:将Swift文件/代码导入基于Objective-C的项目。
如果您希望Objective-C代码或类访问您的属性/方法,请使用它。
大多数情况下,当你对Swift类的Objective-C基类进行子类化时会发生这种情况。
必须使用 @objc 属性标记Swift类或协议 可在Objective-C中访问和使用。这个属性告诉了 编译器可以访问这段Swift代码 Objective-C的。如果你的Swift类是Objective-C的后代 class,编译器自动为你添加@objc属性。
这里有关于@objc
。
Language Interoperability Compatibility
已更新的链接:看起来这些链接已由apple更新。
答案 3 :(得分:9)
@objc是一个类属性,所以你使用
@objc public class MyClass
它将类方法公开给Objective C类,所以只有当你的类包含公共函数时才会使用它
答案 4 :(得分:7)
一个迟到的答案,但是这个@objc
行为在Swift 4(在Xcode 9中出现,10天前通常发布)中略有变化。
在Swift 4中,删除了@objc
的一些推理案例。这仅仅意味着在一些其他情况下,在Swift编译器推断出@objc
标头之前,它在Swift 4中没有被推断。
阅读有关this change
的Swift演进提案正如已经提到的,通常@objc
是将某些方法暴露给Objective-C运行时,这是Swift与语言互操作的一部分。
答案 5 :(得分:0)
默认情况下,Swift
不支持Objective-C
的互操作性,以避免减少代码库。例如,当您使用Swift
语言编写框架时,并且想要使用Objective-C
代码中的框架时,此功能将非常有用。
要使用Objective-C中的Swift功能:
NSObject
扩展马克·斯威夫特:
a。 @objcMembers
课程-公开所有 public
字段和方法
b。 @objc
课程-公开public init()
。
@objc public
字段和方法-有选择地公开它们
Swift的方法将在下一个命名中可用:
<swiftName>With<firstArgument>:<secondArgument>:
例如:
public func printHelloWorld(arg1: String, arg2:String)
//is reached through:
[someObject printHelloWorldWithArg1: arg2:];