Monday, September 28, 2015

A Simple Swift iOS App from Start to Finish - Implementing the Main View's code Part 2

Introduction

This is part of a series of articles describing the creation of a simple iOS app. A complete list of the articles is included in the first part A Simple Swift iOS App from Start to Finish - Introduction.

I have set up a web site for the finished app at http://DaysWithoutThings.com and you can download it free directly from the app store:





In this article I will finish implementing the code for the main view. There are two parts left to implement. Firstly I need to implement the methods that will set up the display and secondly I need to implement the methods that will react to swipe gestures.



Setting up the Display

 I have already implemented the code to choose which setup method will be called depending on the number of Things defined in my previous article A Simple Swift iOS App from Start to Finish - Implementing the Main View's Code Part 1

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        var thingCollection = appDelegate.thingCollection!
        
        switch thingCollection.things.count {
        case 0:
            moveToList()
        case 1:
            displaySingleItem()
        default:
            displayMultipleItems()
            
        }
        

    }

If there is only one thing defined the displaySingleItem will display that item and then set a timer which will call back to the displaySingleItem method after 60 seconds.

If there is more that one thing defined the displayMultipleItems method will show each item in turn by setting the same call back timer to 3 seconds.
Before implementing these method I need to create some class constants and variables.

 class MainViewController: UIViewController {

    let appDelegate:AppDelegate
    let longDelaySeconds:NSTimeInterval = 60
    let shortDelaySeconds:NSTimeInterval = 3
    var currentItemIndex = 0
    var timer:NSTimer?

The long and short delaySeconds are the time intervals that will be passed to the Timer object The currentItemIndex will be updated by the displayMultipleItems method every time it is called  to track which thing it should display next.The timer variable will hold a reference to the active timer which will be used to stop the timer when necessary. I will start by reseting currentItemIndex to zero and reseting the timer in the viewWillAppear method.


    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        var thingCollection = appDelegate.thingCollection!
        

        currentItemIndex = 0
        stopTimer()
        switch thingCollection.things.count {

Next I will implement the two display methods.


    func displaySingleItem() {
        displayCurrentItem()
        setRedisplayTimer(Selector("displaySingleItem"), delay: longDelaySeconds)
    }
    
    func displayMultipleItems() {
        displayCurrentItem()
        currentItemIndex++
        if currentItemIndex == appDelegate.thingCollection?.things.count {
            currentItemIndex = 0
        }
        setRedisplayTimer(Selector("displayMultipleItem"), delay: shortDelaySeconds)
    }

The displayCurrentItem method updates the view to display the message for the current thing. before I can implement it I need to create an outlet and connect it to the label in my Main View.



@IBOutlet var message: UILabel!

Now I can add my displayCurrentItem method.


    func displayCurrentItem() {
        if let  thing = appDelegate.thingCollection?.things[currentItemIndex] {
            var dayCount = thing.currentDayCount
            var withWord = thing.withSwitch == true ? "with" : "without"
            var dayWord = dayCount == 1 ? "day" : "days"
            message.text = "\(dayCount) \(dayWord)\n\(withWord)\n\(thing.name)"

        }
    }

This just builds up the message to display from the current thing's attributes. Because I set the label control to auto size the size of the font will change depending on how long the thing's name is.




Implementing Swipe Gestures

I want the user to be able to advance the display to the next or previous thing using horizontal swipes.
To implement this I first have to add the correct gesture recognizers to my Main View in the storyboard.



I am going to drag two Swipe Gesture Recognizers on to my Main View and change one of them to recognize swipes to the left instead of the default swipes to the right.



Next I am going to create IBAction methods and connect them to the recognizers by right clicking on the recognizer and dragging from the empty circle next to sent action - selector.



Swipe left will move the display to the next thing in the collection. Because my displayMultipleItems method pre-increments the current item index all I have to do for a left swipe is to stop the timer and call displayMultipleItems.


    @IBAction func didSwipeLeft(sender: AnyObject) {
        if appDelegate.thingCollection!.things.count > 1 {
            stopTimer()
            displayMultipleItems()
        }

    }

    func stopTimer() {
        if let myTimer = timer {
            if myTimer.valid {
                myTimer.invalidate()
            }
        }

    }


Swipe right is slightly more complicated. I have to decrement the current index by two and then adjust if it need to wrap around to the end of the list.


    @IBAction func didSwipeRight(sender: AnyObject) {
        var count = appDelegate.thingCollection!.things.count
        if  count > 1 {
            stopTimer()
            currentItemIndex -= 2
            if currentItemIndex < 0 {
                currentItemIndex = count + currentItemIndex
            }
            displayMultipleItems()
        }

    }

Wrapping up

I have finished the main coding of my app! When I run my app now the Main View cycles through the things I have defined and I can swipe to go back or forward through them.



In my next article  I will discuss how I will test my app and fix any issues I find during my testing.

Next:       A Simple Swift iOS App from Start to Finish - Testing the App

No comments:

Post a Comment