Navigation
Tuesday
Jan062015

SpriteKit and Swift – converting a project from Objective-C

In November 2013 I was looking for an excuse to play with SpriteKit and came up with the idea for a mini-game with a Christmas theme. This is what it looks like:

When Swift was announced at WWDC 2014 I was eager to give it a try and looked through my grab bag of side projects for a suitable candidate to try migrating a project from Objective-C to Swift. ’Shooter‘ was a good candidate, because it‘s not too big but also not too trivial.

The source code is available on github: https://github.com/feinstruktur/Shooter and I‘m planning to post about lessons learned when transitioning from Objective-C to Swift in a future update. However, the commit history already tells a pretty decent story of the transition. Commit ab6df2e merges the ‘swift’ branch into master and 8ed7782 is where the journey starts.

Wednesday
Jun042014

Switfly build a Mac app

Curious about Swift, I went ahead and translated Matt Gallagher’s example from Objective-C to Swift. If you stick this in a Playground file it will launch a minimal Mac app. Or you create a simple text file and chmod +x it for direct execution from the command line.
#! /usr/bin/swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk

import Cocoa

var app = NSApplication.sharedApplication()
app.setActivationPolicy(.Regular)

var menuBar = NSMenu()
var appMenuItem = NSMenuItem()
menuBar.addItem(appMenuItem)
app.mainMenu = menuBar

var appMenu = NSMenu()
var appName = NSProcessInfo.processInfo().processName
var quitTitle = "Quit \(appName)"
var quitMenuItem = NSMenuItem(
    title: quitTitle,
    action: Selector("terminate:"),
    keyEquivalent: "q"
)
appMenu.addItem(quitMenuItem)

appMenuItem.submenu = appMenu

var window = NSWindow(
    contentRect: CGRect(x: 0, y: 0, width: 200, height: 200),
    styleMask: NSTitledWindowMask,
    backing: NSBackingStoreType.Buffered,
    defer: false
)

window.cascadeTopLeftFromPoint(NSPoint(x: 20, y: 20))
window.title = appName
window.makeKeyAndOrderFront(nil)
app.activateIgnoringOtherApps(true)
app.run()
Wednesday
Aug212013

Work can be frustrating sometimes

Wednesday
Oct242012

Location-aware passcode settings

Are you on the fence what the passcode setting should be on your iOS device? Are you worried that anyone could access all your data if you left it somewhere yet at the same time annoyed by having to type in your passcode all the time?

I know I am. I use my phone so frequently that a five minute passcode setting actually rarely kicks in. My iPad on the other hand I don’t pick up as often and therefore I would have to enter the passcode pretty much every time. Which is why I don’t use one.

This came back to bite me a few weeks ago when I left my iPad on the cross-trainer in the gym. When I noticed my iPad was missing I wished I had at least set a passcode to protect its contents. Thinking about why I hadn’t, it occurred to me how I could have had the best of both worlds: no passcode while at home or at other places I consider “safe” and a passcode everywhere else.

iOS should simply allow you to define location specific passcode settings. You should be able to define a default which applies everywhere and then one or more regions that are exceptions. This would allow you to define a basic safe setting with a passcode and then other areas where you’re more liberal. You could even have passcode settings of different complexity depending on where you are. No passcode at your home, a complex one abroad, and a simple one everywhere else.

Below you‘ll find an illustration of what the setup for this could look like.

Sunday
Aug122012

Unit testing asynchronous code

Grand Central Dispatch and blocks have made it very easy to send blocks of code off to the background for execution and since it is so much easier, asynchronous code is much more common.

All this is a blessing – except when it comes to unit testing. To test the result of an asynchronous task, you need to force it back to “synchronicity”, so to speak. Unfortunately, Xcode’s built-in testing framework SenTestingKit does not provide any help in this regard. All its test macros like STAssertEquals assume values to be returned synchronously, leaving it up to you to provide them from asynchronous tasks.

GHUnit, on the other hand, does have a mechanism to test asynchronous tasks. However, its setup is a little more complicated than simply adding the built-in SenTestingKit. Unless you need GHUnit for some of its other features, STK is therefore usually the best way to get started with unit testing in Xcode.

To allow for asynchronous testing with SenTestKit, I’ve added a category to SenTestCase that is based on GHUnit’s asynchronous test. It is available as part of a sample project on github.

A test of an asynchronous task using the added method waitWithTimeout:forSuccessInBlock: looks like this:

- (void)test_completion
{
  Downloader *dl = [[Downloader alloc] init];
  
  __block BOOL received = NO;
  [dl startDownloadWithCompletion:^{
    received = YES;
  }];
  
  [self waitWithTimeout:1.1 forSuccessInBlock:^BOOL{
    return received;
  }];
  STAssertTrue(received, nil);
}

This code tests the completion handler of an asynchronous call of a Downloader class (see the example project for details) by waiting for a block to return YES within a given time limit.

What I prefer about this category over the one in GHUnit is that the test is fully contained within the body of the test method. There is no need to implement any other callback method and reference it from this test. This makes copy and paste of tests for re-use much simpler, for example.