Release news: Hungry Bunny & KeyChainItemCRUDKit

Pete Barber from C#, C++, Windows & other ramblings

Not a technical post today, just a bit of news on the things I've been working on.

Firstly, my latest SpriteKit game written in Swift is now available on the App Store. It's called Hungry Bunny and is effectively an endless runner/skill test. It's free with ads.



Secondly, now that Hungry Bunny is complete I've returned to working on another project. This is nowhere near complete but I got to the point where I needed to securely store an OAuth2 token on iOS. I came across the Keychain API. However, the API for this was long winded and I only wanted to use it in a simple manner. Therefore I created a Swift framework to provide CRUD access to it along with a higher level interface where any type conforming to NSCoding and be saved, loaded & deleted.

This is available on github and also as my first ever CocoaPod. All the docs are in the README plus there's an example iOS program (Single View App) and the Unit Tests.

Drawing into bitmaps and saving as a PNG in Swift on OS X

Pete Barber from C#, C++, Windows & other ramblings

Not an in depth post today. For a small iOS Swift/SpriteKit game I'm writing for fun I wanted a very basic grass sprite that could be scrolled; to create a parallax effect. This amounts to a 800x400 bitmap which contains sequential isosceles triangles of 40 pixels with random heights (of up to 400 pixels) and coloured using a lawn green colour.

Initially I was creating an SKShapeNode and creating the triangles above but when scrolling the redrawing of these hurt performance, especially when running on the iOS Simulator hence the desire to use a sprite.

I had a go at creating these with Photoshop. Whilst switching to a sprite improved performance the look of the triangles drawn by hand wasn't as good as the randomly generated ones. Therefore I thought I'd generate the sprite.

It wasn't really practical to do this on iOS as the file was needed in Xcode so I thought I'd try experimenting with a command line OS X (Cocoa) program in Swift. A GUI would possibly be nice to preview the results (and re-generate if needed) and to select the save-to file location but this solution sufficed.

I'd not done any non-iOS Swift development and never generated PNGs so various amounts of Googling and StackOverflow-ing was needed. Whilst the results of these searches were very helpful I didn't come across anything showing a complete program to create a bitmap, draw into it and then save so the finished program is presented below. It's also available as a gist.


1:  import Cocoa  
2:
3: private func saveAsPNGWithName(fileName: String, bitMap: NSBitmapImageRep) -> Bool
4: {
5: let props: [NSObject:AnyObject] = [:]
6: let imageData = bitMap.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: props)
7:
8: return imageData!.writeToFile(fileName, atomically: false)
9: }
10:
11: private func drawGrassIntoBitmap(bitmap: NSBitmapImageRep)
12: {
13: var ctx = NSGraphicsContext(bitmapImageRep: bitmap)
14:
15: NSGraphicsContext.setCurrentContext(ctx)
16:
17: NSColor(red: 124 / 255, green: 252 / 255, blue: 0, alpha: 1.0).set()
18:
19: let path = NSBezierPath()
20:
21: path.moveToPoint(NSPoint(x: 0, y: 0))
22:
23: for i in stride(from: 0, through: SIZE.width, by: 40)
24: {
25: path.lineToPoint(NSPoint(x: CGFloat(i + 20), y: CGFloat(arc4random_uniform(400))))
26: path.lineToPoint(NSPoint(x: i + 40, y: 0))
27: }
28:
29: path.stroke()
30: path.fill()
31:
32: }
33:
34: let SIZE = CGSize(width: 800, height: 400)
35:
36: if Process.arguments.count != 2
37: {
38: println("usage: grass <file>")
39: exit(1)
40: }
41:
42: let grass = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(SIZE.width), pixelsHigh: Int(SIZE.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)
43:
44: drawGrassIntoBitmap(grass!)
45: saveAsPNGWithName(Process.arguments[1], grass!)
46:

When a Swift immutable collection isn’t or is at least immutable-ish

Pete Barber from C#, C++, Windows &amp; other ramblings

Take the following code:

 struct Foo  
{
var value: Int
}

let foo = [Foo(value: 1), Foo(value: 2)]

By using 'let foo' an immutable array has been created. As such no members of this array can be replaced and nor can an element's contents be modified. As such both statements below result in compilation errors.

 foo[0] = Foo(value: 777) // error!  
foo[0].value = 8 // error!

If foo were declared var then both of the above statements would work.

This changes slightly when using reference types:

 class Bar  
{
var value: Int = 0

init(value: Int)
{
self.value = value
}
}

let bar = [Bar(value: 1), Bar(value: 2)]

bar[0] = Foo(value: 777) // error!
bar[0].value = 8 // allowed

The first case of trying to replace an element fails as before but modifying the instance referenced by that element is permitted. This is because the immutable collection holds a reference to the instance of Bar. Modifying the instance does not change the reference so the collection remains unchanged.

If you're making an effort to make your code as immutable (const) as possible (I'm from a C++ background so I endeavour to making everything as const I can) then this is a gotcha to lookout for.

The only way to make Bar properly const is to provide a private setter for the member, assuming it's defined in it's own source file (so this example doesn't work in a Plaground), i.e.

 class Baz  
{
private(set) var value: Int = 0

init(value: Int)
{
self.value = value
}

func f()
{
value = 88;
}
}

Which now prevents value being assigned too.

 let baz = [Baz(value: 1), Baz(value: 2)]  
baz[0].value = 8 // error!


Even if all the properties have private setters there might be methods on the reference type that modify the instance, such as f() above. Just having an immutable collection of reference types is not sufficient to stop these mutating the instances referred too. Invoking f() in the above collection will change the value to 88, i.e.

 println("\(baz[0].value)") // Gives 1  
baz[0].f()
println("\(baz[0].value)") // Gives 88


This differs to C++ where if a collection is const or is returned as a const reference (from a method) than not only is the container immutable but so are its contents. It would be good if Swift were to gain a mechanism that would mark the collection and its contents completely immutable other than having to use a value type.

Anyway, beware of making a collection of reference types immutable and assuming that both the collection and its contents cannot be modified!

Book review: Swift Essentials

Pete Barber from C#, C++, Windows &amp; other ramblings

Disclaimer


I was asked to review: Swift Essentials by Alex Blewitt from Packt Publishing (I'd previously reviewed another book of theirs for the ACCU) and ideally publicise the review. In return I was given a free copy of the eBook and offered another free eBook of my choice upon publication of this review. However, no pressure was exerted and nor was any editorial control requested or given.

In short


It's a good book that provides a more than basic introduction to iOS development using Swift. My major criticism is the title, it does not do the book justice. The sub-title 'Get up and running lightning fast with this practical guide to building applications with Swift' is a far better description. This book is ideal if you're already able to program but would like to learn about iOS development with Swift rather than with Objective-C. It's more about learning iOS app development with Swift rather than about Swift.

In long


The offer to review this book came at good time for me. I'd read quite a lot of the Swift Programming Language book, read many blog articles, attended most of the Swift London meet ups (which incidentally gets a mention in the resource section of the book; so I may have inadvertently met the author) and published my first iOS App written entirely in Swift, a game called Boingy Splat. Therefore I was interested to see what someone else made of the language itself, working with it to create iOS apps and importantly to see parts and techniques I'd missed.

The books takes you from doing mainly pure Swift using REPL on the command line and then introducing and using Playgrounds to implementing a full app, albeit without persisting any data. Smaller apps demonstrating features that will be used in the final app are created along the way. These are small and snappy and allow something concrete to be created along the way, quickly! There is a section on creating Playground packages and adding documentation that seems far from essential; interesting though.

Some of the first chapter introducing the fundamental types and constructs can get a bit dull if you've been there with other languages but it's information that needs presenting. Importantly as soon as possible the Swift idioms (iteration, containers, enums, let versus var etc.) are presented. This is the information that existing developers need.

The Playgrounds chapters introduces a little Cocoa Touch by the way of displaying images. Other than the choice of the author's face as the content (ironic rather than egomaniacal I hope :-)) it's good to be already manipulating the OS with Swift rather than just 'doing' Swift.

From chapter 3 onwards (there are 7 in total) the focus switches to creating apps. The most important concepts (that will allow you to search for and understand more detailed documentation and blogs) are introduced, i.e. Table Views, Master-Detail, Storyboards (and creating purely programmatic views), Custom Views, MVC architecture and accessing remote data. No time is spent on app signing etc. which is an understandable omission but a mention and a reference could prove useful for those very new to iOS development.

The later chapters tend to introduce a new iOS features and new Swift feature making use of one with the other. Even Unit Testing gets a mention when introducing classes and using mocking as example of sub-classing. Likewise full and practical use of Swift's enums and extension methods are given in the remote data chapter.

I was pleased to see Storyboards getting central billing for creating UIs as this is now more or less de rigueur and was always my issue with the Big Nerd Ranch book. The use of Segues is also covered along with how to create the UI using Interface Builder. In this chapter and the rest of the book a fair amount of time is spent showing how to pass data from from View to another. It's a shame the Singleton anti-pattern is presented as a way to share data in the final program especially given the coupling this causes which makes Unit Testing as advocated earlier in the book hard to accomplish.

As this is a new book it was good to see it tackle Auto Layout and not just from the Interface Builder perspective but go so far to explain and use the Visual Format Language. It's quite a feat to present this succinctly and not just cop out with a reference to the official documentation. It's this information that takes a somewhat scary area of iOS development and removes the fear.

The remote data chapter is good in that talks about synchronous versus asynchronous calls and makes use of Swift Closures for the callbacks. It covers useful details such as having to update the UI on the main thread versus performing work on others and shows the mechanisms to achieve this. A small library of useful methods that can be used outside of the book is created in the process. Again, this isn't super detailed information but it's setting new iOS developers on the right course allowing common areas of pain and confusion to be avoided.

Other than title the I have only a couple of criticisms. Firstly, I kept finding references to things either just before they were presented or to unhighlighted aspects of the code. This suggested that in order to keep the size of the book down that various pages had been chopped but less than perfect re-editing had occurred. I was able to reconcile all of these but it meant spending time flicking back through pages. Secondly, in a similar vein whilst the book contains screenshots there are sections where some intermediate screenshots or those of the final effect would aid the description. It's arguable as to whether the persistence of data is an 'essential'. I think it would have been worth taking the page count to 250 (from the current 228) to cover basic persistence; 2nd edition?

Formatting


I read the eBook on iPad mini 2 using the Kindle reader app (mobi format); I haven't seen the paper version.

For technical eBooks, especially to be read on anything smaller than a full size tablet means the formatting, especially of the code is very important. The text is laid out well and most of the code is split-up so the differences between text and code highlight the other which works well. There were a few times when I needed to switch to landscape mode to make the code more readable.

Towards the end where a full program in larger sections is presented it breaks down as there is little text on the same page. Different colours would have been useful for the comments and given the use of inline lambdas (for asynchronous calls) then some other formatting or again another colour would have helped separate these from the code consuming them; though I did notice some use of bold. The use of ANSI rather K&R style braces (though this seems preferred by Apple and is more compact) may have help readability.

Conclusion


When Swift was first released (June '14) a lot of people thought that learning Swift would make then iOS developers whereas the real challenge (other than learning how to program) is to learn how to program against iOS. At that time learning just Swift by itself as a first language had no real benefit especially as all the books and blog articles used Objective-C plus the Cocoa Touch APIs were still rather Swift unfriendly.

Whilst knowing Objective-C is probably essential for a full-time iOS developer today and a basic knowledge will be useful for a long time to come, 8 months down the line learning iOS development just with Swift is extremely viable. This book will allow you to do this. It's not as comprehensive at the de facto book for learning iOS development: Big Nerd Ranch's iOS Programming but it is more than sufficient, uses the latest language and covers features introduced with Xcode 6, e.g. Auto Layout and demonstrates app development along the lines of how Apple sees it, by using Storyboards and Auto Layout. It's also significantly shorter!

Whilst it doesn't cover everything and what it does cover doesn't go into great detail it introduces and uses most of the key concepts of both Swift and iOS. To write an app you'll still need to read and refer to the official documentation and read blogs etc. but after reading this book there will not be much that is alien to you.

I'd recommend this book if you can already program and would like to learn how to develop for iOS. If you already know iOS but would like to learn Swift with familiar examples and see how to access the Cocoa APIs using Swift then this is also a good book. Even if you can't program and aspire to iOS development then this is a book that you could pick up and get a long with pretty soon after you'd got to grips with the basics of programming.

I think it is possible for this to become the 'go to' book for starting iOS development.

Optional chaining with dictionaries (in Swift)

Pete Barber from C#, C++, Windows &amp; other ramblings

Whilst learning Swift and SpriteKit I came across an issue with the documentation for SKNode.userData. In an early XCode beta it was specified as an implicitly unwrapped optional whereas now it is clearly an optional.

Therefore the code I originally used to access values was:

var node = SKNode()
...
if let userData = node.userData
{
    if let value = userData["key']
      // do something with value
}

Once I discovered optional chaining I was able to shorten this to:

var node = SKNode()
...
if let value = userData?["key"]
{
  // do something with value
}

I.e. Use optional chaining to check for existence of userData

This is not something I've seen written about before. Optional chaining  of subscripts is mentioned in The Swift Programming Language book but this only appears in reference to providing a custom subscript operator for a class as opposed to using it with stock types and a brief mention in connection with Dictionaries when the key is not present is also made, e.g.

var dict = ["foo": "hello"]
dict["bar"]? = "world"

The latter is interesting as without the '?' then "world" will be inserted along with the creation of the "bar" key whereas using optional chaining the key must already exist.

Both forms can be combined, e.g.

var dict : [String : String]?
dict?["bar"]?= "world"

which will only insert world if the key "bar" exists and dict exists.

The use of optional chaining with subscript types can lead, like lots of other uses of optional chaining to more readable & succinct code, this is just another example.

Resolving strong references between Swift and Objective-C classes – Using unowned and weak references from Swift to Objective-C classes

Pete Barber from C#, C++, Windows &amp; other ramblings

My Swift and SpriteKit exploration continues. At the moment I'm writing the collision handling code.

Rather than derive game objects from SKSpriteNode with each derived class containing the code for handling collisions with the other types of game objects I'm following something akin to a Component-Entity model.

I have per-game-object handler classes of which an instance of each is stored in the actual SKSpriteNode's userData dictionary. In turn each handler instance has a reference to the SKSpriteNode that references it. Given ARC is used this is a classical strong-reference chain which will prevent memory from being freed. The usual solution to this in Objective-C is to have one of the references be weak. In Swift there are two types of weak references: weak which is the same as in Objective-C and unowned (which I think is new). The difference is that an unowned reference can never be nil, i.e. it's optional whether a weak pointer reference an object but an unowned pointer must always reference something. As such the member variable is always defined using let and must be initialized, i.e. an init method is required.

The following code shows how I was intending to implement this. There is the strong reference from node.UserData to PhysicsActions and then the unowned reference back again from PhysicsActions.

class PhysicsActions
{
  unowned let node : SKSpriteNode

  init(associatedNode : SKSpriteNode)
  {
    // Store really weak (unowned) reference
    self.node = associatedNode
  }

  func onContact(other : PhysicsActions)
  {
     // Do stuff with node

  }
}

class func makeNode(imageNamed name: String) -> SKSpriteNode
{
  let node = SKSpriteNode(imageNamed: name)
  node.userData = NSMutableDictionary()
  // Store strong reference
  node.userData["action"] = makeActionFn(node)
  return node

}

However, when I went to use this code it crashed within the onContact method when it attempted to use the node. Changing this the reference type from unowned to weak fixed this, e.g.

weak let node : SKSpriteNode?

This verified that the rest of the code was ok so this seemed to look like another Swift/Objective-C interoperability issue. Firstly, I made a pure Swift example which is a simplified version from the The Swift Programming Language book.

class Foo
{
  var bar : Bar?

  func addBar(bar: Bar)
  {
    self.bar = bar
  }
}

class Bar
{
  unowned let foo : Foo
  init(foo : Foo)
  {
    self.foo = foo
  }

  func f()
  {
    println("foo:\(foo)")
  }
}

var foo : Foo? = Foo()
var bar = Bar(foo: foo!)
foo!.ç(bar)

bar.f()

Which works and results in:

foo:C14XXXUnownedTest3Foo (has 1 child)

Ok, not a fundamental problem but let's try having an unowned reference to an Objective-C class which is just like the real case as that's what SKSpriteNode is.

Foo2.h

@interface Foo2 : NSObject
@end

Foo2.m

@implementation Foo2

-(id)init
{
  return [super init];
}

@end

main.swift

class Bar2
{
  unowned let foo2 : Foo2
  init(foo2 : Foo2)
  {
    self.foo2 = foo2
  }

  func f()
  {
    println("foo2:\(foo2)")
  }
}

var foo2 = Foo2()
var bar2 = Bar2(foo2: foo2)
bar2.f()

Which when foo2.f() is invoked results in:

libswift_stdlib_core.dylib`_swift_abortRetainUnowned:
0x100142420:  pushq  %rbp
0x100142421:  movq   %rsp, %rbp
0x100142424:  leaq   0x17597(%rip), %rax       ; "attempted to retain deallocated object"
0x10014242b:  movq   %rax, 0x348be(%rip)       ; gCRAnnotations + 8
0x100142432:  int3   
0x100142433:  nopw   %cs:(%rax,%rax)

Again, changing unowned let foo2 : Foo2 to weak var foo2 : Foo2? works. 

I can't explain what the actual problem is but it looks like the enhanced weak reference support (unowned) only works with pure Swift classes. If you have cyclic references to Objective-C classes from Swift then don't use unowned. In fact writing the previous sentence led me to try the following:

let orig = Foo2()
unowned let other = orig
println("other:\(other)")
println("orig:\(orig)")

No cyclic references, just an ordinary reference counted instance of Foo2 (the Objective-C class) which is then assigned to an unowned reference. The final call to println will keep the instance around until the end. This crashes as per the previous example when the other variable is accessed. Changing the type assigned to orig from Foo2 (Objective-C) to Foo (Swift) make it work.

Therefore it seems unowned should not be used to refer to Objective-C classes, just Swift classes.



Beware: Despite the docs SKNode userData is optional

Pete Barber from C#, C++, Windows &amp; other ramblings

In the Swift documentation for SKNode the userData member (a dictionary) is defined as follows:

userData

A dictionary containing arbitrary data.

Declaration

SWIFT
var userData: NSMutableDictionary!

OBJECTIVE-C

@property(nonatomic, retain) NSMutableDictionary *userData

However, in Objective-C the userData member is initially nil. Given that this is the same class then it should also be in Swift and using it, e.g.

let node = SKSpriteNode(imageNamed: name)
node.userData["action"] = Action() // custom class

causes a crash:

fatal error: Can't unwrap Optional.None

This is because the it is in fact nil despite the '!' following the Swift definition. This must be a documentation bug. The correct code is:

let node = SKSpriteNode(imageNamed: name)
node.userData = NSMutableDictionary()
node.userData["action"] = Action() // custom class

XCode 5 versus XCode 6 default generated Game (Sprite Kit) project and scene sizes

Pete Barber from C#, C++, Windows &amp; other ramblings

As a way to learn about Swift I've been trying to write a simple game using Sprite Kit. My initial plan was to just allow a ball to be dragged around the screen and ensure it was constrained by the screen edges. This was a little harder than originally envisioned. This was partly because the default Game project generated by Xcode 6 is slightly different to that generated by Xcode 5 and so none of the existing Sprite Kit tutorials referred to this area.

My main issue was that I could move the ball around and when the drag finished the ball was endowed with velocity so it travelled after release and despite writing some simple code to ensure if the additional travel would take it off the screen this would bound it.

func boundPosToScene(newPos : CGPoint) -> CGPoint
{
  var retVal
  let radius = ball.size.width / 2

  if newPos.xradius < 0
  {
    retVal.xradius
  }

  if newPos.xradius > self.size.width
  {
    retVal.x = self.size.widthradius
  }

  if newPos.yradius < 0
  {
    retVal.yradius;
  }

  if newPos.yradius > self.size.height
  {
    retVal.y = self.size.heightradius
  }

  return retVal;

}

Where ball is a member variable of the class containing this method that is an instance of SKSpriteNode.

Despite this the ball kept disappearing. Reading various online articles, tutorials & StackOverflow posts there seemed to be an issue with Sprite Kit projects always starting up in landscape mode. When I added some debug to this statement (& else where), i.e.


println("view.bounds\(view.bounds), self.frame:\(self.frame), self.size:\(self.size)")

I got:

view.bounds(0.0,0.0,320.0,568.0), scene:(0.0,0.0,1024.0,768.0), scene.size:(1024.0,768.0)

OK. The view looks good but the scene is in landscape and even if orientated to portrait it's a lot larger than the actual view. But why? There were lots of posts about the landscape issues but nothing about the non-aligned size with Xcode 5. Well, a quick test by generating projects with 5 & 6 (NOTE: I'm new to Sprite Kit as well as Swift so I hadn't used it with 5) shows that the generated 'Game' Xcode 5 projects programmatically creates a scene that is sized to the view:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;
    
    // Create and configure the scene.
    SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;
    
    // Present the scene.
    [skView presentScene:scene];
}

whereas with XCode 6 it uses an SKS file (called GameScene):

override func viewDidLoad() {
  super.viewDidLoad()

  if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
    // Configure the view.
    let skView = self.view as SKView
    skView.showsFPS = true
    skView.showsNodeCount = true
            
    /* Sprite Kit applies additional optimizations to improve rendering performance */
    skView.ignoresSiblingOrder = true
            
    /* Set the scale mode to scale to fit the window */
    scene.scaleMode = .AspectFill

  }
}

Looking at the GameScene.sks:



You can see that the default scene size is 1024x768, i.e. iPad in landscape mode. Changing this to 320x576 (for iPhone 4 inch) fixes the problem.

NOTE: When making this change make sure you explicitly save the changes. Just modifying the values and building/running the project often seems to result in them being reset. I make sure I navigate away from the Size boxes before pressing Cmd-S.

Of course this is inflexible as it doesn't size to device. As I'd like my app to run on multiple device types I'm probably better of following the Xcode 5 generated code or perhaps just adding re-sizing code once the Scene has been loaded from the SKS file; as I'm not sure what else that gives me.

If you do this. In GameViewController.swift you'll also probably want to change

scene.scaleMode = .AspectFill

to

scene.scaleMode = .ResizeFill

Anyway, this difference in the generated starter apps is something to be aware of & the fact that the initial landscape startup issue reported against Xcode 5 seems to be present though possibly in a different guise. Certainty in the generated app from Xcode 5 it all works fine for me. When I added logging code to display the View and Scene size they were both reported as 320x568.

Subclassing Objective-C classes in Swift and the perils of Initializers

Pete Barber from C#, C++, Windows &amp; other ramblings

--- Begin update

1. The post below applies to Xcode 6 Beta 2. With Beta 3 & 4 the relationships between the Swift and Objective-C regarding the calling of super class initializers has been formalized.

1a. A Swift class can have multiple non-convenience initializers but in this case they must all property initialize any properties. Also, a non-convenience initializer cannot invoke another initializer, i.e. it cannot call self.init(...)

1b. When calling an Objective-C any initializer can be called but unlike what happened in Beta 2 if the initializer invoked is not the Objective-C 'designated' initializer and thus calls it this DOES NOT now result in a virtual like call to an initializer with that signature in the subclass, i.e. the main problem that led to the writing of this blog post.

2. If you want to subclass an SKSpriteNote in Beta 4 the following StackOverflow post shows how.

3. It seems that for some OS classes, in my case SpriteKit either Apple directly or some Xcode magic now provides a shim Swift wrapper of the Objective-C interface (the one for SKSpriteNode has a comment with a date of 2011 but when attempting to "show in Finder" nothing happens). As such all the initializers for SKSpriteNode are marked as convenience except for the 'designated' initializer, e.g.

class MySpriteNode : SKSpriteNode {}

3a. This is now essentially a Swift only project with the MySpriteNode now deriving from SKSpriteNode which is a Swift class. As such the Swift rules must be followed. This means that any convenience initializers in MySpriteNode can only call non-convenience initializers for MySpriteNode and these MUST in turn call a non-convenience initializers in the superclass. In the case of SKSpriteNode there is a only a single designated initializer which is:

   /**
     Designated Initializer
     Initialize a sprite with a color and the specified bounds.
     @param texture the texture to use (can be nil for colored sprite)
     @param color the color to use for tinting the sprite.
     @param size the size of the sprite in points
     */

    init(texture: SKTexture!, color: UIColor!, size: CGSize)

Therefore from a derived class it's impossible to use the super class convenience methods which is what Swift demands but is a shame as it often means re-implementing similar code in the derived class, as per the StackOverflow link.

It's not perfect by any means but it's a lot more consistent than Beta 2. I don't (yet) understand where the magic shim comes from and this is update is based on Beta 4 whereas of writing Beta 5 has just been released!

--- End update

As a way to learn Swift I decided to have a play with Sprite Kit. One of the first things I did was to create a subclass of SKSpriteNode. This has a very handy initializer:

init(imageNamed name: string) (in Swift)
-(instanceType)initWithImageNamed:(NString*)name (in Objective-C)

I then derived from this resulting in:

class Ball : SKSpriteNode
{
    init()
    {
        super.init(imageNamed: "Ball")
    }
}

and added it to my scene as follows:

var ball = Ball()
ball.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(ball)

Having successfully written similar code using SKSpriteKitNode directly:

var ball = SKSpriteNode(imageNamed: "Ball")
ball.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(ball)

I was expecting it to work. However I received the following runtime error:

fatal error: use of unimplemented initializer 'init(texture:)' for class 'Ploing.Ball'

The odd thing was that it was complaining about the lack of initializer in the Ball class. Why would calling a base class initializer result in a call back to the derived class? I wasn't sure but to work around this I decided to add the missing initializer:

init(texture: SKTexture!)
{
    super.init(texture: texture)
}

Having duly done this I then got the next error:

fatal error: use of unimplemented initializer 'init(texture:color:size:)' for class 'Ploing.Ball'

Ok, same process add that one to the Ball class. 

init(texture texture: SKTexture!, color color: UIColor!, size size: CGSize)
{
    super.init(texture: texture, color: color, size: size)
}

That time it worked but I was puzzled as to why. What seems to be happening is that the derived class is calling the non-designated initializer in the super class which is then calling the designated (or another non-designated one in between). However, when this initializer is called rather than calling the super class implementation it calls one in the derived class, whether it exists or not. In the case of Ball they didn't hence the error.

It turns out that in the middle of the the Initialization section of the The Swift Programming Language there is the following:

Initializer Inheritance and Overriding
Unlike subclasses in Objective-C, Swift subclasses do not not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is automatically inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized.
If you want your custom subclass to present one or more of the same initializers as its superclass—perhaps to perform some customization during initialization—you can provide an overriding implementation of the same initializer within your custom subclass.
This explains it. Basically, in Swift, initialization methods work like virtual functions in fact super virtual functions. If a super class initializer is invoked and that in turns calls another initializer (designated or not) then it forwards the call to the derived class. The upshot of this seems to be that for any derived class in Swift it would need to re-implement all of the super classes initializers or at least any which may be invoked from the the other initializers.

Time for some experiments

I therefore set out to confirm this with a simple Swift example:

class Foo
{
    var one: Int;
    var two: Int;

    init(value value:Int)
    {
        self.init(value: value, AndAnother:7)
    }

    init(value value:Int, AndAnother value1:Int)
    {
        one = value;
        two = value1;
    }

    func print()
    {
        println("One:\(one), Two:\(two)")
    }
}

class Bar : Foo
{
    init()
    {
        super.init(value:1);
    }
}

let bar = Bar()
bar.print()

This wouldn't compile. 

Designated initializer for 'Foo' cannot delegate (with 'self.init'); did you mean this to be a convenience initializer?
Must call a designated initializer of the superclass 'Foo'

Whereas in Objective-C the designated initializer is effectively advisory, in Swift it's enforced. If a initializer isn't marked with the convenience  keyword then it seems (at least during compilation) all initializers are treated as being the designated initializor and not at the same time. In this case the compilation failed as there was no designated initializer for Bar.init to call and as Foo.init(value value:Int) wasn't marked as a connivence initializer it was assumed to the designated one and is thus forbidden from calling another initializer in its own class; somewhat paradoxically.

These two rules prevent issues that occur with Objective-C's advisory initializer. All but the designated initializer must be prefixed with the convenience keyword. Secondly this is the only initializer permitted to call the super class initializer meaning all the the convenience initializers can only (cross) call other convenience or the designated initializer for their class. Following these rules gives a working example:

class Foo
{
    var one: Int;
    var two: Int;

    convenience init(value value:Int)
    {
        self.init(value: value, AndAnother:7)
    }

    init(value value:Int, AndAnother value1:Int)
    {
        one = value;
        two = value1;
    }

    func print()
    {
        println("One:\(one), Two:\(two)")
    }
}

class Bar : Foo
{
    init()
    {
        super.init(value: 7, AndAnother: 8)
    }
}

let bar = Bar()
bar.print()

Which gives the results:

One:7, Two:8

It also completely bypasses the convenience method of the superclass rendering it useless for calling from a derived class.

As for explaining the original problem this doesn't help either as the new rules prevent the problem. Herein lies the clue though. It suggests the problem is not with Swift classes subclassing other Swift classes but when a Swift class subclasses an Objective-C class.

Subclassing Objective-C from Swift

Time for another experiment but this time using a base class written in Objective-C:

Base.h

@interface Base : NSObject

-(id)initWithValue:(NSInteger) value;
-(id)initWithValue:(NSInteger) value AndAnother:(NSInteger) value1;
-(void)print;

@end

Base.m

#import "Base.h"

@interface Base ()
@property NSInteger one;
@property NSInteger two;
@end

@implementation Base

-(id)initWithValue:(NSInteger) value
{
    return [self initWithValue:value AndAnother:2];
}

-(id)initWithValue:(NSInteger) value AndAnother:(NSInteger) value1
{
    if ([super init])
    {
        self.one = value;
        self.two = value1;
    }
    
    return self;
}

-(void)print
{
    NSLog(@"One:%d, Two:%d", (int)_one, (int)_two);
}

@end

main.swift

class Baz : Base
{
    init()
    {
        super.init(value: 7)
    }

    init(value value:Int, AndAnother value1:Int)
    {
        super.init(value: value, andAnother: value1);
    }
}

var baz = Baz()
baz.print()

Looking at Base it's obvious that the desginated initializer is initWithValue:(int)value AndAnother:(int)value1 whereas Baz is calling a 'convenience' initializer. This compiles happily but when run gives the following error:

fatal error: use of unimplemented initializer 'init(value:andAnother:)' for class 'Test.Baz'

This is the same type of error as in the original SKSpriteNote sample. Here, Baz's initializer is successfully invoking the Base.initWihValue:(int) value but when it invokes Base's designated initializer this is when the super virtual functionality of the initializers comes into play and an attempt is made to call this non-existent method on Baz. This is easily fixed by adding that method such as it calls the super class method as in:

class Baz : Base
{
    init()
    {
        super.init(value: 7)
    }

    init(value value:Int, AndAnother value1:Int)
    {
        super.init(value: value, andAnother: value1);
    }
}

Giving the result:

2014-06-07 17:40:18.632 Test[47394:303] One:7, Two:2

Alternatively and staying true to the Swift way the parameterless intializer which is obviously a convenience initializer should be marked as such. This then causes a compilation failure as this is now forbidden from calling the super class initialzer and instead must make a cross call to the designated initializer giving the following code:

class Baz : Base
{
    convenience init()
    {
        self.init(value: 7, AndAnother: 8)
    }

    init(value value:Int, AndAnother value1:Int)
    {
        super.init(value: value, andAnother: value1);
    }
}

Which gives the result:

2014-06-07 17:40:46.345 Test[47407:303] One:7, Two:8

This differs from the previous version as the connivence initializer now calls the designated one within Baz meaning the  -(id)initWithValue:(NSInteger) value is never called which is why the second value is nolonger 2.

Conclusion

Whilst this explains the behaviour I was seeing when subclassing SKSpriteNode and by providing a mirror of its initializers without marking any as convenience it solves the problem of using the convenient init(imageNamed name: string) method it doesn't do so particularly elegantly nor in a fully Swift style; as it leaves the class with a set of initializers none of which are marked convenience.

A designated initializer could be specified by marking all but the init(texture texture: SKTexture!, color color: UIColor!, size size: CGSize) method as convenience and having them cross call this one. However this would prevent the direct calling of init(imageNamed name: string) which is a lot more convenient than the other methods. 

Ironically, whilst Swift formalizes the designated initializer concept and it looks like it will work well for pure Swift code it can be somewhat inconvenient when subclassing Objective-C classes.

P.S. For those of us who have trouble spelling the keyword convenience is far from convenient. A keywoard to mark the designated initializer may well have been more convenient and probably easier to spell! 

Keyboard configuration for Windows’ developers on OS X (& also IntelliJ)

Pete Barber from C#, C++, Windows &amp; other ramblings

Recently I've been doing some ActionScript programming. Rather than target a Flash Player app. I've been using ActionScript in combination with Adobe AIR in order to create an iOS app. This has meant I've been spending time in OS X and using IntelliJ with the the ActionScript/Flex/AIR plugin as my IDE.

Most of my previous work has been done on UNIX (so command lines & vi) and Windows. In particular I depend on the various Windows & Visual Studio editor key combinations plus the Insert, Delete, Home & End keys. For starters this means I use a PC keyboard with the iMac rather than the Apple keyboard as it lacks these keys; I'm also based in the UK so I use a British PC keyboard.

In addition to these keys I wanted the following combos to be available across all of OS X and any apps.
  • Alt-Tab to cycle through apps.
  • Ctrl-F for find.
  • Ctrl-S for save current document (I habitually press this whilst editing).
  • Ctrl-C & Ctrl-V for copy & paste.
  • Ctrl-Z for undo.
  • Obtain the correct behaviour for the '\|' key and the '`¬' key. They were swapped initially.
  • '@' & '"' correctly mapped.
Additionally, I wanted these combos to be available in IntelliJ:
  • Ctrl-Left Arrow & Ctrl-Right Arrow to move the previous/next word respectively
    • Plus their selected text equivalents.
  • Ctrl-Home/Ctrl-End to move to the top/bottom of the document being edited.
This post is a description of what I installed & configured to allow to
achieve this.

Configuring a British PC keyboard

The first step was to tell OS X I was using a PC keyboard, specifically a British one. This is achieved through the System Preferences->Keyboard->Input Sources.



Here new input sources can be added by clicking the '+'. I added 'British - PC'. Adding doesn't mean it will be used though. For this also check the 'Show Input menu in menu bar' option. This adds a country flag and the name of the input source. Clicking on this allows the input source to be changed. If you swap between a PC keyboard and the iMac keyboard (which I do from time to time) this is an easy way to swap.



What all this gives you is the '"' and '@' keys in the right place. Otherwise they're transposed. Note: backslash and backquote remain transposed.

Windows' key combos

The second step was obtaining the Windows' key combos. This requires mapping the Windows' combos to the corresponding OS X combos whilst preventing the Windows' combos being interpreted as something else. After some searching it seemed like the preferred solution to this is using a 3rd party program called KeyRemap4MacBook. According to various reviews it does the job well but configuring it, especially creating your own mappings is complicated. The former being down to the UI and the latter to the XML format. All these things are true but once you've got used to it, like a lot of things it's nowhere near as daunting as it first seems; and the document is very good too. Part of the motivation for this post is to record the configuration & steps for my benefit should I need to do it again.

KeyRemap4MacBook comes with a number of canned mappings. In addition to mapping across the board they can be limited to include or exclude a specific set of apps. In particular I make use of a set of pre-defined mappings from the 'For PC Users' section which won't be applied in VMs (generally running Windows, especially useful when running Windows 8 in Parallels from the Bootcamp partition) and terminals.

As I still use the Apply keyboard from time to time when I want to do very Apple-ly stuff I have the 'Don't remap  Apple's keyboards' option enabled.

What I use

The canned mappings I use from 'For PC Users' section are:
  • Use PC Style Copy/Paste
  • Use PC Style Undo
  • Use PC Style Save
  • Use PC Style Find
These can easily be seen these in KeyRemap4MacBook using the 'show enabled only' (from the many definitions) option:



Without doing very little work this meets the majority of my needs. In addition to the 'For PC Users' and 'General' section you may also notice the three re-mappings at the start. These are custom mappings I had to create. I'm not going to explain the XML format as this is available from the documentation. Instead, here are my custom mappings.

<?xml version="1.0"?>
<root>
 <appdef>
  <appname>INTELLIJ</appname>
  <equal>com.jetbrains.intellij</equal>
 </appdef>

 <replacementdef>
  <replacementname>MY_IGNORE_APPS</replacementname>
  <replacementvalue>VIRTUALMACHINE, TERMINAL, REMOTEDESKTOPCONNECTION, VNC, INTELLIJ</replacementvalue>
 </replacementdef>

 <replacementdef>
  <replacementname>MY_IGNORE_APPS_APPENIDX</replacementname>
  <replacementvalue>(Except in Virtual Machine, Terminal, RDC, VNC and IntelliJ)</replacementvalue>
 </replacementdef>


 <item>
  <name>Use PC style alt-TAB for application switching</name>
  <appendix>{{ MY_IGNORE_APPS_APPENIDX }}</appendix>
  <identifier>private.swap_alt-tab_and_cmd-tab</identifier>
  <not>{{ MY_IGNORE_APPS }}</not>
  <autogen>__KeyToKey__ KeyCode::TAB, ModifierFlag::OPTION_L, KeyCode::TAB, ModifierFlag::COMMAND_L</autogen>
 </item>

 <item>
  <name>Swap backslash and backquote for British PC keyboard</name>
  <identifier>private.swap_backslash_and_quote_for_britishpc</identifier>
  <autogen>__KeyToKey__ KeyCode::DANISH_DOLLAR, KeyCode::BACKQUOTE</autogen>
  <autogen>__KeyToKey__ KeyCode::BACKQUOTE, KeyCode::DANISH_DOLLAR</autogen>
 </item>

 <item>
  <name>Use PC Ctrl-Home/End to move to top/bottom of document</name>
  <appendix>{{ MY_IGNORE_APPS_APPENIDX }}</appendix>
  <identifier>private.use_PC_ctrl-home/end</identifier>
  <not>{{ MY_IGNORE_APPS }}</not>
  <autogen>__KeyToKey__ KeyCode::HOME, ModifierFlag::CONTROL_L, KeyCode::CURSOR_UP, ModifierFlag::COMMAND_L</autogen>
  <autogen>__KeyToKey__ KeyCode::HOME, ModifierFlag::CONTROL_R, KeyCode::CURSOR_UP, ModifierFlag::COMMAND_L</autogen>
  <autogen>__KeyToKey__ KeyCode::END, ModifierFlag::CONTROL_L, KeyCode::CURSOR_DOWN, ModifierFlag::COMMAND_L</autogen>
  <autogen>__KeyToKey__ KeyCode::END, ModifierFlag::CONTROL_R, KeyCode::CURSOR_DOWN, ModifierFlag::COMMAND_L</autogen>
 </item>

</root>

I didn't want these mappings other than swapping backslash and backquote to be applied in various apps. i.e. VMs, VNC & RDC (where Windows is running anyway) and Terminal where it interferes with bash. To enable this I used the <not> element giving a list of excluded apps. along with using the appendix element to state this in the description.

Rather than copy the list of apps. and description I used KeyRemap4MacBook's replacement macro feature. There is a list of builtin apps. that can be referred too but I also looked at the XML file from the source that contains the 'For PC Users' mapping.

The _L & _R refer to keys which appear twice: on the left & right side of the keyboard.

The format allows multiple mappings to be grouped. These don't have to be similar but this the intention, i.e. all the ctrl-home/end mappings are together. Each <autogen> entry is a separate mapping but they are enabled/disabled collectively.

The format isn't too bad. The weird thing from an XML perspective is the <autogen> element. This is source combo followed by combo to generate instead separated by a comma. I think it would be easier to understand if this element were broken down into child elements with say <to> and <from> elements.

This private.xml is also available as a GIST.

IntelliJ

IntelliJ complicates things slightly as it provides its own key-mapping functionality similar to that of KeyRemap4MacBook but solely for itself. This means that there can be a conflict with KeyRemap4MacBook.

I'm writing this a while after I originally implemented it. In fact part of the reason I'm writing this post at all is so I have a record of what's required. Since getting this working it looks like I've changed my IntelliJ Keymap (from Preferences). Originally it was set to 'Mac OS X' but is now set to 'Default'.

When is was set to 'Mac OS X' the KeyRemap4MacBook mappings worked well except that Ctrl-Home/End wouldn't work. This is because that combination is mapped to something else. Additionally the 'Mac OS X' mappings don't provide support for Ctrl-Left/Right-Arrow for hoping back and forth over words. My initial solution to this was to modify (by taking a copy) the 'Mac OS X' mapping:
  • Change 'Move Caret to Next Word' from 'alt ->' to 'ctrl->'.
  • Change 'Move Caret to Previous Word' from 'alt <-' to 'ctrl <-'.
  • Change 'Move Caret to Next Word with Selection' from 'alt shift ->' to 'ctrl shift ->'.
  • Change 'Move Caret to Previous Word with Selection' from 'alt shift <-' to 'ctrl shift <-'.
  • Change 'Move Caret to Text End' from 'cmd end' to 'ctrl end'.
  • Change 'Move Caret to Text Start' from 'cmd home' to 'ctrl home'.
However, it seems that the 'Default' key mappings are as per-Windows but when KeyRemap4MacBook is running they all conflict. In fact I may have missed this completely when initially figuring this out.

Therefore the far easier solution is to select the 'Default' IntelliJ mapping and using KeyRemap4MacBook make it aware of IntelliJ and exclude it from key re-mapping as per the other applications. This is the purpose of the appdef section in private.xml. KeyRemap4MacBook doesn't need definitions for other excluded apps. as these are built-in.

The mappings are not perfect. IntelliJ is great but this is now down to IntelliJ's mapping and having excluded it from KeyRemap4MacBook mapping. I still miss Ctrl-Left/Right-Arrow and Ctrl-Home/End in other apps. but hopefully this should just be a case of defining more mappings and the Ctrl-Z (undo) mapping effectiveness seems to vary.