Archive for the ‘Swift’ Category

Four Lessons from Circle Intersection

Yesterday, a fairly simple discussion of circle intersection came up: how do you subtract one circle from another to form a “cut out” Bezier path. This allows you to add an affordance or decoration to a circle, but add some space between the primary figure and the secondary bubble.

Exploring this question provided some interesting lessons that I thought I’d share in a quick post.

Embrace Core Graphics Types

When working with basic geometry, redirect your mathematics to Core Graphics. Bezier paths, points, rects, and other core geometric features use CGFloat, not Double. You minimize your pain by extending CGFloat as needed to address common geometric concerns such as exponentiation or mathematical constants rather than switching back and forth between Swift.Double and CGFloat:

/// Exponentiation operator
infix operator **: HighPrecedence

extension CGFloat {
    /// Returns base ^^ exp
    /// - parameter base: the base value
    /// - parameter exp: the exponentiation value
    public static func **(base: CGFloat, exp: CGFloat) -> CGFloat {
        return CGFloat(pow(Double(base), Double(exp)))
    }
    
    /// Tau
    public static var tau = CGFloat(Double.pi * 2.0)
}

Construct utility types

It helps to think about the kinds of types that will support your geometric challenge. For this example, I built two new types: a line segment (2 end points) and a circle (a center and a radius). Bringing these under the Core Graphics umbrella unified my representations with the tools they need to express their geometry:

/// 2-point representation of line segment
public struct Segment {
    public let (p1, p2): (CGPoint, CGPoint)
    var dx: CGFloat { return p2.x - p1.x }
    var dy: CGFloat { return p2.y - p1.y }
    public var length: CGFloat { 
        return sqrt(dx ** 2 + dy ** 2) 
    }
}

/// Center/Radius circle representation
public struct Circle {
    public let center: CGPoint
    public let radius: CGFloat
}

Being Core Graphic native enables you to leverage constructors using the appropriate types. For example, my circle can construct a path for drawing to a UIKit-compatible context:

/// Returns a Bezier path sweeping between two angles
public func path(from startAngle: CGFloat = 0, to endAngle: CGFloat = CGFloat.tau, 
    clockwise: Bool = true) -> UIBezierPath {
    return UIBezierPath(arcCenter: center, radius: radius,
                        startAngle: startAngle, endAngle: endAngle,
                        clockwise: clockwise)
}

This path method allows me to express each circle as a path, hiding the details of a UIBezierPath constructor. When I want to throw up a visual reference point, I just construct a circle at that point and fill it:

let p1 = Circle(center: segment.p1, radius: 2.5)
p1.path().fill()

Very handy.

Let the math be the math

When you’re working with standard algorithms, it helps to step back from your standard Swift key paths and use the terms of art you’re translating into code. For example, it can be convenient to break down some basic Swift into algorithm-specific terms:

let (x1, y1, r1) = (self.center.x, self.center.y, self.radius)
let (x2, y2, r2) = (other.center.x, other.center.y, other.radius)

It may not be “Swifty”, but doing so leads to easier inspection when comparing your implementation to the how-to reference in a book or paper.

Draw It

Playgrounds are great when it comes to testing drawing algorithms because you can use real data and get immediate results to see whether your assumptions and expectations are properly met.

In this example, the first two circles intersect, allowing the construction of the “chunked out” major circle and a condensed minor circle. The original circles are outlined and the two red points indicate the overlap points.

The second pair does not intersect, so it’s left simply as two outlines.

If you want to play around with this rough implementation, I left the code for this over at github. Feel free to expand or improve upon my approach, as it was very much an off-hand “here’s more or less how you can do this” exercise.

Using memory addresses for hashing

Today, Tim talks about conforming reference types to a hashable program. This enables you to use specific class instances for set elements and dictionary keys. Read on to learn more and don’t forget to follow Tim on Twitter.

For reference types, it often makes sense to consider two variables to be equal when they reference the same address in memory. Say you have a UIView instance visible on screen, for example. You could create a copy of that view with the exact same properties (size, position, background color, etc.) but modifying the copy will obviously have no visible effect.

Testing whether two variables refer to the same instance is easy using the identity operators (=== and !==). However, this does not allow you to put instances of an arbitrary class in a Set, or use them as keys in a Dictionary, since that requires conforming to the Hashable protocol.

Interestingly, classes that inherit from NSObject don’t face this problem: NSObject implements == and hashValue, the two requirements of the Hashable protocol, using isEqual(_:) and hash respectively. The default implementation of isEqual uses pointer equality, and the default value for hash is the instance’s memory address.

In order to use memory addresses for hashing without inheriting from NSObject (which you shouldn’t), you can use the ObjectIdentifier type that is part of the Swift standard library:

final class Foo: Hashable {
    static func == (left: Foo, right: Foo) -> Bool {
        return left === right
    }
    
    var hashValue: Int {
        return ObjectIdentifier(self).hashValue
    }
}

Note that an instance’s memory address can (and will) change across different executions of the program, but that’s fine: the Hashable protocol doesn’t require hash values to be stable across different executions.

Of course, you can put this code in a protocol extension to make it reusable:

protocol PointerHashable: class, Hashable {}

extension PointerHashable {
    static func == (left: Self, right: Self) -> Bool {
        return left === right
    }
    
    var hashValue: Int {
        return ObjectIdentifier(self).hashValue
    }
}

Now, all it takes for a custom class to be usable as set elements and dictionary keys is conformance to PointerHashable. But be careful: the Hashable protocol requires that two instances that are considered equal with == also have the same hash value, so if you are implementing == using custom logic, you will need a custom hashValue implementation as well.

Erica Knows Nothing About Kotlin: Installing and using Kotlin from Xcode

Andy Wilkinson wanted some useful tips for Kotlin in the style of my normal blog. I know nothing about Kotlin other than it’s vaguely Swifty and has a little too much Java in it for my decaf tastes. Nonetheless, I decided to oblige.

Here’s what I discovered.

Install Kotlin

Installation couldn’t be simpler. I used brew: brew install kotlin, which installed a copy to /usr/local/bin/kotlin on my first try. Woo!

Say “Hello World”

You run the Kotlin REPL with kotlinc-jvm, which I did not guess on my first try and had to hunt around doing web searches to discover:

Next, I tried to create an app. Once again I discovered that Kotlin is a little less straightforward than Swift in this regard.

Notice that you have to call kotlinc, the command line compiler, not kotlin. Then you can run the  736709-byte large jar results with (ew) java.

Unfortunately, it’s not as simple as one might hope to create a straightforward script:

However if you rename the file from hello2.kt to hello2.kts, you can run it as a command-line script:

Whee.

Hop into Xcode

Create a new Cross-platform Xcode project: File > New > Project > Cross-platform > External Build System > Next. Enter a name, and edit the build tool to kotlinc. Click Next. Navigate to a save location and click Create.

Choose File > New > macOS > Other > Empty. Click Next. Name the file HelloWorld.kts. (See the kts extension? This allows it to be run as a script.)

Edit your Run scheme (Scheme > Edit Scheme or Command-<). Choose the Info tab, select Other from the Executable pop-up list.

Type a forward slash, then continue to navigate to /usr/local/bin. Select kotlinc, uncheck Debug executable, and then click Close.

Next choose the Arguments tab and edit the arguments passed on launch to include both the -script flag and the source file:

You’re now ready to run:

Do something interesting

Now that you have the basics all ready to play with, create a slightly more interesting testing environment. For example, pull up Project Euler and challenge yourself to a few of their ideas:

That Kotlin “Feeling”

As when I played around with Python, I was surprised at Kotlin’s familiarity.

  • The println commands felt quaint and old fashioned like Swift 1.
  • The cascading dot sequence (which I cut and pasted for the second result, and Xcode didn’t automatically indent) felt as fresh as modern Swift. I also felt pretty confident in my overall Swift-influenced style despite jumping into an entirely new language.
  • Extending Int with the divisibleBy function was a little weird and I deliberately used the = syntax to define my function rather than a more familiar brace and return, just so I could say I tried to be more authentically kotlinny.
  • The two dot range did catch me but it was an easy fix from three dots to two.
  • I quite liked using $-delimited variable names compared to Swift’s \() insertion sequence.

Given that other than a few math functions and hello world, this post contains all my Kotlin code to date, I don’t have much more to add about the language similarities and differences, but let me know if you’d be interested in reading more about “Erica learns Kotlin”. Otherwise, I’ll get back to doing other things during this extremely dead week before WWDC starts.

Tests that don’t crash

Give a big hi to Tim V! He’ll be posting here when a topic inspires him and today, he’s going to talk about how to write tests that fail gracefully.

Most people that have been writing Swift code for a while try to limit their usage of optional force unwraps and try! as much as possible. Test code, on the other hand, is often still littered with unsafe code. It’s true that crashes in tests aren’t nearly as undesirable as in production code, but it’s fairly straight-forward to write tests that fail gracefully when an unexpected nil is encountered, or when an error is thrown unexpectedly.

Consider the following unit tests:

class Tests: XCTestCase {
    func testFoo() {
        let value = try! foo()
        XCTAssertEqual(value, 5)
    }
    
    func testBar() {
        let value = bar()!
        XCTAssertEqual(value, "bar")
    }
}

What a lot of people don’t seem to know is that individual tests can be marked with throws to automatically handle thrown errors:

func testFoo() throws {
    let value = try foo()
    XCTAssertEqual(value, 5)
}

Much better. To write testBar in a safer way, we’ll need to throw an error when the output of bar is nil. We could declare a separate error for each optional value we want to unwrap in one of our tests, but that requires writing a lot of extra code. Instead, we can throw a more general Optional.Error.unexpectedNil each time an unexpected nil value is encountered:

extension Optional {
    enum Error: Swift.Error {
        case unexpectedNil
    }
    
    func unwrap() throws -> Wrapped {
        guard let value = self else { throw Error.unexpectedNil }
        return value
    }
}

Note: Swift 3.0 and below does not support nesting types inside a generic type, so if you’re not yet using Swift 3.1, you’ll have to declare a separate enum OptionalError instead.

Now we can rewrite testBar as follows:

func testBar() throws {
    let value = try bar().unwrap()
    XCTAssertEqual(value, "bar")
}

After these changes, whenever a test would normally crash, it now simply fails. And as a bonus, all tests are guaranteed to be executed, where previously a single crash would prevent the remaining tests from being run.

5 Easy Dispatch Tricks

Swift Dispatch offers a great way to schedule and control concurrent code. Here are five easy ways to improve your Dispatch experience.

1. Adding Seconds

Swift makes it easy to fetch the current time as DispatchTime.

let timeNow = DispatchTime.now()

You can easily add seconds to now (in Double increments) using the + operator. As you can see from its signature, the RHS of the + operator expects a Double value of seconds.

Here are a couple of examples that show how easy it is to do this:

let timeInFive = DispatchTime.now() + 5
let timeInSevenAndHalf: DispatchTime = .now() + 7.5

DispatchTime also supports the minus operator, although subtraction is rarely used in dispatch:

public func -(time: DispatchTime, seconds: Double) -> DispatchTime

2. Adding unit time

DispatchTimeInterval offers handy units for microseconds, milliseconds, nanoseconds, and seconds. They all take integer arguments:

For example, you might dispatch five print commands, each offset by an increasing number of seconds:

(1 ... 5).forEach {
    DispatchQueue.main.asyncAfter(
        deadline: .now() + .seconds($0)) {
        print("Hi there!")
    }
}

This approach works by mixing and matching DispatchTime and DispatchTimeInterval math. These operators, too, are baked into Swift:

public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
public func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime

This version is arguably more readable and maintainable than the raw + 5 from trick #1:

let timeInFive = DispatchTime.now() + .seconds(5)

3. Going Floating Point with Dispatch Time Intervals

DispatchTimeInterval case initializers are limited to integer arguments. You can extend the type to add support for double values, returning a nanosecond instance with the equivalent value for a Double number of seconds:

// Built-in enumeration
public enum DispatchTimeInterval {
 case seconds(Int)
 case milliseconds(Int)
 case microseconds(Int)
 case nanoseconds(Int)
}

// Custom factory using a `Double` value
extension DispatchTimeInterval {
    public static func seconds(_ amount: Double) -> DispatchTimeInterval {
        let delay = Double(NSEC_PER_SEC) * amount
        return DispatchTimeInterval.nanoseconds(Int(delay))
    }
}

Like the earlier use of DispatchTimeInterval this convenience constructor improves code readability while bypasssing Int-only case initializers:

let timeInEightAndHalf: DispatchTime = .now() + .seconds(8.5)

4. Async Forwards

Although DispatchTime math is convenient, it’s super-common to schedule code with respect to the current time. Why not let DispatchTime do the heavy lifting for you? Instead of saying .now() + some interval, consider extending DispatchTime to  incorporate now into the call. Here’s an example that introduces a secondsFromNow(_:) dispatch time:

extension DispatchTime {
    public static func secondsFromNow(_ amount: Double) -> DispatchTime {
        return DispatchTime.now() + amount
    }
}

stride(from: 1.0, through: 5.0, by: 1.0).forEach {
    DispatchQueue.main.asyncAfter(deadline: .secondsFromNow($0)) {
        print("Hi there!")
    }
}

5. Testing in Playgrounds

When working with dispatch in Playgrounds, ensure that execution  continues until your work is done. Use PlaygroundPage‘s indefinite execution and halting to control that work.

import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10)) {
    print("Ending Execution")
    PlaygroundPage.current.finishExecution()
}

Got any other favorite dispatch tricks? See something I need to fix? Drop me a comment, a tweet, or an email and let me know.

Update:

Like this post? Consider buying a book. Thank you!

Randomness and Portability

If you’ve written cross-platform code between Apple and Linux, you may have run into the “missing arc4random” issue. Part of BSD, and therefore automatically distributed with Darwinarc4random uses “the key stream generator employed by the arc4 cipher, which uses 8*8 8 bit S-Boxes”

On Linux, you can revert back to rand()/random() using conditional compilation but that’s not a great solution for anyone looking for quality pseudo-randomness. Matt Gallagher has a lovely write-up about native Swift RNGs at Cocoa with Love, and links to his implementation over at the CwlUtils repository.

Jens Persson, on the swift-users list, offers this native Swift generator,  a “stripped down version” of Xoroshiro128+ PRNG as well.

Xcode Autocomplete Frustrations

A year after it debuted, Xcode’s enhanced autocomplete features continue to struggle with overly liberal matches:

In this example, several of the matching text results display few commonalities with my search phrase . There’s really no reason that “fatale” should match CFDataGetLength(theData: CFData!).

It shouldn’t be hard to create heuristics that count the number of matched chunks, their distance from each other, to build a score related to whether the match is chunky (a good thing for keywords) and singular (another good thing for discerning developer intent).

Successful autocompletion promotes good matches and discards inappropriate ones. “upper” should score high on CFStringUppercase and low on CGScreenUpdateOperation and CSSMERR_TP_INVALID_CERTGROUP_POINTER.

That’s not the only problem with autocomplete. Image literal completion is a big problem. Xcode often prioritizes images over code APIs. When starting to type “picker”, Xcode should not suggest “picture-of-lovely-cat”. Here are some real world examples of this issue:

One developer told me that while typing in for closures, that eighty percent of the time, he gets a random autocompleted image literal instead of the keyword he’s shooting for:

Surely, this is an obvious place to introduce autocomplete preferences that allow you to exclude literals from the API list. The auto complete for image literals should act more like colors, offering an Image Literal entry point to a image picker instead of clogging the API name space:

It would certainly get rid of those inappropriate in matches.

Thanks Olivier Halligon, Andrew Campoli, and everyone else who gave me feedback and direction for this post.

Fun with Unicode Names

I don’t use Unicode all that often but I tend to use the character picker copypasta or hex codes when I do:

var ghoti = "🐟" // from character picker
print(ghoti) // 🐟
ghoti = String(UnicodeScalar(0x1F41F)!)
print(ghoti) // 🐟

Cocoa also supports loading unicode characters by name using the \N{UNICODE CHARACTER NAME} escape sequence. You can use patterns to construct unicode characters as in the following example:

// Make sure to escape the backslash with a second
// backslash to allow proper string construction
"\\N{FISH}"
   .applyingTransform(StringTransform.toUnicodeName, 
        reverse: true) // 🐟
let constructed = "I want to eat a \\N{FISH} sandwich"
   .applyingTransform(StringTransform.toUnicodeName,
        reverse: true)
print(constructed!) // "I want to eat a 🐟 sandwich"

This is a reverse transform, in that it converts from escaped names to the symbol it represents. The forward transform takes a string and inserts name escape sequences in place of unicode characters:

let transformed = "🐶🐮💩"
    .applyingTransform(StringTransform.toUnicodeName, 
    reverse: false)
// \N{DOG FACE}\N{COW FACE}\N{PILE OF POO}

Unicode escapes are also usable in Cocoa regex matching. This example searches for the little blue fish in a string, printing out the results from that point:

let fishPattern = "\\N{FISH}"
let regex = try! NSRegularExpression(pattern: fishPattern, options: [])

let string = "I wish I had a 🐟 to eat"

// You have to use Cocoa-style ranges. Ugh.
let range = NSRange(location: 0, length: string.characters.count)

// There's a fair degree of turbulence between 
// the Cocoa API and Swift here, especially with
// the Boolean stop pointer
regex.enumerateMatches(in: string, options: [], range: range) {
    (result, flags, stopBoolPtr) in
    guard let result = result
        else { print("Missing text checking result"); return }
    let substring = string.substring(from: 
        string.index(string.startIndex, offsetBy: result.range.location))
    print(substring) // "🐟 to eat"
}

It’s hard going back from Swift’s string indexing model to Cocoa’s NSRange system. Native regex can’t arrive soon enough.

You can also break down unicode scalars to components:

var utf16View = UnicodeScalar("🐟")!.utf16
print(utf16View[0], utf16View[1]) // 55357 56351
print(String(utf16View[0], radix:16), 
    String(utf16View[1], radix: 16)) // d83d dc1f

This scalar approach goes boom  when you try to push into highly composed characters:

Instead:

let utf16View = "👨‍👩‍👦‍👦".utf16
for c in utf16View {
    print(c, "\t", String(c, radix: 16))
}
// 55357 	 d83d
// 56424 	 dc68
// 8205 	 200d
// 55357 	 d83d
// 56425 	 dc69
// 8205 	 200d
// 55357 	 d83d
// 56422 	 dc66
// 8205 	 200d
// 55357 	 d83d
// 56422 	 dc66

It’s interesting to see the four d83d components in there.

Got any fun little Unicode tricks? Drop a comment, a tweet, or an email and let me know.

Update: 

Tuple assignments

Do you have any good examples of when it would be useful to have a tuple but be doing complicated enough stuff with them?

Here are some examples I grepped out of a local folder, including some from third parties:

var (x, y) = (7.5, 7.5)
let (controlPoint1θ, controlPoint2θ) = (dθ / 3.0, 2.0 * dθ / 3.0)
var (_, sceneWidth) = boundingNode.boundingSphere
let (vMin, vMax) = label.boundingBox
let (duration, _) = cameraController?.performFlyover(toFace: mainActor.rotation) ?? (0, 0)
struct Point { var (x, y) : (Double, Double) }

Hope that helps.

Holy War: This seems wrong

This works:

["23"].map({ Int($0) }) // works

But this doesn’t, presumably because of the defaulted radix argument for public init?(_ text: String, radix: Int = default):

["23"].map(Int.init) // nope
["23"].map(Int.init(_:)) // nope

But this does work:

[("23", 10)].map(Int.init(_:radix:)) // works

and this:

zip(["23"], repeatElement(10, count: .max))
    .map(Int.init(_:radix:)) // works

What do you think? Should this splattage be splermissable or splorbidden?

 

For those who “wish for this every day”, you can always extend Int:

extension Int {
    /// provides map-specific `String` initialization
    ///
    /// e.g. `["23"].map(Int.init(string:))`
    ///
    public init?(string value: String) {
        self.init(value, radix: 10)
    }
}