With the addition of error handling to Swift 2, we got a way to deal with errors with the nice try/catch exception handling syntax from many languages,
but without the associated cost of stack unwinding.
As with anything new, some questions come to mind. How do we test methods that can throw errors? In Objective-C we had a few XCTest assert macros to help with this, like XCTAssertThrows. Swift 1 does not support exceptions, so these macros,
which get translated to Swift functions, are absent from the XCTest framework in Swift. I was expecting to find them in the Swift 2 version of the framework,
but they’re missing.
So the first thing that comes to mind is to just wrap the asserts into do/catch blocks.
And Xcode complains: “Call can throw, but it is executed in a non-throwing autoclosure.”
Assert macros use the @autoclosure attribute, so everything you pass to them becomes a closure. A non-throwing closure.
So you need to first try to get the result and pass just that.
This works. But, we hate repetition, don’t we?
Good. We can check if a method throws or not. But some methods return things and we would like to compare these things to other things.
Ok, that’s equality. But what about >, < and membership checks? Let’s add a validator closure then.
I spent the past few weeks digging into Swift while working on PSPDFKit. Today I was trying to enumerate a directory recursively.
I resorted to NSFileManager and its method enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:.
It returns an NSDirectoryEnumerator object which supports NSFastEnumeration. That means you can use the for-in loop in Objective-C.
Without thinking, I wrote a for-in loop in Swift. Not so fast.
Type ‘NSDirectoryEnumerator’ does not conform to protocol ‘SequenceType’.
Apple should have supported this. So I spent some time browsing trough the Swift headers and with the help of generics
I wrote a custom substruct (?) that conforms to the GeneratorType protocol and can be initialized with an object of type NSEnumerator.
In my case I was dealing with NSDirectoryEnumerator which iterates trough NSURL objects. So I wrote an extension to extend it with support for SequenceType.
The nice thing is that using for-in in Swift now provides you with NSURL objects!
This generic can now be used to extend any kind of NSEnumerator so you can enjoy clean for-in loops in Swift.
Like just about any other iOS developer, I was caught completely by surprise when Apple announced Swift.
I was expecting modest improvements to Objective-C, maybe even an Objective-C 3.0 release, but nothing as wild as a new language.
But I got excited, really excited, when I watched the state of the union video (no, I was not one of the lucky WWDC ticket lottery winners).
I started reading the Swift book right away. “I’m going to read this trough first,” I said to myself, “and hack later.”
Well, guess what? I started hacking after the introduction chapter. After I alternated between reading and hacking for a while,
I needed a project to work on. And so I chose to port JSImageLoader to Swift and see how it goes.
Update: See the updated code for Swift 1.2 at the bottom of this post.
The first thing I did was to outline classes and add properties. This was easy. The second step was to implement initializers.
Trivial, if it’s not a singleton. My first idea was to write it the exact same way I would do it in Objective-C, using dispatch_once.
I came across a major difference right away; static variables can only be declared inside enums and structs.
Luckily structs can be defined inside methods and, like in this case, property getters. So I came up with the code below:
Then I read more of the book, watched some more WWDC videos and browsed more of the Apple developer forums.
Then I found this post by Joe Groff (@jckarter) who works on the Swift compiler:
Global and static properties are already dispatch_once’d, so there’s really no need for this. You can simply define the singleton instance as a global variable or static let property of a struct.
This is getting better and better! He says there are two options, one with a global variable and one with a static let as the property of a struct.
I’m not a fan of polluting the global space too much so I chose the latter:
While I do agree that this could be made even nicer by having a private static class let property,
I think that it’s great that global variables and static let properties are wrapped in dispatch_once.
I’m sticking to this implementation for now.
Update: Swift 1.2 added support for static properties on classes so now a singleton can be simply initialized when declaring the property. No more embedded structs!
I thought drawing gradients on iOS is easy. Well, until our designer gave me this:
I went on and implemented the drawRect: method on a custom UIView. I used CGGradient and wrote the drawing code. I ran the project in the simulator and noticed that the gradient was quite different. Ran on the device, same thing.
I played around with different colors and their positions but nothing turned out like the Photoshop gradient. After some head scratching I figured it must be something to do with how the colors are interpolated. CGGradient uses a linear interpolation of colors.
What I need is a slope (ease-in ease-out for you familiar with animation timings) function and apply that to each color component. I actually cared only about transparency so I had to only adjust the alpha channel.
I needed this:
Looking at the documentation, CGGradient doesn’t support custom color interpolation. There is something called CGShading that does. The documentation is not absolutely clear on how to use it, but after some experimenting I came up with a solution, which is presented below. There is also a sample project available on GitHub so you can compare CGGradient and CGShading.
Most programmers are familiar with the ternary operator ?: that is available in C and most other languages.
But what some people may not know is that you can also use this operator with only two arguments.
Instead of writing
you can do this
The other thing some of you may not know is that when defining a const you can’t use an if statement to define it based on a condition, but you can do this: