Guides and Sample Code


Using Swift with Cocoa and Objective-C (Swift 4.1)

On This Page

Writing Swift Classes and Protocols with Objective-C Behavior

Interoperability lets you write Swift code that incorporates Objective-C behavior. You can subclass Objective-C classes, declare and adopt Objective-C protocols, and take advantage of other Objective-C functionality when writing Swift code. This means that you can create classes and protocols based on familiar, established behavior in Objective-C and enhance them with Swift’s modern and powerful language features.

Inheriting from Objective-C Classes

In Swift, you can define subclasses of Objective-C classes. To create a Swift class that inherits from an Objective-C class, add a colon (:) after the name of the Swift class, followed by the name of the Objective-C class.

  1. import UIKit
  2. class MySwiftViewController: UIViewController {
  3. // define the class
  4. }

A Swift subclass gets all the functionality offered by the superclass in Objective-C.

To provide your own implementations of the superclass’s methods, use the override modifier. The compiler automatically infers the name of the overridden Objective-C method that matches the Swift method name. You can use the @objc(name) attribute to explicitly specify the corresponding Objective-C symbol.

When a Swift class introduces many new methods or properties that require behavior from the Objective-C runtime, use the @objcMembers attribute in the declaration of that class. Applying the @objcMembers attribute to a class implicitly adds the @objc attribute to all of its Objective-C compatible members. Because applying the @objc attribute can increase the compiled size of an app and adversely affect performance, only apply the @objcMembers attribute on declarations when each member needs to have the @objc attribute applied.


The NSCoding protocol requires that conforming types implement the required initializer init(coder:) and the required method encode(with:). Classes that adopt NSCoding directly must implement this method. Subclasses of classes that adopt NSCoding that have one or more custom initializers or any properties without initial values must also implement this method.

For objects that are loaded from Storyboards or archived to disk using the NSUserDefaults or NSKeyedArchiver classes, you must provide a full implementation of this initializer. However, you might not need to implement an initializer for types that are expected to or cannot be instantiated in this way.

Adopting Protocols

Objective-C protocols are imported as Swift protocols, which can be adopted by a class in a comma-separated list following the name of a class’s superclass, if any.

  1. class MySwiftViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  2. // define the class
  3. }

To declare a type that conforms to a single protocol in Swift code, use the protocol name directly as its type (as compared to id<SomeProtocol> in Objective-C). To declare a type that conforms to multiple protocols in Swift code, use a protocol composition, which takes the form SomeProtocol & AnotherProtocol (as compared to id<SomeProtocol, AnotherProtocol> in Objective-C).

  1. var textFieldDelegate: UITextFieldDelegate
  2. var tableViewController: UITableViewDataSource & UITableViewDelegate

When a Swift initializer, property, subscript, or method is used to satisfy a requirement of an Objective-C protocol, the compiler automatically infers the name to match the requirement, similar to what is done for overridden methods. You can use the @objc(name) attribute to explicitly specify the corresponding Objective-C symbol.

Writing Initializers and Deinitializers

The Swift compiler ensures that your initializers do not leave any properties in your class uninitialized to increase the safety and predictability of your code. Additionally, unlike Objective-C, in Swift there is no separate memory allocation method to invoke. You use native Swift initialization syntax even when you are working with Objective-C classes—Swift converts Objective-C initialization methods to Swift initializers. For more information about implementing your own initializers, see Initializers in The Swift Programming Language (Swift 4.1).

When you want to perform additional clean-up before your class is deallocated, you can implement a deninitializer instead of the dealloc method. Swift deinitializers are called automatically, just before instance deallocation happens. Swift automatically calls the superclass deinitializer after invoking your subclass’ deinitializer. When you are working with an Objective-C class or your Swift class inherits from an Objective-C class, Swift calls your class’s superclass dealloc method for you as well. For more information about implementing your own deinitializers, see Deinitializers in The Swift Programming Language (Swift 4.1).

Using Swift Class Names with Objective-C APIs

Swift classes are namespaced based on the module they are compiled in, even when used from Objective-C code. Unlike Objective-C, where all classes are part of a global namespace–and must not have the same name–Swift classes can be disambiguated based on the module they reside in. For example, the fully qualified name of a Swift class named DataManager in a framework named MyFramework is MyFramework.DataManager. A Swift app target is a module itself, so the fully qualified name of a Swift class named Observer in an app called MyGreatApp is MyGreatApp.Observer.

In order to preserve namespacing when a Swift class is used in Objective-C code, Swift classes are exposed to the Objective-C runtime with their fully qualified names. Therefore, when you work with APIs that operate on the string representation of a Swift class, you must include the fully qualified name of the class. For example, when you create a document–based Mac app, you provide the name of your NSDocument subclass in your app’s Info.plist file. In Swift, you must use the full name of your document subclass, including the module name derived from the name of your app or framework.

In the example below, the NSClassFromString(_:) function is used to retrieve a reference to a class from its string representation. In order to retrieve a Swift class, the fully qualified name, including the name of the app, is used.

  1. let myPersonClass: AnyClass? = NSClassFromString("MyGreatApp.Person")

Integrating with Interface Builder

The Swift compiler includes attributes that enable Interface Builder features for your Swift classes. As in Objective-C, you can use outlets, actions, and live rendering in Swift.

Working with Outlets and Actions

Outlets and actions allow you to connect your source code to user interface objects in Interface Builder. To use outlets and actions in Swift, insert @IBOutlet or @IBAction just before the property or method declaration. You use the same @IBOutlet attribute to declare an outlet collection—just specify an array for the type.

When you declare an outlet in Swift, you should make the type of the outlet an implicitly unwrapped optional. This way, you can let the storyboard connect the outlets at runtime, after initialization. When your class is initialized from a storyboard or xib file, you can assume that the outlet has been connected.

For example, the following Swift code declares a class with an outlet, an outlet collection, and an action:

  1. class MyViewController: UIViewController {
  2. @IBOutlet weak var button: UIButton!
  3. @IBOutlet var textFields: [UITextField]!
  4. @IBAction func tappedButton(_ sender: UIButton?) {
  5. print("button was tapped!")
  6. }
  7. }

Live Rendering

You can use two different attributes—@IBDesignable and @IBInspectable—to enable live, interactive custom view design in Interface Builder. When you create a custom view that inherits from the UIView class or the NSView class, you can add the @IBDesignable attribute just before the class declaration. After you add the custom view to Interface Builder (by setting the custom class of the view in the inspector pane), Interface Builder renders your view in the canvas.

You can also add the @IBInspectable attribute to properties with types compatible with user defined runtime attributes. After you add your custom view to Interface Builder, you can edit these properties in the inspector.

  1. @IBDesignable
  2. class MyCustomView: UIView {
  3. @IBInspectable var textColor: UIColor
  4. @IBInspectable var iconHeight: CGFloat
  5. // ...
  6. }

Specifying Property Attributes

In Objective-C, properties have a range of potential attributes that specify additional information about a property’s behavior. In Swift, you specify these property attributes in a different way.

Strong and Weak

Swift properties are strong by default. Use the weak keyword to indicate that a property has a weak reference to the object stored as its value. This keyword can be used only for properties that are optional class types. For more information, see Attributes.

Read/Write and Read-Only

In Swift, there are no readwrite and readonly attributes. When declaring a stored property, use let to make it read-only, and use var to make it read/write. When declaring a computed property, provide a getter only to make it read-only and provide both a getter and setter to make it read/write. For more information, see Properties in The Swift Programming Language (Swift 4.1).

Copy Semantics

In Swift, the Objective-C copy property attribute translates to @NSCopying. The type of the property must conform to the NSCopying protocol. For more information, see Attributes in The Swift Programming Language (Swift 4.1).

Implementing Core Data Managed Object Subclasses

Core Data provides the underlying storage and implementation of properties in subclasses of the NSManagedObject class. Core Data also provides the implementation of instance methods that you use to add and remove objects from to-many relationships. You use the @NSManaged attribute to inform the Swift compiler that Core Data provides the storage and implementation of a declaration at runtime.

Add the @NSManaged attribute to each property or method declaration in your managed object subclass that corresponds to an attribute or relationship in your Core Data model. For example, consider a Core Data entity called “Person” with a String attribute “name” and a to-many relationship “friends”:

image: ../Art/coredataeditor_2x.png

Choose “Create NSManagedObject Subclass…” from the “Editor” menu to generate corresponding Swift code for the NSManagedObject subclass, Person:

  1. // Person+CoreDataClass.swift
  2. import CoreData
  3. class Person: NSManagedObject {
  4. // Insert code here to add functionality to your managed object subclass
  5. }
  6. // Person+CoreDataProperties.swift
  7. extension Person {
  8. @NSManaged var name: String
  9. @NSManaged var friends: NSSet
  10. }

The name and friends properties are both declared with the @NSManaged attribute to indicate that Core Data provides their implementation and storage at runtime.

To configure a Swift subclass of NSManagedObject for use by a Core Data model entity, open the model entity inspector in Xcode, enter the class name into the Class field, and choose “Current Product Module” from the Module field drop-down list.

image: ../Art/coredatanamespace_2x.png

Declaring Protocols

In Swift, you can define protocols that Objective-C classes can conform to. To create a Swift protocol that can be adopted by an Objective-C class, mark the protocol declaration with the @objc attribute.

  1. import UIKit
  2. @objc protocol MyCustomProtocol {
  3. var people: [Person] { get }
  4. func tableView(_ tableView: UITableView, configure cell: UITableViewCell, forPerson person: Person)
  5. @objc optional func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forPerson person: Person)
  6. }

A protocol declares all initializers, properties, subscripts, and methods that an Objective-C class must implement in order to conform to the protocol. Any optional protocol requirements must be marked with the @objc attribute and have the optional modifier.

An Objective-C class can conform a protocol declared in Swift in the same way that it would an Objective-C protocol, by implementing the required methods.

  1. @interface MyCustomController: UIViewController <MyCustomProtocol>
  2. @property (nonatomic, strong) NSArray<Person *> *people;
  3. @end
  4. @implementation MyCustomController
  5. @synthesize people;
  6. - (void)tableView:(UITableView *)tableView
  7. configure:(UITableViewCell *)cell
  8. forPerson:(Person *)person
  9. {
  10. // Configure cell
  11. }
  12. @end