Nonoku - Composition

Since I’m using the same background in a bunch of places I want to make it really easy to re-use. I could make a sub-class of UIViewController which implements the functionality. I’m not a fan of that, if it can be avoided. These things have tendency to grow. I could also create a static class method to return the background SKNode. That’s a little better but that’s just a form of composition and Swift actually gives us a nice way to implement this with Protcols and Extensions.

I start by moving declaring the function used for creating the background in a protocol. I’ll call it BackgroundProtocol because I’m awful at names. That’s easy to change later if I decide to add more functionality anyway.

protocol BackgroundProtocol {
    func createBackground(size: CGSize) -> SKNode
}

I can add that protocol to other classes and they’ll have the createBackground(size:) function available to them. Using an extension I can then create a default implementation (by striking coincidence, that’s the code I already had for this).

extension BackgroundProtocol {
    func createBackground(size: CGSize) -> SKNode {         
        let node = SKEffectNode()
        // snip ...
        return node
    }
}

Now I can add that to all the views in my app and they can just call it to get the functionality. And, of course, it can be overridden if needed.

class MainMenuViewController: UIViewController, BackgroundProtocol {
    override func viewDidLoad() {
        super.viewDidLoad()
        let spriteView = (view as? SKView)!
        let scene = SKScene(size: view.bounds.size)
        scene.addChild(createBackground(size: scene.size))
        spriteView.presentScene(scene)
    }
}

Nonoku - Creating a Background

So, I was getting bored of looking at a grey background and, as a break from cleaning up, refactoring, and adding the fiddly (nut necessary) UI code, I decided to run up a quick background.

The original version of Nonoku had a vertical gradient fill, light to dark, with subtle diagonal striping. I liked this so decided to reproduce it. However, it made sense to me to implement this in code. Since I’m using SpriteKit already, rendering to an SKEffectNode which rasterises the nodes made sense (the background is not animated so I can basically update once and be done).

There’s no native way, as far as I’m aware, to draw a gradient on a node, so the first thing would be to create an SKTexture. Again, since this is a one time deal, I’m not too worried. I’ve done something similar before so I already knew I could use a CIFilter to generate this. From that, I can get a CIImage. That can be passed to a CIContext to create a CGImage which can finally be passed to the SKTexture which I’ll pass into an SKSprite.

From reviewing the CIFilter documentation, I can get a list of available filters as follows:

class func filterNames(inCategory category: String?) -> [String]

Even better, under the list of category constants, there is kCICategoryGradient. For this kind of quick exploratory code, I usually start a Swift Playground to spike out the things I don’t know.

So, skipping a step, I have this:

print("\(CIFilter.filterNames(inCategory: kCICategoryGradient))")
let filter = CIFilter(name: "CILinearGradient")
print("\(filter?.attributes)")

The list of filterNames has a couple of likely contenders, CILinearGradient and CISmoothLinearGradient. They take the same attributes (two colours, and two vectors) so I ended up trying both. In my use case I couldn’t see any difference between the two so decided to stick with CILinearGradient. If it ever comes up as an issue, it’s a very simple change to make.

CIFilter.attributes() gives me a list of the supported attributes, and a brief description of them. That's enough to define how I'm going to use it so I can leave the playground and come back to my code.

Since I want to create a new SKTexture with this gradient it makes sense to do it as an extension on SKTexture. I need the size, the start colour, and the end colour. I could add additional logic here but, following YAGNI (You Ain’t Gonna Need It), I am only interested in a vertical gradient so that’s all I’ll support.

extension SKTexture {
    convenience init?(size: CGSize, color1: SKColor, color2: SKColor) {
        guard let filter = CIFilter(name: "CILinearGradient") else {
            return nil
        }
        let startVector = CIVector(x: 0, y: size.height)
        let endVector = CIVector(x: 0, y: 0)
        filter.setValue(startVector, forKey: "inputPoint0")
        filter.setValue(endVector, forKey: "inputPoint1")
        filter.setValue(CIColor(color: color1), forKey: "inputColor0")
        filter.setValue(CIColor(color: color2), forKey: "inputColor1")

        let context = CIContext(options: nil)
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        guard let filterImage = filter.outputImage,
            let image = context.createCGImage(filterImage, from: rect) else {
            return nil
        }

        self.init(cgImage: image)
    }
}

Interestingly, whilst I can just get a ciColor from a UIColor (SKColor aliases UIColor), I can’t use it in the CIFilter due to the following issue.

*** -CIColor not defined for the UIColor UIExtendedSRGBColorSpace 0.666667 0.223529 0.223529 1; need to first convert colorspace.

Instead, I had to create a new instance of CIColor with the UIColor. I’m not sure if there are any issues associated with this, but it’s working fine for me so far.

From there, I just created an SKSpriteNode with the generated texture. The lines were just stroked SKShapeNodes with a CGPath which just have a defined start and end point.

So here’s how it looks:

It’s still early so I’m not sure if this is the final version but it does make the game easier to play as it’s much easier to tell where the empty spaces are. Also, with this approach I can easily generate backgrounds with different colours so I have a bunch of options.

It’s still early so I’m not sure if this is the final version but it does make the game easier to play as it’s much easier to tell where the empty spaces are. Also, with this approach I can easily generate backgrounds with different colours so I have a bunch of options.

Unit Testing - Mocking In Swift

Mocking is a useful tool when writing unit tests. Due to limitations in the current swift version, there aren’t any real mocking frameworks like the ones you see for Java and Obj-C. That said, there are work arounds. Here’s a quick one when you need a one-off:

Method to test:

func crossDissolve(toIdentifier identifier: StoryboardIdentifier) {
    let nextViewController = viewController(forIdentifier: identifier)
    nextViewController.modalPresentationStyle = .fullScreen
    nextViewController.modalTransitionStyle = .crossDissolve
    show(nextViewController, sender: self)
}

This just performs a simple cross-dissolve between two view controllers (the one it’s on to the new one).There are four things to validate:

  1. The UIViewController passed to show(_:sender:) is the one expect.
  2. The sender is correct
  3. That the presentation style is fullScreen
  4. The transition style is crossDissolve

Since it doesn’t return any values I’m going to have to capture them instead. The method under test is crossDissolve(…) so I don’t want to change that behaviour. Everything else is fair game though. In this case, if I intercept the call to show(…) I can capture the parameters passed and validate them.

Since this is a one-off I can nest a class inside my test and capture the values appropriately. Then I can fill in the test.

func testCrossDissolve() {
    class MockSut: UIViewController {
        var showViewController: UIViewController?
        var showSender: Any?
        override func show(_ vc: UIViewController, sender: Any?) {
            showViewController = vc
            showSender = sender
        }
    }
    let mockSut = MockSut()
    mockSut.crossDissolve(toIdentifier: .gameViewController)
    XCTAssertNotNil(mockSut.showViewController as? GameViewController)
    XCTAssertEqual(mockSut.showSender as? UIViewController, mockSut)
    XCTAssertEqual(mockSut.showViewController?.modalPresentationStyle, .fullScreen)
    XCTAssertEqual(mockSut.showViewController?.modalTransitionStyle, .crossDissolve)
}

So, we’re creating a subclass of UIViewController and overriding a method that is called by the method we are interested in testing. Then we can use assertions to complete our test.

Of course, this could get messy if we had a bunch of test cases which needed to handle overrides. In that case I’d move the MockSut class out of the function and into the parent class. If I needed it outside of this specific set of tests, I’d move it into its own class so it could be used in multiple places.

Cleaning Up The Code

So, looking back over the last code, I realised that I was overthinking it massively. The original reasoning behind it didn’t hold up, so I fixed it.

protocol NavigationProtocol {
    func viewController(forIdentifier identifier: StoryboardIdentifier) -> UIViewController
}

extension NavigationProtocol {
    private var storyboard: UIStoryboard {
        return UIStoryboard(name: "Main", bundle: nil)
    }

    func viewController(forIdentifier identifier: StoryboardIdentifier) -> UIViewController {
        return storyboard.instantiate(withIdentifier: identifier)
    }
}

Yep, that’s a bit smaller. Hooray.

Bonus - time for unit tests ;)

func testInstantiateViewController_Splash() {
        let viewController = sut.viewController(forIdentifier: .splashViewController)
        XCTAssertTrue(viewController is SplashViewController)
    }

    func testInstantiateViewController_MainMenu() {
        let viewController = sut.viewController(forIdentifier: .mainMenuViewController)
        XCTAssertTrue(viewController is MainMenuViewController)
    }

Swift Generics

After installing SwiftLint I was going through resolving the issues. Fortunately, I hadn’t too many problems, mostly because it’s still a small project.

Some longish lines did catch my attention though.

enum StoryboardIdentifier: String {
    case splashViewController
    case mainMenuViewController
    case levelSelectViewController
    case optionsViewController
    case gameViewController
}

fileprivate extension UIStoryboard {
    func instantiateAppViewController(withIdentifier identifier: StoryboardIdentifier) -> UIViewController {
        return instantiateViewController(withIdentifier: identifier.rawValue)
    }
}

fileprivate class NavigationAssistant {
    private static let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)

    private static var splashViewController: SplashViewController {
        return (mainStoryboard.instantiateAppViewController(withIdentifier: .splashViewController) as? SplashViewController)!
    }

    private static var mainMenuViewController: MainMenuViewController {
        return (mainStoryboard.instantiateAppViewController(withIdentifier: .mainMenuViewController) as? MainMenuViewController)!
    }

    private static var levelSelectViewController: LevelSelectViewController {
        return (mainStoryboard.instantiateAppViewController(withIdentifier: .levelSelectViewController) as? LevelSelectViewController)!
    }

    private static var optionsViewController: OptionsViewController {
        return (mainStoryboard.instantiateAppViewController(withIdentifier: .optionsViewController) as? OptionsViewController)!
    }

    private static var gameViewController: GameViewController {
        return (mainStoryboard.instantiateAppViewController(withIdentifier: .gameViewController) as? GameViewController)!
    }

As often seems to happen, on revisiting I can see a way to improve it. First off, it's a little bit verbose in the naming. Changing instantiateAppViewController to just instantiate shortens everything up to get it well under the limit. AppViewController is superfluous, named only to stop a naming collision between the extension and the actual class, and ViewController for the thing it is returning. instantiate could possibly be improved upon but it's clear enough in context for the moment.

That’s minor stuff though. What really caught my eye is that I’m repeating the same code over and over. That cast is kind of messy since I’m kind of cheating SwiftLint there. Without that I had return mainStoryboard.instantiateAppViewController(withIdentifier: .splashViewController) as! SplashViewController which is marginally shorter but it’s not really the problem. What I don’t like is that it’s the same call each time with the only change being the Type I’m casting to. If, instead of casting back as a UIViewController, I was to cast back as the type I was expecting then that would save a bunch of repeated code.

I’ve used generics a bunch of times but I keep forgetting about them - at least when I’m first writing out the code. That’s not necessarily a bad thing since the current way works and I’ve come back to it eventually to clean things up. That’s partly my reasoning for writing this post though, to remember to use these things (appropriately).

So, modify the call which returns the UIViewController to return a generic. Easy:

fileprivate extension UIStoryboard {
    func instantiate<T>(withIdentifier identifier: StoryboardIdentifier) -> T {
        return (instantiateViewController(withIdentifier: identifier.rawValue) as? T)!
    }
}

Fairly straight forward, still have that ugly ‘cast to optional, force unwrap’ to appease SwiftLint. Wait a second, SwiftLint also has a rule about force unwrapping! Optional, but maybe there’s a better way.

guard let viewController = instantiateViewController(withIdentifier: identifier.rawValue) as? T else {
    fatalError("Could not instantiate viewController")
 }
return viewController

There we go. Now it’s explicit what the behaviour is meant to be. It’s a little more code but no-one scanning the code should be confused by the intent.

So the whole thing looks like this now. Much better. The repeated logic is now in a single place. I'm happier with how it looks and, whilst there might be more lines, it feels more compact. I think there are some other improvements that can be made but that goes outside the scope of this post.

enum StoryboardIdentifier: String {
    case splashViewController
    case mainMenuViewController
    case levelSelectViewController
    case optionsViewController
    case gameViewController
}

fileprivate extension UIStoryboard {
    func instantiate<T>(withIdentifier identifier: StoryboardIdentifier) -> T {
        guard let viewController = instantiateViewController(withIdentifier: identifier.rawValue) as? T else {
            fatalError("Could not instantiate viewController")
        }
        return viewController
    }
}

fileprivate class NavigationAssistant {
    private static let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)

    private static var splashViewController: SplashViewController {
        return mainStoryboard.instantiate(withIdentifier: .splashViewController)
    }

    private static var mainMenuViewController: MainMenuViewController {
        return mainStoryboard.instantiate(withIdentifier: .mainMenuViewController)
    }

    private static var levelSelectViewController: LevelSelectViewController {
        return mainStoryboard.instantiate(withIdentifier: .levelSelectViewController)
    }

    private static var optionsViewController: OptionsViewController {
        return mainStoryboard.instantiate(withIdentifier: .optionsViewController)
    }

    private static var gameViewController: GameViewController {
        return mainStoryboard.instantiatZ(withIdentifier: .gameViewController)
    }

Swift: Image Picker

A quick overview of getting an image from the camera, or the photo library.

First, set up your view in the interface builder. For this example, I'm keeping it really simple with a UIImageView and 3 buttons.

Update the UIViewController for your view to import MobileCoreServices (contains the constants required for defining what we want from the picker). Also, add support for the protocols we will need for our view controller to serve as a delegate on the picker. If you have created a new project, this will be ViewController.swift.

import UIKit
import MobileCoreServices

class ViewController: UIViewController {
 
}

extension ViewController: UIImagePickerControllerDelegate {

}

extension ViewController: UINavigationControllerDelegate {
    
}

Note that I've taken advantage of Swift's protocol extensions to keep my delegate handling code separate from the rest of my application code. This helps keeps things logically grouped and makes it easier to keep it tidy. I'm not interlacing different contexts which will make it easier to read if I come back to it months later.

Add the user interface code. We're going to get a reference to the UIImageView so we can update it. We'll also hook up actions to the buttons so we can trigger the desired behaviour.

class CameraViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    
    @IBAction func displayCamera(sender: UIButton) {
        displayImagePicker(.Camera)
    }
    
    @IBAction func savedPhotos(sender: UIButton) {
        displayImagePicker(.SavedPhotosAlbum)
    }

    @IBAction func photosLibrary(sender: UIButton) {
        displayImagePicker(.PhotoLibrary)
    }
    
    func displayImagePicker(sourceType: UIImagePickerControllerSourceType) {
        guard UIImagePickerController.isSourceTypeAvailable(sourceType) else {
            return
        }
        
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = sourceType
        imagePicker.allowsEditing = false
        imagePicker.mediaTypes = [kUTTypeImage as String]
        presentViewController(imagePicker, animated: true, completion: nil)
    }
    
    func handleImage(image: UIImage) {
        imageView.image = image
    }
}

A quick description of what's here:
@IBOutlet allows us to connect a component from Interface Builder - just display the source code side-by-side with the Interface Builder view and Ctrl+Drag to connect them. If you drag to an empty space in your code, Interface Builder will prompt you to create an @IBOutlet, or @IBAction.
@IBAction allows us to connect an action on a component in Interface Builder. In this case, Touch Up Inside to define a touch event ending (lift up) that occurred inside the relevant component. As with @IBOutlet, Ctrl+Drag to connect the Interface Builder view to the source code.

The UIImageView, imageView, is defined as a weak reference as the reference will be held for us by the view so we don't need a strong reference in our UIViewController under most circumstances. Doing so can, in fact, lead to memory problems. We don't need specific references for the buttons since we don't need to access, or change, their state.

The @IBAction prefixed functions will trigger when the relevant button is pressed. I've included the button as a parameter, though this isn't necessary for this application, as it can be useful in other cases and is included by default if you let Xcode create the method for you. These methods just call a helper with an appropriate parameter for the source we want to get an image from.

displayImagePicker(sourceType) is a method that creates, and displays, the image picker. This just lets us reuse code that we'd otherwise have to include in all 3 of our IBAction methods since the only change, in this example, is the sourceType. Other than the image picker, the only notable addition is the use of a guard-statement to check if the source type is available. For this I'm just returning if it's not, but a more complete application might display an error message here.

handleImage(image) takes a UIImage as a parameter and updates the imageView to display it. This is nice for a test but of minimal use otherwise.

This code will run but will not do much because we don't currently handle the image retrieval. Nothing is calling the handleImage(image) method yet. Update the UIImagePickerControllerDelegate protocol extension like so:

extension ViewController: UIImagePickerControllerDelegate {
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        dismissViewControllerAnimated(true, completion: nil)
        let mediaType = info[UIImagePickerControllerMediaType] as! String
        if mediaType == kUTTypeImage as String {
            let image = info[UIImagePickerControllerOriginalImage] as! UIImage
            handleImage(image)
        }
    }
}

All we're doing here is handling the UIImagePickerController being dismissed and retrieving the image, if the media type is an image. It should be since we've requested that only image types be allowed but I've included the check in case you want to extend this to handle video in the future.

Note that, whilst we do need to declare that we support the UINavigationControllerDelegate protocol to assign our view controller as the delegate of the image picker, we don't need to handle any of the callbacks so we can leave this blank for now.

Run the app. It's better on a real device since the simulator doesn't support the camera, but the photo library should be accessible on both (privacy restrictions permitting). 

Swift: Initialising a 2D Array

I have a struct called Tile, which has (for now) a position defined as a tuple:

struct Tile {
    let pos: (Int, Int)
}

And a class called Board, which has a 2D array of Tile objects:

class Board {
    let tiles: [[Tile]]
    
    init() {
        var tilesArray = [[Tile]]()
        for row in 0..<Board.rows {
            var rowTiles = [Tile]()
            for column in 0..<Board.columns {
                let tile = Tile(pos:(column, row))
                rowTiles.append(tile)
            }
            tilesArray.append(rowTiles)
        }
        
        tiles = tilesArray      
    }
}

This works, though it feels a little messy... I'll have to come back and look at this again.

Xcode 7 and Swift 2: Unit Testing (again)

Some follow up from creating a new project and adding tests.

This turned out to be important...

This turned out to be important...

I hadn't really noticed in the last one but I hadn't added the new classes to the test target, as I would under Obj-C. In Swift 2 there's a new @testable keyword. I found it blogged by Natasha the Robot when I started looking to find out why I wasn't seeing any code coverage showing up for my classes.

Then I started wondering why I was getting Undefined Symbol errors. I could resolve them by including the classes, but then I wouldn't get coverage and everything I saw on @testable assured me I didn't need to include them. Finally, I remembered I'd been getting a bit click happy earlier. I'd disabled Allow testing Host Application APIs.

One checkbox later and I'm a happy camper...

Okay, not a lot done tonight but I feel like a few pieces fell into place.

Xcode Plugins

Install the Alcatraz (http://alcatraz.io) package manager to get these.  

https://github.com/neonichu/BBUFullIssueNavigator
Shows the whole error/warning in the issue navigator instead of a single line.

https://github.com/yuhua-chen/MCLog
Allows you to filter the console by a regular expression. 

https://github.com/markohlebar/Peckham
Add imports from anywhere in the code base - press Cmd+Ctrl+P to pop up a window which has autocompletion for your headers. 


https://github.com/onevcat/VVDocumenter-Xcode
Fill in a quick documentation template.


https://github.com/kinwahlai/XcodeRefactoringPlus
Additional refactoring tools. Still not as full-featured as some IDEs but it's a case where every little helps.