Book Image

Swift High Performance

By : Kostiantyn Koval
Book Image

Swift High Performance

By: Kostiantyn Koval

Overview of this book

Swift is one of the most popular and powerful programming languages for building iOS and Mac OS applications, and continues to evolve with new features and capabilities. Swift is considered a replacement to Objective-C and has performance advantages over Objective-C and Python. Swift adopts safe programming patterns and adds modern features to make programming easier, more flexible, and more fun. Develop Swift and discover best practices that allow you to build solid applications and optimize their performance. First, a few of performance characteristics of Swift will be explained. You will implement new tools available in Swift, including Playgrounds and REPL. These will improve your code efficiency, enable you to analyse Swift code, and enhance performance. Next, the importance of building solid applications using multithreading concurrency and multi-core device architecture is covered, before moving on to best practices and techniques that you should utilize when building high performance applications, such as concurrency and lazy-loading. Finally, you will explore the underlying structure of Swift further, and learn how to disassemble and compile Swift code.
Table of Contents (15 chapters)
Swift High Performance
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
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.

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.

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