Mobile App Development Blog

Blog Home

Objective C vs Swift: A Beginner’s Guide to Swift Programming

April 14, 2016

Being a techie and an iOS app developer, I am obsessed with the latest in technology. And I like to believe that it shows in the kind of apps we build. Since a lot of my fellow developers want to get a head start in Swift programming, I put together a tutorial that will help them jumpstart their efforts. This blog post is written with an assumption that you are familiar with Objective C and are looking for a quick overview of the features of Swift.

swift-objective-c

Trying out Swift vs. Objective-C

As a Swift beginner, all you need to do is install the Latest Xcode from the App Store and create a playground to experiment.

I must also add that even though I will take you through the fundamentals of Swift programming, you can always refer to Apple’s Swift homepage as it is the best reference for learning Swift programming.

Variables and Constants

Declaring a variable in Swift is done using the var keyword.

var x = 1

var s = “Hello”

You will notice that two variables x and s are of different types. x is an Integer, while s is a String. Swift is a type safe language, and it will deduce variable types from the assigned value. If you wish to make your code more readable you can optionally annotate the variable’s type:

var y: Int

y = 2

Constants are similar, but you declare them using let instead of var. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.

let c1 = 1 // Constant known at compile time

var v = arc4random()

let c2 = v // Constant known only at run time

As their name suggests, they are immutable, so the following code will cause a compile-time error.

let c = 1

c = 3        // error

Other types can also be declared as constant. For example, the following code declares an array as a constant, and if you attempt to modify any of the elements, the Swift compiler will report an error:

var arr2 = [4, 5, 6]

arr2[0] = 8

print (arr2)    // [8, 5, 6]

let arr = [1, 2, 3]

a[0] = 5    // error

Optionals

Constants need to be initialized when declaring them, and variables need to be initialized before use. So where’s the Objective-C nil equivalent? Swift introduces optional values. Optional values can have a value or be nil. If you take a look at the following code, you will notice that x was assigned an Optional value of 2014. This means that Swift compiler was aware that x might also be nil.

var s = “2014”

var x = s.toInt()

print(x)    // Optional(2014)

If you make a change in this code and assign the value “abc” to s, which cannot be converted to an Integer, you will notice that x is now anil.

var s = “abc”

var x = s.toInt()

print(x)    // nil

The return type of toInt() function is Int?, which is an optional Int. Let’s try to call a standard function on x:

var x = “2014”.toInt()

print(x.successor()) // error

The compiler signals an error, since x is an optional and could potentially be nil. We have to test x first, and make sure that the successor function is invoked on a real number, and not a nil value:

var x = “2014”.toInt()

if x != nil

{

print(x!.successor())    // 2015

}

Note that we have to unwrap x by appending an exclamation mark (!). When we are sure that x contains a value, we can access it. Otherwise we will get a runtime error. We can also do what Swift calls optional binding, converting the optional into a non-optional variable

let x = “123”.toInt()

if let y = x

{

print(y)

}

The code in the if statement will only execute if x has a value, and assign it to y. Note that we don’t need to unwrap y, it’s type is not optional since we know x is not nil.

Check Apple’s Swift tutorial to read more details on optionals and nice features like optional chaining

String Interpolation

In Objective-C formatting strings is usually done with the stringWithFormat: method:

NSString *user = @”Gourav”;

int days = 3;

NSString *s = [NSString stringWithFormat:@”posted by %@ (%d days ago)”, user, days];

Swift has a feature called string interpolation to do the same, but it is more compact and easier to read:

let user = “Gourav”

let days = 3

let s = “posted by \(user) \(days) ago”

You can also use expressions:

let width = 2

let height = 3

let s = “Area for square with sides \(width) and \(height) is \(width*height)”

To learn more about Swift’s string interpolation and other new features, go here.

Functions

Function definition in Swift is different from C. A sample function definition is below:

func someFunction(s:String, i: Int) -> Bool

{

…    // code

}

Swift functions are first-class types. This means that you can assign functions to variables, pass them as parameters to other functions, or make them return types:

func stringLength(s:String) -> Int

{

return countElements(s)

}

 

func stringValue(s:String) -> Int

{

if let x = s.toInt()

{

return x

}

return 0

}

func doSomething(f:String -> Int, s:String) -> Int

{

return f(s).successor()

}

let f1 = stringLength

let f2 = stringValue

doSomething(f1, “123”)    // 4

doSomething(f2, “123”)    // 124

Again, Swift infers the types of f1 and f2 (String -> Int), although we could have defined them explicitly:

let f1:String -> Int = stringLength

Functions can also return other functions:

func compareGreaterThan(a: Int, b: Int) -> Bool

{

return a > b

}

func compareLessThan(a: Int, b: Int) -> Bool

{

return a < b

}

func comparator(greaterThan:Bool) -> (Int, Int) -> Bool

{

if greaterThan

{

return compareGreaterThan

}

else

{

return compareLessThan

}

}

let f = comparator(true)

println(f(5, 9))

A guide to functions in Swift can be found here.

Enumerations

Enumerations in Swift are much more powerful than in Objective-C. As Swift structs, they can have methods, and are passed by value:

enum MobileDevice : String

{

case iPhone = “iPhone”, Android = “Android”, WP8 = “Windows Phone8”, BB = “BlackBerry”

 

func name() -> String

{

return self.toRaw()

}

}

let m = MobileDevice.Android

print(m.name())    // “Android”

Unlike Objective-C, Swift enumerations can assign Strings, characters or floats as values for each member, besides integers. The convenient toRaw() method returns the value assigned to each member.

Enumerations can also be parameterized:

enum Location

{

case Address(street:String, city:String)

case LatLon(lat:Float, lon:Float)

 

func description() -> String

{

switch self

{

case let .Address(street, city):

return street + “, ” + city

case let .LatLon(lat, lon):

return “(\(lat), \(lon))”

}

}

}

let loc1 = Location.Address(street: “2070 Fell St”, city: “San Francisco”)

let loc2 = Location.LatLon(lat: 23.117, lon: 45.899)

print(loc1.description())        // “2070 Fell St, San Francisco”

print(loc2.description())        // “(23.117, 45.988)”

More information about enumerations is available here.

Tuples

Tuples group multiple values into a single compound value. The values within a tuple can be of any type and do not have to be of the same type as each other.

let person = (“Gourav”, “Aryan”)

print(person.0) // Gourav

You can also name the individual tuple elements:

let person = (first: “Gourav”, last: “Aryan”)

print(person.first)

Tuples are extremely convenient as return types for functions that need to return more than one value:

func intDivision(a: Int, b: Int) -> (quotient: Int, remainder: Int)

{

return (a/b, a%b)

}

print(intDivision(11, 3))    // (3, 2)

let result = intDivision(15, 4)

print(result.remainder)    // 3

Unlike in Objective-C, Swift supports pattern matching in a switch statement:

let complex = (2.0, 1.1)    // real and imaginary parts

switch complex

{

case (0, 0):

println(“Number is zero”)

case (_, 0):

println(“Number is real”)

default:

println(“Number is imaginary”)

}

In the second case we don’t care about the real part of the number, so we use an _ to match anything. You can also check for additional conditions in each case. For that we need to bind the pattern values to constants:

let complex = (2.0, 1.1)

switch complex

{

case (0, 0):

println(“Number is zero”)

case (let a, 0) where a > 0:

println(“Number is real and positive”)

case (let a, 0) where a < 0:

println(“Number is real and negative”)

case (0, let b) where b != 0:

println(“Number has only imaginary part”)

case let (a, b):

println(“Number is imaginary with distance \(a*a + b*b)”)

}

Note how we need to bind only the values we are going to use in the comparison or in the case statement.

To read more about tuples, go here.

Classes and Structures

Unlike Objective-C, Swift does not require you to create separate interface and implementation files for custom classes and structures. As you learn Swift, you will learn to define a class or a structure in a single file, and the external interface to that class or structure is automatically made available for other code to use.

Defining Classes

Class definitions are very simple:

class Bottle

{

var volume: Int = 1000

 

func description() -> String

{

return “This bottle has \(volume) ml”

}

}

let b = Bottle()

print(b.description())

As you can see, declaration and implementation are in the same file. Swift no longer uses header and implementation files. Let’s add a label to our example:

class Bottle

{

var volume: Int = 1000

var label:String

 

func description() -> String

{

return “This bottle of \(label) has \(volume) ml”

}

}

The compiler will complain because label is a non-optional variable and will not hold a value when a Bottle is instantiated. We need to add an initializer:

class Bottle

{

var volume: Int = 1000

var label:String

 

init(label:String)

{

self.label = label

}

func description() -> String

{

return “This bottle of \(label) has \(volume) ml”

}

}

Or, we could use Optional type for a property, which does not to be initialized. In the following example we made volume an Optional Integer:

class Bottle

{

var volume: Int?

var label:String

init(label:String)

{

self.label = label

}

func description() -> String

{

if self.volume != nil

{

return “This bottle of \(label) has \(volume!) ml”

}

else

{

return “A bootle of \(label)”

}

}

}

Structures

The Swift language also has structs, but they are much more flexible than in Objective-C. The following code tutorial defines a struct:

struct Seat

{

var row: Int

var letter:String

init (row: Int, letter:String)

{

self.row = row

self.letter = letter

}

func description() -> String

{

return “\(row)-\(letter)”

}

}

Like classes in Swift, structures can have methods, properties, initializers, and conform to protocols. The main difference between classes and structures is that classes are passed by reference, while structs are passed by value.

This example demonstrates passing classes by reference:

let b = Bottle()

print(b.description())    // “b” bottle has 1000 ml

var b2 = b

b.volume = 750

print(b2.description())    // “b” and “b2″ bottles have 750 ml

If we try similar case with struct, you will notice that variables are passed by value:

var s1 = Seat(row: 14, letter:”A”)

var s2 = s1

s1.letter = “B”

print(s1.description())    // 14-B

print(s2.description())    // 14-A

When should we use struct and when should we use class? As in Objective-C and C, use structs when you need to group a few values, and expect them to be copied rather than referenced. For example, complex numbers, 2D or 3D points, or RGB colors.

An instance of a class is traditionally known as an object. However, Swift classes and structures are much closer in functionality than in other languages, and much functionality can apply to instances of either a class or a structure type. Because of this, the more general term used in Swift reference is instance, which applies to any of these two.

Learn the basics of Swift classes and structures here.

Properties

As we saw earlier, properties in Swift are declared with the var keyword inside a class or struct definition. We can also declare constants with a let statement.

struct FixedPointNumber

{

var digits: Int

let decimals: Int

}

var n = FixedPointNumber(digits: 12345, decimals: 2)

n.digits = 4567    // ok

n.decimals = 3     // error, decimals is a constant

Also keep in mind that class properties are strongly referenced, unless you prefix them with the weakkeyword. However there are some subtleties with weak non-optional properties, so read the automatic reference counting chapter in Apple’s Swift guide.

Computed Properties

Computed properties do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.

The following code provides a sample of a computed value sign:

enum Sign

{

case Positive

case Negative

}

struct SomeNumber

{

var number:Int

var sign:Sign

{

get

{

if number < 0

{

return Sign.Negative

}

else

{

return Sign.Positive

}

}

set (newSign)

{

if (newSign == Sign.Negative)

{

self.number = -abs(self.number)

}

else

{

self.number = abs(self.number)

}

}

}

}

We can also define read-only properties by just implementing a getter:

struct SomeNumber

{

var number:Int

var isEven:Bool

{

get

{

return number % 2 == 0

}

}

}

In Objective-C, properties are usually backed by an instance variable, declared explicitly or automatically created by the compiler. In Swift, on the other hand, a property doesn’t have a corresponding instance variable. That is, the backing store of a property cannot be accessed directly. Suppose we have this in Objective-C

// .h

@interface OnlyInitialString : NSObject

@property(strong) NSString *string;

@end

// .m

@implementation OnlyInitialString

– (void)setString:(NSString *newString)

{

if (newString.length > 0)

{

_string = [newString substringToIndex:1];

}

else

{

_string = @””;

}

}

@end

Since, in Swift, computed properties don’t have a backing store, we need to do something like this:

class OnlyInitialString

{

var initial:String = “”

var string:String

{

set (newString)

{

if countElements(newString) > 0

{

self.initial = newString.substringToIndex(advance(newString.startIndex, 1))

}

else

{

self.initial = “”

}

}

get

{

return self.initial

}

}

}

Properties are explained in more detail here

To Be Continued

Well, there are only so many things I could cover in one blog post. There are many more important new things to learn about in Swift – like Generics, interaction with Objective-C libraries, closures, optional chaining, and operator overloading. However, I believe that this quick read will help many Objective-C developers to get on track and let the Swift bird take them to a new heights.

About the author: Gourav Jamwal is a Senior iOS Developer and a huge Apple fanboy. He loves sporting a beard and is extremely hard to find at his desk. But you can always reach him here.

At July, we don’t just build apps, we create experiences. Want to partner with a leading iPhone app development company?

Let’s Connect

Posted Under: