© Molly K. Maskrey 2016

Molly K. Maskrey, App Development Recipes for iOS and watchOS, 10.1007/978-1-4842-1820-4_15

15. Coin Toss Project

Molly K. Maskrey

(1)Parker, Colorado, USA

In this chapter we’ll move into developing a more up-to-the-minute kind of application. We’ll work with Swift and the Apple Watch to create a very simple game of flipping a coin. I’ve actually used this on occasion, out in the world, to choose a path when I’m confronted with a couple of different, seemingly equal choices. I often wonder why I make so many wrong decisions.

Problem

We want to get started in Swift, but make it a fun experience.

Solution

We’ll build a simple, easy-to-implement app for the Apple Watch.

Let’s Work Through the Project

This time, we will take a different approach in our development, and I’ll endeavor to do the same in the upcoming projects as well. We would normally create the project (which we will always start with) then dive into the logic of the algorithms, finishing up with embellishments such as the app icons. Because Xcode gives us complete functioning templates in an architectural sense—functionally they do nothing—we can generally build and run our apps right from the start, without adding much code at all.

What we’ll do here is to create the project in Xcode, build the project to ensure that it works to the extent of loading onto our devices, work through getting our app icons in place and displayed properly, then add the other necessary code and objects to provide the coin-flipping functionality.

Create the Project

Start by creating the project, as shown in Figure 15-1. At this point, you should be familiar with creating any type of project in Xcode. Here, the easiest solution is to go to File ➤ New ➤ Project… in Xcode, then select under “WatchOS” the “iOS App with WatchKit” option . By default, for me anyway, Xcode chose a universal build—that is, for both iPhone and iPad. Since we’re working toward an Apple Watch app, and at the time of this writing this would only work through an iPhone, you should probably change the “Devices” drop-down to “iPhone.”

A371701_1_En_15_Fig1_HTML.jpg
Figure 15-1. Create the project in Xcode, but instead of “Universal,” you may want to change this to “iPhone only” since that will be our focus

Note that there are three targets: the Coin Toss app that executes on the phone, the Watch app itself, and the Watch App extension. As we are at the early stages of development on Apple Watch, projects using Watch are set up so that an iPhone app is required in addition to two Watch targets. The iPhone-only (currently) app allows connection with and the proper setup of the Watch. The two Watch targets provide the UI (the Watch App itself) and the logic (the Watch App extension). The splitting of the two parts of Watch is derived from the original WatchOS 1 release. The Watch app represents the UI that the user sees on the face, whereas the extension contains most of the logic. Previously, in WatchOS (aka version 1) the extension ran on the iPhone and communicated with the Watch app—the UI—that ran on the Watch device. With the release of WatchOS 2 , the extension now runs on the Watch device, permitting native Watch apps to be built.

You can, of course, choose to either work with the simulator at this point or build directly onto your devices. I’m taking the latter approach, building directly to my device to give you an idea of how things work with this more complicated approach. Once you’ve set up and verified that all your credentials in the project settings are correct, go ahead and build the project. You won’t get anything very useful except a blank screen on the simulator or actual iPhone device. What we want to do now is to press the Home button, either on the phone or virtually in the simulator, to get to the splash screen. Look for the app icon, and you should see something that looks like Figure 15-2.

A371701_1_En_15_Fig2_HTML.jpg
Figure 15-2. Initially building the app to your device will show the default icon

Fix the App’s Icons

I’ll certainly detail how we’re going to make the app work, but for a little bit of fun let’s fix the icon right away. In fact, because we’re building for the Watch and the iPhone, let’s get them both in shape before proceeding. First, locate the image files in the additional source code for the AppIcon, as shown in Figure 15-3, and the Watch, Figure 15-4. The quickest way to locate the actual image files, or any project file for that matter, is to, from within Xcode, right-click on the file name you’re interested in—for the image files that would be the Assets.xcassets icon in the Project Navigator—then select “Show in Finder.” From there, open the enclosing folder to see the actual image files.

A371701_1_En_15_Fig3_HTML.jpg
Figure 15-3. Either use the provided files or create your own images for icons used on the iPhone
A371701_1_En_15_Fig4_HTML.jpg
Figure 15-4. While you’re at it, get the Watch icons ready as well

Locate the AppIcon in the xcassets section of the iPhone target files in the Xcode organizer, as shown in Figure 15-5. Drag the appropriate size file from its location in the Finder onto the blank place for it in Xcode. You should be able to verify that the correct size is properly associated with the appropriate icon slot. You should know immediately if an incorrectly sized file has been placed. A yellow triangle with an ‘!’ mark will show at the top. In the organizer on the left, click on the Issue Navigator to get more information on the incorrect file placement.

A371701_1_En_15_Fig5_HTML.jpg
Figure 15-5. Place the image file onto its correct spot in the xcassets, AppIcon section in Xcode. Errors should be shown instantly in the Issue Navigator

Build and install the app onto your device, and the proper app icon should now show up on the iPhone splash screen , as in Figure 15-6.

A371701_1_En_15_Fig6_HTML.jpg
Figure 15-6. Now the iPhone app icon is properly displayed

Start the Watch app on the iPhone and scroll down to find the Coin Toss application we just built. Slide the “Show App on Apple Watch” option to the ON position. On the Apple Watch, observe as the app begins to load. It will have a default icon similar to, but much smaller than, the one we saw earlier on the iPhone.

Note

You need to have paired your Apple Watch to the iPhone being used in this part of the exercise.

Just as we did for the iPhone app icon, drag the files from the Finder to the proper location in Xcode. In this case, we’ll want to look at the xcassets in Xcode as before, this time choosing the xcassets under the Watch app section, as shown in Figure 15-7.

A371701_1_En_15_Fig7_HTML.jpg
Figure 15-7. Similar to the iPhone, we want to properly install the images for the Watch

From the project pull-down, select “Clean” and then rebuild your app for your device or simulator. If using an actual device, go to the Watch app and slide the “Show App on Apple Watch” option to the ON position. You should now see the app begin to load on your Watch as before, but with the proper icon, as shown in Figures 15-8 and 15-9.

A371701_1_En_15_Fig8_HTML.jpg
Figure 15-8. The app will begin to load using the proper icon on your Watch
A371701_1_En_15_Fig9_HTML.jpg
Figure 15-9. When loading completes, the app icon will properly appear and function on the Watch face

Set Up the Remaining Icons

Now that we have the iPhone and Watch icons set correctly, let’s finish off the rest of the graphics. First, we need an image of the heads and tails sides of a coin, and, because we want to simulate the flipping of the coin in the air, we’ll also add a side shot.

In the xcassets section where we added the Watch app, create a new, blank imageset as shown in Figures 15-10 and 15-11. The new imageset will be named something generic, such as image. Click on the name and change it to heads, as shown in Figure 15-12.

A371701_1_En_15_Fig10_HTML.jpg
Figure 15-10. Click the ‘+’ button at the bottom of the Assets.xcassets center window and choose “New Image Set”
A371701_1_En_15_Fig11_HTML.jpg
Figure 15-11. You’ll see a new empty imageset displayed
A371701_1_En_15_Fig12_HTML.jpg
Figure 15-12. Change the name of the imageset to “heads”

Repeat the previous steps for the tails and side of the coin images. Locate the three files using Finder, as shown in Figure 15-13. Drag the appropriate images to the correct spots in the xcassets section, as shown in Figures 15-14, 15-15, and 15-16. Note that, because we’re working with the Watch, I’m only loading the 1X images into the assets folder. Using the technique we described earlier, you’ll find these images in the source code.

A371701_1_En_15_Fig13_HTML.jpg
Figure 15-13. Locate either the provided set or your own images of the heads, tails, and side of the coin
A371701_1_En_15_Fig14_HTML.jpg
Figure 15-14. Load the side of the coin into the xcassets
A371701_1_En_15_Fig15_HTML.jpg
Figure 15-15. Load the heads side of the coin into the xcassets
A371701_1_En_15_Fig16_HTML.jpg
Figure 15-16. Load the tails side of the coin into the xcassets

The last thing we need to do is create a sequence of images that we can use to simulate a coin flip. Create a series of images named flip1 through flip10. In the code, we’ll use the image set name “flip” and 10-image sequence that will automatically append the increment number to the sequence and pull the images from the xcassets, i.e., flip1, flip2, flip3, through flip10. This way, we have all our graphics files managed by Xcode through the xcassets mechanism and simplify our functional code a great deal. While it looks like we have a lot more images, as shown in Figure 15-17, in actuality, outside of the iPhone and Watch icons, we still only have the three additional files for heads, tails, and the side of the coin.

A371701_1_En_15_Fig17_HTML.jpg
Figure 15-17. Add the sequence of ten image assets and set to the correct graphic as described previously

One important note: the image selected for each of the image assets must be in a specific order to work in our code. For example, if we landed on heads, our next flip sequence would be side, tails, side, heads, side, etc. But if we landed on tails, we’d want our sequence to be side, heads, side, tails, etc. Where we start is in the Swift code, which we’ll get to shortly, but for now, order the sequence of image assets as follows:

1. flip1 = side

2. flip2 = heads

3. flip3 = side

4. flip4 = tails

5. flip5 = side

6. flip6 = heads

7. flip7 = side

8. flip8 = tails

9. flip9 = side

10. flip10 = heads

Create the Storyboards

Select the Project Navigator in the organizer on the left of the Xcode screen and go to the CoinToss WatchKit App, not the extension, and select interface.storyboard.

Add three objects from the library, in this order: button, separator, image. Then set the image in the attributes inspector to be flip2 (Figure 15-8). Add IBOutlets to the WatchKit extension InterfaceController.swift file by bringing up the assistant editor and control-dragging from the button and image in the usual manner:

@IBOutlet var button:    WKInterfaceButton!
@IBOutlet var coinImage: WKInterfaceImage!
A371701_1_En_15_Fig18_HTML.jpg
Figure 15-18. Add three objects to the Watch interface storyboard Interface Controller: a button, a separator, and an image that we will default to flip2

Also, add an IBAction for the button, called buttonPressed:

@IBAction func buttonPressed() {
}

You now have completed the UI setup and added the skeleton code for the action and outlets for our app. Next, we’ll complete the app by adding just a little bit of code.

Write the Code

Listing 15-1 shows the code for the ViewController.swift file . It should be apparent that this is the Swift generated by Xcode when we created the project. Confused? You needn’t be. This simply means that we do not write any additional code to execute on the iPhone. We could if, say, we wanted to do a coin flip on the phone itself, but then it’d be just as simple to pull a coin from our purse.

Listing 15-1. No Code Needs to Be Added to the ViewController.swift File
//
//  ViewController.swift
//  CoinToss
//
//  Created by Molly Maskrey on 12/14/15.
//  Copyright © 2015 Global Tek Labs. All rights reserved.
//


import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

In the awakeFromContext method, in the WatchKit extension file, we want to first make sure that the image is not animating in case something happened, such as a hang from a previous execution of the app. This puts us in a known state when the app awakes on our Watch.

The only other thing we need do is to add the logic to simulate the flip inside the buttonPressed() method we added when creating the storyboard. All the additional needed code is shown in Listing 15-2. First, we set the coinImage outlet to the image named flip. There is no actual image so named, but we’re using this as our sequence for the animation. Next, we generate a random number between 0 and 1—that is, one of two options, like a heads or a tails. Finally, depending on the random number generated, we start animating and either stop on a heads or tails depending on the random number. The animation is pretty crude and has a staccato appearance. This is intentional for this exercise so you can get a better sense of what is happening as the app executes.

Listing 15-2. Add the Following Code to the InterfaceController.swift File
@IBAction func buttonPressed() {
    self.coinImage.setImageNamed("flip")
    let randomNumber = arc4random_uniform(2)  // random # between 0 and 1
    if randomNumber == 0 {
        self.coinImage.startAnimatingWithImagesInRange(NSRange(location: 1, length: 10),
        duration: 1, repeatCount: 2)
    } else  {
        self.coinImage.startAnimatingWithImagesInRange(NSRange(location: 1, length: 7),
        duration: 1, repeatCount: 2)
    }
}


override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)


    // Configure interface objects here.
    self.coinImage.stopAnimating()
}

That completes the Coin Toss application. Build the app onto your iPhone and Apple Watch, and you should now have a virtual coin on your wrist whenever you need it.

Problem

The app won’t install onto your Apple Watch. This is usually a problem centered on build settings.

Solution

This problem generally appears as a Watch app that installs most of the way then disappears. Typically, the Watch icon will load to about three-fourths of the way, then disappear as shown in Figure 15-19. Most often this is the result of a couple of things. At the time of this writing, many developers reported a similar issue that was solved by adding a specific, user-defined setting for the Watch App and extension, or at the project level so it is distributed to all targets. In the project’s build settings, click the ‘+’ and select “Add User-Defined Setting,” as shown in Figure 15-20.

A371701_1_En_15_Fig19_HTML.jpg
Figure 15-19. A common install issue in early Watch development is that the app partially installs, but then disappears
A371701_1_En_15_Fig20_HTML.jpg
Figure 15-20. Add a user-defined setting to the project’s build settings

Add the value STRIP_BITCODE_FROM_COPIED_FILES and set the value to NO. Clean and rebuild the project, and this should fix the problem.

Finally, if this does not fix the problem, make sure the deployment target for your Watch in the build settings, for both the Watch App and the extension, is set correctly. Often, when creating a new Xcode Watch project, the settings will default to the latest values. For example, in my case, WatchOS 2.1 was the default deployment target, but the development Apple Watch I used for this exercise was at WatchOS 2.0.

It’s always a good idea to quickly look through all the build settings for each of the three targets—iPhone, Watch App, and extension—when you’re working on a new project and have strange problems.

Summary

As with all projects in this book, I wanted to give you a very brief overview of the steps needed to create the simplest of Watch applications. Xcode provides us a way to create our template Watch app by creating the three blank targets needed: the iOS app, the actual Watch App (or user interface), and the Watch App extension wherein the actual logic resides. The extension also provides the mechanism for moving data between the iPhone and the Watch. Why do that? If you look at the available frameworks Apple provides for Watch, you’ll see several are missing. From my point of view, the most notable is Core Bluetooth. This means I can’t access BTLE devices from a Watch. I need to use the iPhone as a pass-through device.

We also talked about dealing with graphics and icon files in order to create a minimally functioning app. In addition, the awakeWithContext method in the Watch App extension will likely be the “go-to” place for your initialization, much like the viewDidLoad services in our iOS apps.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.239.76.211