Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use @objc in Swift?

In Swift, I see some methods like:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

I was wondering, when to use @objc? I read some documents, but they are saying when you want it to be callable in Objective-C, you should add @objc flag

However, this is a private function in Swift, what does the @obj do?

like image 535
Wingzero Avatar asked Jun 12 '15 04:06

Wingzero


People also ask

What is @objc dynamic in Swift?

Swift generates code that is only readable to other Swift code. But if we need to interact with the Objective-C runtime, we need to instruct Swift what to do. Here comes @objc to make swift code available to Objective-C.

Is OBJC faster than Swift?

Performance. The official Apple website claims that Swift is 2.6 times faster than Objective-C. However some studies indicate that the difference is not as dramatic. Swift and Objective-C are both statistically typed languages that use the same iOS SDK and the high-quality Low Level Virtual Machine compiler.

How do I use Objective-C and Swift together?

To import a set of Objective-C files into Swift code within the same app target, you rely on an Objective-C bridging header file to expose those files to Swift. Xcode offers to create this header when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.


4 Answers

private mean it visible only in Swift. so use @objc to visible in Objective-C. If you have a func to selector a private func in swift, it is required.

The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime.

See: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

like image 138
Reming Hsu Avatar answered Oct 21 '22 08:10

Reming Hsu


Another late answer, but none of the existing answers on this question really answer the OP's question, which is: why the heck would you need to use @objc on a private class member, if @objc is there for interaction with Objective-C, and the member in question is private, meaning that even if you have Objective-C code in your project, it shouldn't be able to see the member anyway?

The reason is that, because many of the frameworks are written in Objective-C, sometimes Objective-C features are needed to interact with certain APIs.

For example, suppose I want to register for a notification via DistributedNotificationCenter:

DistributedNotificationCenter.default.addObserver(self,
                                                  selector: #selector(somethingHappened(_:)),
                                                  name: someNotification,
                                                  object: nil)

For this to work, we need to be able to get the selector for the somethingHappened method. However, selectors are an Objective-C concept, so if the method is not visible to Objective-C, it does not have a selector. Therefore, even if the method is private and should not be called by arbitrary outside code, it will need an @objc in order for the DistributedNotification code, which is written in Objective-C, to be able to call it via its selector.

Another common case where @objc is needed is to support Key-Value Coding (KVC), especially on macOS, where KVC and KVO are used to implement Cocoa Bindings. KVC is, like many other systems in Cocoa, implemented in Objective-C, which has the effect of requiring KVC-compliant properties to be exposed to the Objective-C runtime. Sometimes, it makes sense for KVC-compliant properties to be private. One example is when you have a property that affects other properties:

@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 this case, our actual stored property is private, but the dependent property, which we do expose to outside code, needs to send its notifications when the private property is updated. By marking the private property as @objc, we can easily do that by setting up a KVC dependency—otherwise, we'd have to write code to manually send the notifications in the private property's willSet and didSet handlers. In addition, the static property that informs the KVC system that dependentProperty is dependent on originalProperty needs to be exposed to Objective-C so that the KVC system and find it and call it, but it's not relevant to clients of our code.

Also, a view controller in a macOS app that updates controls in its view using Cocoa Bindings as an implementation detail may make certain private properties KVC-compliant in order to bind those controls to them.

So as you see, there are times when a method or property may need to be exposed to Objective-C in order to interact with the frameworks, without necessarily needing to be visible to clients of your code.

like image 25
Charles Srstka Avatar answered Oct 21 '22 10:10

Charles Srstka


@objc / dynamic

It's for compatibility: Once you import your Swift file/code into Objective-C based project.

And use that if you want your property/method to be accessed by Objective-C code or class.

Most of the time it happens when you are sub classing a Swift class of Objective-C base class.

A Swift class or protocol must be marked with the @objc attribute to be accessible and usable in Objective-C. This attribute tells the compiler that this piece of Swift code can be accessed from Objective-C. If your Swift class is a descendant of an Objective-C class, the compiler automatically adds the @objc attribute for you.

Here apple documentation that says about @objc.

Using Swift from Objective-C

Language Interoperability Compatibility

Links Updated:
Looks like the links has been updated by apple.

like image 25
0yeoj Avatar answered Oct 21 '22 09:10

0yeoj


@objc is a class attribute, so you use

@objc public class MyClass

It exposes the class' methods to Objective C classes, so you'll only use it if your class contains public functions

like image 12
Fraser Avatar answered Oct 21 '22 09:10

Fraser