Tag Archives: Swift

How to use Arrays in Swift

Swift has its own built-in Array class. Although it’s bridged to NSArray, a Swift Array is something entirely different. Swift Arrays do not work with such trusted methods like addObject anymore.

Because I will probably have forgotten most of this by tomorrow, here’s a quick lowdown on how to play with Swift Arrays.

// create an empty array [type in square brackets]
var emptyArray = [String]()

// create an array with inferred values
var array = ["one", "two", "three"]

// loop through the array
for value in array {
    print("The value is \(value)")
}

// insert new value at a particular index
array.insert("two and a half", atIndex: 2)
var value = array[2]

// add something to the end of our array
array += ["new value"]
// or
array.append("another value")

// grab the last entry in our array
value = array.last!

// add another array
let anotherArray = ["four", "five", "six"]
array += anotherArray

// how many entries does our array have?
print(array.count)

// remove the last item in the array
array.removeLast()

// remove an item at a particular index
array.removeAtIndex(3)

Swift Arrays and Lazy Initialisation

Swift Arrays don’t like being initialised with a closure. God only knows why. We can however solve this puzzle with a simple function that returns our initialised values:

    lazy var data: [String] = self.initData()
    
    func initData() -> [String] {
        
        // initialize data array and return it
        var data = [String]()
        
        let formatter = NSNumberFormatter()
        formatter.numberStyle = .SpellOutStyle
        
        for var i = 0; i < 30; i++ {
            let number = NSNumber.init(integer: i)
            data.append(formatter.stringFromNumber(number)!)
        }
        return data
    }

For everything else about Swift Arrays, check out the Collection Types section of The Swift Programming Language:





How to write a Custom Initialiser in Swift

I’m used to initialising my Objective-C objects with a custom initialiser. It’s a trick I’ve learnt from the legendary Simon Allardice back in the day. It works a treat every time!

Turns out it’s a Cocoa and Cocoa Touch design pattern, and the principle can be applied similarly in Swift, with a couple of important differences.

Or shall I say pitfalls?

Continue reading





How to access values in a Swift Dictionary

Swift has its own dictionaries, much like Objective-C has the NSDictionary class. Although the two are bridged, they are not the same: trusty old NSDictionary methods do not work with Swift Dictionaries.

Here’s a quick summary of how Swift Dictionaries work.

Creating and iterating over Swift Dictionaries

Let’s create a Swift Dictionary and then list all its values using Fast Enumeration:

// make a Swift Dictionary (Option 1)
var dict: Dictionary = ["key1": "Value 1", "key2": "Value 2", "key3": "Value 3"]

// or, specifying the key/value types (Option 2)
var dict: [String: String] = ["key1": "Value 1", "key2": "Value 2", "key3": "Value 3"]

// or, specifying nothing at all and let everything be inferred (Option 3)
var dict = ["key1": "Value 1", "key2": "Value 2", "key3": "Value 3"]

// list all values
for (key, value) in dict {
    print(key, value)
}

// output: 
key1 Value 1
key3 Value 3
key2 Value 2

The easiest way to create a dictionary is Option 3, letting the compiler infer everything. The other two options are valid too.

What’s special in comparison to NSDictionaries is that in Swift, we can pass both the key and the value to the for loop, rather than just the key.

Accessing a single key’s value

What the elaborate Apple documentation doesn’t explicitly mention for stupid people like me is how to access a single value in the Swift Dictionary. It’s surprisingly simple:

// list a single key's value
print("Value for key1 is", dict["key1"])

// output
Value for key1 is Value 1

Changing a value in our dictionary

We can use the same syntax to update a value in our Swift Dictionary too. Notice that the dictionary must be declared as a variable rather than a constant. The compiler is nice enough to offer this service free of charge:

// change the value of key1 to something else
dict["key1"] = "New Value"
print("Value for key1 is now", dict["key1"])

// output
Value for key1 is now New Value

Adding key/value pairs to our dictionary

To add another key/value pair, we’ll pretend it already exists and simply set its value:

// add a key/value pair 
dict["key4"] = "Brand New Item"

Counting all entries in the dictionary

To see how many key/value pairs we have in our dictionary, we can call the count method:

// how large is the array?
print("The dictionary has", dict.count, "entries.")

// output
The dictionary has 3 entries.

Clearing out a Swift Dictionary

To empty the whole dictionary from all keys and values without destroying the whole thing, we can use this:

// empty my dictionary
dict = [:]
print("The dictionary now has", dict.count, "entries.")

// output
The dictionary has 0 entries.

This is different to setting the dictionary to nil because it leaves the key/value types in place (here: String and String).

Further Reading





How to switch root view controllers in Swift

Here’s how to switch root view controllers in Swift. It comes in handy when you want to instantiate a view controller from your storyboard and display it at arbitrary points in your app.

Imagine a single view application with an additional view controller. Each view controller has a button that switches to the other view controller. To make it more interesting, each view controller is embedded in a navigation controller. The methods to switch to either view controller are called centrally in the AppDelegate.swift file:

func switchViewControllers() {
    
    // switch root view controllers
    let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
    let nav = storyboard.instantiateViewControllerWithIdentifier("Two")
    
    self.window?.rootViewController = nav
    
}

func switchBack() {
    
    // switch back to view controller 1
    let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
    let nav = storyboard.instantiateViewControllerWithIdentifier("One")
    
    self.window?.rootViewController = nav
}

In our storyboard, let’s make sure that each navigation controller has a Storyboard ID for manual instantiation. In the above example that’s One and Two respectively.

To call the first method from our first view controller, we’ll do this:

@IBAction func switchButtonPresed(sender: AnyObject) {
    
    // switch root view controllers in AppDelegate
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.switchViewControllers()
}

We’ll grab a reference to our UIApplication’s delegate and typecast it to be an instance of AppDelegate. Unlike in Objective-C, there’s no need to import this class into our view controller in Swift. Then we go ahead and call the method.

In our second view controller, we’ll do exactly the same, except for calling the other method in AppDelegate:

@IBAction func switchButtonPressed(sender: AnyObject) {
    
    // change to first view controller
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.switchBack()
}

Here’s a demo project that shows the above in action:





How to use Swift classes in Objective-C

It is possible to use Swift classes from Objective-C code (and vice versa) – but Apple’s documentation is a little cloudy (and verbose) on how to actually achieve this magic.

Here’s how it works.

I’m assuming we have a project written in Objective-C, but there’s a new Swift class that needs to be used and we want to access it from Objective-C code, with Objective-C syntax.

Preparing your Xcode Project

As soon as we add a Swift class to an Objective-C project, we’ll get an invitation from Xcode: “Shall I create a Bridging Header” it asks. Technically we don’t need this: it will be useful to do the reverse of what we want to do, i.e. make Objective-C code usable in Swift.

Agree to the friendly offer anyway, so both classes can access each other natively. It may come in handy for future use.

Screen Shot 2015-11-13 at 18.09.59

You’d think this is all the information our clever Xcode should need, but it isn’t. We’ll also need to tell it that we want to use both Swift and Objective-C in the same project (as if that wasn’t obvious).

To do this, head over to your target and find the Build Settings tab. We’re looking for an option called Embedded Content contains Swift Code (under Build Options):

Screen Shot 2015-11-13 at 18.50.20

That’s all we have to do in Xcode for now.

Continue reading





How to kill your app when it enters background mode

By default, any iOS app we create with Xcode automatically continues running for a short period of time, even if the user puts it in the background and launches a new app. You can even prolong the background execution of an app if your app needs it (for example, finish downloads or long running calculations).

But not all apps need this capability. In fact, if we want to be really nice, we can opt out app in to terminate when it hits the background. It’s really easy to do too: all we need to add is a boolean value into our Info.plist file. It’s called UIApplicationExitsOnSuspend.

Set it to YES and our app terminates as soon as someone presses the home button.

Screen Shot 2015-11-06 at 23.26.02

To add the key, either select your Info.plist file, or head over to your target and click the Info tab at the top (see screenshot).

This is a plist editor, and if you’re not familiar with how to use it, let me introduce you to one of the worst examples of UI design ever – Apple Style:

  • hover over the Key column until you see those little +/- icons come up
  • select the plus icon to add another row
  • double-click the Key part if your row until you can type something in
  • type “UIApplicationExistsOnSuspend” and see it turn into the text “Application does not run in background mode”
  • notice that the type column has changed into Boolean
  • in the Value column, on the far right, find two arrows and change the value to YES
  • that’s it!

Termination Testing

The easiest way to test if this is working is to add a couple of log messages to your AppDelegate file. Find the method stubs for applicationDidEnterBackground and applicationWillTerminate and write yourself a message:

func applicationDidEnterBackground(application: UIApplication) {

    NSLog("we are in the background...")
}

func applicationWillTerminate(application: UIApplication) {

    NSLog("we have terminated")
}

The first method will be called with or without the magic termination key. But the second method will only be called if the app is purged from memory. If you set the key correctly, both methods should be called.

Note that even though the app is killed, it is still visible when you double-tap the home key – but it no longer occupies any memory, nor will it continue to run in the background. As far as I know, this behaviour can only be changed by the user swiping up on an app after a double-tap, or by a hard reset of iOS (hold CTRL+HOME until the Apple Loog appears).