Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Swift High Performance

You're reading from   Swift High Performance Leverage Swift and enhance your code to take your applications to the next level

Arrow left icon
Product type Paperback
Published in Nov 2015
Publisher Packt
ISBN-13 9781785282201
Length 212 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Kostiantyn Koval Kostiantyn Koval
Author Profile Icon Kostiantyn Koval
Kostiantyn Koval
Arrow right icon
View More author details
Toc

Table of Contents (10) Chapters Close

Preface 1. Exploring Swift's Power and Performance FREE CHAPTER 2. Making a Good Application Architecture in Swift 3. Testing and Identifying Slow Code with the Swift Toolkit 4. Improving Code Performance 5. Choosing the Correct Data Structure 6. Architecting Applications for High Performance 7. The Importance of Being Lazy 8. Discovering All the Underlying Swift Power Index

Swift interoperability

There are two main points that Apple thought of when introducing Swift:

  • The usage of the Cocoa framework and established Cocoa patterns
  • Easy to adopt and migrate

Apple understood that and took it very seriously while working on Swift. They made Swift work seamlessly with Objective-C and Cocoa. You can use all Objective-C code in Swift, and you can even use Swift in Objective-C.

It's very crucial to be able to use the Cocoa framework. All of the code that is written in Objective-C is available for use in Swift, both Apple frameworks and third-party libraries as well.

Using Objective-C in Swift

All the Cocoa frameworks written in Objective-C are available in Swift by default. You just need to import them and then use them. Swift doesn't have header files; instead, you need to use a module name. You can also include your own Swift frameworks in the same way:

import Foundation
import UIKit
import Alamofire // Custom framework

Setup

To include your own Objective-C source files, you need to do a small setup first. The process is a bit different for the application target and framework target. The main idea is the same—to import the Objective-C header files.

The application target

For the application target, you need to create a bridging header. A bridging header is a plain Objective-C header file in which you specify the Objective-C import statements.

Xcode will show a popup, offering to create, and set up a bridging header for you when you add the Objective-C file to a Swift project, or vice versa for the first time. This is the best and the most convenient way to add it.

The application target

If you decline the Xcode help, you can create a bridging header yourself anytime. To do that, you need to follow these steps:

  1. Add a new header file to the project.
  2. Go to Target | Build Settings.
  3. Search for Objective-C Bridging Header and specify the path to the bridging header file created in step 1.
    The application target

Once you set up bridging header, the next step is to add import statements to it:

Bridging.h

//
//  Use this file to import your target's public headers that you //  would like to expose to Swift.

#import "MyClass.h"

The framework target

For the framework target, you simply need to import the .h Objective-C header files to the framework's umbrella header. The Objective-C header files must be marked as public. The umbrella header is the header in which you specify your publicly available API. Usually, it looks like this—the ExampleFramework.h umbrella header:

#import <UIKit/UIKit.h>

//! Project version number for MySwiftKit.
FOUNDATION_EXPORT double MySwiftKitVersionNumber;

//! Project version string for MySwiftKit.
FOUNDATION_EXPORT const unsigned char MySwiftKitVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <MySwiftKit/PublicHeader.h>

#import <SimpleFramework/MyClass.h>

Calling Objective-C code

Once you are done with the setup, you can use all Objective-C APIs in Swift. You can create instances, call methods, inherit from Objective-C classes, conform to protocols, and do other things that you can do in Objective-C. In this example, we will use the Foundation classes, but the rules are the same for third-party code as well:

import UIKit
import Foundation

let date = NSDate()
date.timeIntervalSinceNow

UIColor.blackColor()
UIColor(red: 0.5, green: 1, blue: 1, alpha: 1)

class MyView: UIView {
    //custom implementation
}

Tip

Inherit from Objective-C classes only if you need it. This can have a negative impact on performance.

There is free bridging between Swift types and Objective-C Foundation types. Automatic bridging happens on assignment and when you pass it as an argument to a function:

let array = [1, 2, 3]

func takeArray(array: NSArray) { }

var objcArray: NSArray = array
takeArray(array)

Converting from Objective-C to a Swift type requires explicit type casting. There are two types of casting: downcasting and upcasting. Casting is usually an unsafe operation, which could fail, and that's why it returns an optional type:

//Upcasting or safe casting
let otherArray: [AnyObject] = objcArray as [AnyObject]

//Downcasting, unsafe casting
if let safeNums = objcArray as? [Int] {
  safeNums[0] + 10 //11
}

let string: NSString = "Hi"
let str: String = string as String

The String type has gone one step even further. You can invoke the Objective-C foundation methods on the Swift String type without any type casting:

var name: String = "Name"
name.stringByAppendingString(": Sara")

Swift made a small improvement to Objective-C code so that it looks more Swift-style. The biggest change is made to instance creation and the style of the initialization code. The init, the initWith, and other factory methods are transformed into Swift initializers:

//Objective-C

- (instancetype)initWithFrame:(CGRect)frame;
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha;

// Swift 
init(frame: CGRect)
init(white: CGFloat, alpha: CGFloat)

The other change is made to NS_ENUM and NS_OPTIONS. They become native Swift types: enum and RawOptionSetType.

As you can see, the API looks a bit different. Because Swift strives for cleanliness, it removes word duplications from the API nomenclature. The other method calls, properties, and names, are the same as they were in Objective-C, so it should be easy to find and understand them.

What is happening behind the scenes is that Swift is generating special interface files to interact with Objective-C. You can see these Swift interface files by holding down the command key and clicking on the type, NSDate and UIColor in our example.

Using Swift in Objective-C

It is also possible to use Swift in Objective-C. It makes Swift very easy to adapt to an existing project. You can start by adding one Swift file, and move more functionality to Swift over time.

The setup process is much easier than that for including Objective-C in Swift. All you need to do is import Swift's autogenerated header to Objective-C. The naming convention of the files for application targets is ProductModuleName + -Swift.h, and for frameworks, it is <ProductName/ProductModuleName + -Swift.h>.

Take a look at the following examples:

#import "SwiftApp-Swift.h"
#import <MySwiftKit/MySwiftKit-Swift.h>

You can inspect the content of that autogenerated file by holding down the command key and clicking on it. By default, Swift classes aren't exposed for use in Objective-C. There are two ways of making Swift classes available in Objective-C:

  • Mark the Swift class, protocol, or enumeration with the @objc attribute.

    You can mark classes, methods, protocols, and enumerations with the @objc attribute. The @objc attribute also accepts the alternative name that is used for Objective-C. When you expose a Swift class by marking it with the @objc attribute, it has to inherit from the Objective-C class, and the enumeration must have a raw Int value:

    @objc(KOKPerson) class Person: NSObject {
      @objc(isMan) func man() -> Bool {
        ...
      }
    }
    @objc enum Options: Int {
      case One
      case Two
    }

    Now, the KOKPerson class with the isMan method is available for use in Objective-C.

  • Inherit from an Objective-C class, NSObject for example:

    When you inherit from an Objective-C class, your Swift class automatically becomes available in Objective-C. You don't need to perform any extra steps in such cases. You can also mark it with the @objc attribute and provide an alternative name:

    class Person: NSObject {
    }

Features of Swift that are not available in Objective-C

There are some features of Swift that are not available in Objective-C, so if you plan to use Swift code from Objective-C, you should avoid using them. Here is the complete list of these features:

  • Structures
  • Generics
  • Tuples
  • Enumerations
  • Type aliases
  • Top-level functions
  • Curried functions
  • Global variables
  • Swift-style variadic parameters
  • Nested types
You have been reading a chapter from
Swift High Performance
Published in: Nov 2015
Publisher: Packt
ISBN-13: 9781785282201
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime