Quantcast
Channel: AirPair Software Coding Tutorials & More
Viewing all articles
Browse latest Browse all 36

Swift Tutorial: Building an iOS application – Part 2

$
0
0
Jack is the author of RubyMotion for Rails Developers and the creator of the RubyMotion-focused MotionInMotion screencast. Request help from Jack

swift

1 Introduction

In part 1 of this tutorial series on building out an iOS application using Swift, we didn’t write any of our own code just yet. Instead we achieved something extremely important: a fundamental understanding of how Swift affects our use of the Cocoa Touch frameworks.

Using the “TaskMe” application that we generated in Xcode 6, it’s time to start adding some real functionality.

2 What you need

We’re going to be building an iOS app in Swift throughout this series, but to do so, you’ll need three things.

This Swift tutorial was written with beta 5 as the current release, and given how active the development is on Swift at the moment, you might read this before we’ve had a chance to update it. So if a code example isn’t working, double check the changes to the language since beta 5.

3 Our first feature

The first feature we want to add is just simply having the ability to add a new task to our task list. Once we’ve created this feature, we’ll be able to tap the “+” button, type in our task’s title and some notes if we like, and when we tap “Save”, we’ll be taken back to the list of tasks.

3.1 Setting up our Storyboard

Due to the Apple’s prerelease software NDA, I can’t show any screenshots, which is a shame for sections of the tutorial like this one where there is some visual aspect to the work. I trust that you’re a smart cookie though and can follow the written instructions with only a little bit of working things out.

For our ‘new task’ user interface, we’d like the user to tape a “+” button and have a new controller pop up modally. Open up Main.storyboard and we’ll get started on this.

We’re actually going to use two controllers to achieve this, a UINavigationController and a normal UIViewController which will be embedded in the new UINavigationController (we won’t be reusing the one already on screen, as that’s for the main workflow). So drag out a UINavigationController and UIViewController from the Object Library (located at the bottom right of Xcode 6) into the editor area.

Delete the table view controller that was created with the UINavigationController, then hold down control, click on the UINavigationController, and drag across to the newly created UIViewController. In the popup that appears, choose “root view controller” from underneath the “Relationship Segue” section of. This will embed the UIViewController in the UINavigationController so we can later add “Cancel” and “Save” buttons to it.

Next we need to set up the segue for navigating to the UINavigationController and UIViewController. Before we do that, though, go into the MasterViewController.swift file and delete the following two lines from the viewDidLoad method:

let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "showAddTaskController:")
self.navigationItem.rightBarButtonItem = addButton

With those deleted, you can also delete the insertNewObject: method.

Back in your Main.storyboard file, drag a Bar Button Item from the Object Library onto the right hand side of the MasterViewController‘s navigation bar. Then, in the Attributes Inspector, change its Identifier to “Add.”

Now we need to set up our segue from the MasterViewController to the new UINavigationController. Hold control and drag from the Bar Button Item you just created to the new UINavigationController, and choose “present modally” from within the “Action Segue” section of the popup.

Select the new segue — it will look like a rectangle in a circle as part of an arrow between the MasterViewController and the new UINavigationController — and set the Identifier to “showAddTask” using the Attributes Inspector.

The last thing left to do is to set up our screen. From the Object Library, drag two Text Fields into the UIViewController, positioning them as you see fit. You should try setting up the Auto Layout constraints by holding control and dragging around both the Text Fields and the containing view.

With the first Text Field selected, we’re going to edit some settings in the Attributes Inspector. First, change the empty placeholder to say “Task Title,” and then change the font size to 24 points. You can do this through the font editor, which can be opened by clicking on the “T” icon next to the font.

So that we can play around with the height as well as the width, let’s change the Border Style to be the second one from the right. Now you can play with the height; I made my text field about 60 points tall, and I also change the Alignment to be centered.

Now, do the same for the second Text Field, except maybe give it a smaller font size — I made mine 16 points — and height, and make the placeholder text something like “Notes.” I also set the alignment for the notes field to be left instead of center.

Click on the navigation bar in the new UIViewController, and set the title to be “Add Task” in the Attributes Inspector.

With all of this done, we now have our two fields and the controllers. Next we need to create our UIViewController subclass for our new Add Task screen.

Before we continue though, try running the application to see that you can now open the new screen, though we can’t get back.

3.2 Creating the AddTaskViewController

From the “File” menu, select “New → File” or use the cmd + N keyboard shortcut to start creating our new AddTaskViewController file.

Making sure you’re in “iOS → Source,” select “Cocoa Touch Class” from the options and click “Next.” In the “Subclass of:” field, type or select “UIViewController,” then add “AddTask” to beginning of the name in the “Class:” field.

Leave “Also create XIB file” unchecked, and make sure “Swift” is selected for “Language,” then click “Next.” A file dialog will pop up; choose the location for the file (the default is likely where you want it to be) and click “Create.”

Before we start editing the file that just popped up, we need to remember to set this to be the class for the UIViewController we created in our Storyboard. Open our Main.storyboard up again, select the new UIViewController we created in the previous section, and set the Class to be AddTaskViewController in the Identity Inspector (the panel on the top left that looks like a small square and some lines).

Now, with the focus on the AddTaskViewController in Interface Builder, open up the Assistant Editor (the tuxedo-looking icon in the toolbar) so that we can set up the outlets between the Storyboard and our code.

Hold control and drag from each of the Text Fields to the top of the class definition for AddTaskViewController, naming each titleField and notesField respectively. This should give you something that looks like this:

class AddTaskViewController: UIViewController {
    @IBOutlet weak var titleField: UITextField!
    @IBOutlet weak var notesField: UITextField!

    override func viewDidLoad() {

If you’ve done any iOS development work using Objective-C before, this will look similar to what you used to see in the header files.

The @IBOutlet is a declaration of the connection between the Storyboard file and your code. The reason it uses an implicitly unwrapped optional is so that the view controller can be initialized without this set, and then these can be set once the views are ready. It won’t effect us in most cases, like setting things up in viewDidLoad or viewWillAppear:animated:, as it will be set by then.

The weak declaration for the variable is also to ensure there are no unnecessary references. Without this, the AddTaskViewController would own the two UITextFields, which means that when the view attempts to be released for whatever reason, it wouldn’t be allowed to because the controller is still hanging onto it’s subviews.

3.3 Cancelling task creation

The next step for us is to set up the “Cancel” button so that when we tap it, our task isn’t saved. Instead, we simply hide the task creation screen.

In the Main.storyboard file, we’re going to drag out a new Bar Button Item from the Object Library, and place it into the left hand side of the navigation bar of our AddTaskViewController‘s screen.

Select the Bar Button Item, then change the Identifier to “Cancel” in the Attributes Inspector.

It’s important to use these standard versions of UI elements for two reasons: future-proofing and accessibility. We could have quite easily just set the title to be “Cancel,” but if Apple changes “Cancel” to be, for instnace, an “X” in the future then our application will be ready for that.

Standard UI elements also have accessibility baked in, and have been thoroughly tested by the best of the best that Apple has.

Now we need to get this “Cancel” button all hooked up. To do that, we’re going to create a new “dismiss” segue.

From the File menu, create a new file, and from the dialog that comes up, select “iOS → Source → Cocoa Touch Class,” then click “Next.” Set “Subclass of:” to “UIStoryboardSegue” and set the “Class:” to be “DismissSegue.” Make sure “Swift” is selected from the “Language” dropdown.

We’ve need to do one tweak before we use this class from our Storyboard. It will currently let a “dismiss” segue appear in Interface Builder, but it will fail at runtime due to some weird behind-the-scenes naming stuff Swift does. To fix this, we need to explicitly define the Objective-C class name so the Storyboard can find the correct class.

You will need to change the class definition to look like this:

@objc(DismissSegue) class DismissSegue: UIStoryboardSegue {

The declaration at the beginning (@objc(DismissSegue)) is to make this class accessible to the Storyboard. This might change over time, but for now it’s required and the application will crash without it.

Now to create a perform method for our custom segue that will simply dismiss the controller.

override func perform() {
    (sourceViewController.presentingViewController as UIViewController).dismissViewControllerAnimated(true, completion: nil)
}

To make the compiler happy, we need to declare that we are sure that the presentingViewController is a UIViewController, as for some reason it’s defined as AnyObject!. From there we can simply dismiss our modal view using dismissViewControllerAnimated:completion.

Now to connect the dots. In the Main.storyboard file, hold control and drag from the selected “Cancel” button, to the MasterViewController. Select the “dismiss” option from the popup.

With all that done, we’re ready to go! Run the application to see our work in action, woohoo!

3.4 Saving our task

Time to actually create some real business value — saving a task — and to do that, we’ll need to have a “Save” button.

In your Main.storyboard file, drag out another Bar Button Item from the Object Library, this time placing it on the right hand side of our AddTaskViewController‘s navigation bar.

Make sure it’s selected, then in our Attributes Inspector, change it’s Identifier to “Save” (didn’t see that coming, did you?)

While we’re here in this file, let’s also clean up something else that has been bugging me. The users of our application don’t care that the list screen is the “Master” screen; to them it’s the “Tasks” screen. Double click where it says “Master” and change it to “Tasks.”

Now add a “dismiss” segue between the “Save” button and the MasterViewController just like you did with the “Cancel” button.

If you run the application now, you should be able to dismiss the modal using either of the buttons, which is exactly what we’re looking for. However, we’d also like to have a task added to a list of tasks, and for our Table View to refresh so that it shows the new task.

We need some central place to put these tasks, and we need a good definition of what exactly a task is, so let’s put a hold on working on the “Save” feature for now, and create these parts.

4 Our core business objects

Modeling our core business objects separately from our user interface is extremely important. It makes them flexible to use, and portable if we were ever to make our application work across platforms — such as adding an iPad or OS X application, or whatever the next ingenious Apple creation ends up being.

We don’t need much. A simple Task struct and a TaskStore class should do us nicely.

4.1 Creating the Task struct

Create a new file (“File → New → File” or command + N), but this time, instead of creating a “Cocoa Touch Class”, we simply need a plain-old “Swift File.”

Name the file “Task” (the “.swift” will be appended automatically) and then we want to create a new “Task” struct within the file:

struct Task {
    let title: String
    let notes: String

    init(title: String, notes: String) {
        self.title = title
        self.notes = notes
    }
}

You may be thinking, “there is no way to edit the Task!” That’s right; instead of making the struct mutable, we’re going to embrace the functional style Swift is aiming to push us towards, and create a nice immutable value object.

When we need to make changes to a task, we’ll simply delete the old one and replace it with the new one. It will seem from the users perspective that it was just edited, but we’re creating less mutable state for us to manage this way, making our lives as programmers easier.

4.2 Managing our TaskStore

Next we need another Swift file for our TaskStore which we’ll set up to be a singleton so that we can access the one instance at all times, adding and “editing” tasks as much as we like.

Create a “Swift File” like we did for our “Task.swift” file, but call it “TaskStore” instead this time.

class TaskStore {
    class var sharedInstance: TaskStore {
        struct Static {
            static let instance = TaskStore()
        }
        return Static.instance
    }

    var tasks: [Task] = []

    func add(task: Task) {
        tasks.append(task)
    }

    func replace(task: Task, atIndex index: Int) {
        tasks[index] = task
    }

    func get(index: Int) -> Task {
        return tasks[index]
    }
}

The first few lines of the TaskStore class create a way for us to use a singleton of our TaskStore by accessing it with TaskStore.sharedInstance.

We then have a few basic functions for us to add, replace, and get tasks from our list.

At some point in the future we could replace this with a more suitable version of this TaskStore class, likely which stores the tasks across launches, but this will do for now.

5 Finishing our first feature

We’re going to wrap up part 2 here with a challenge for you to finish off the “Save” feature. Don’t worry just yet about displaying the list of tasks, as we’ll be covering that in the next part. Simply attempt to get the tasks saved into the TaskStore. You’ll be able to see my solution to this in part 3.

One hint: the trick will be to give the segue from the “Save” button a name, and use the prepareForSegue:sender method.

I hope you’ve enjoyed this series so far, and seen what it’s like to do iOS application development with Swift and Xcode 6. In my opinion so far, though there are some oddities thanks to the language and tools not being complete yet, it’s a large improvement from the verbose and messy history of Objective-C.

The post Swift Tutorial: Building an iOS application – Part 2 appeared first on .


Viewing all articles
Browse latest Browse all 36

Trending Articles