Archive for the ‘Development’ Category

Bug reporter complaints

I wasn’t part of the bug reporter preview but having used it today, I’ve got to say that I am not a huge fan of the updated interface. It may be pretty, but for me it’s harder to use. I’d rather see icons and names at the start of the entry screen than scroll through three pages of iconless text (and their subtables) as I try to recognize the phrase that best matches my issue.

It’s funny because this design is a clearly cognitive mismatch between how I used to find the right items, which was just a matter of a single-screen scan, and trying to construct or detect the right verbal phrase that now matches the target issue. The new system is hitting the wrong part of my brain.

If you look at it, it’s laid out very nicely, with big clear areas to enter text and the “drop a screenshot” system is vastly improved over the old system. (Nice job there!) I like the font choices, can live with the sickly purple, and a lot of thought has gone into streamlining issue entry.

That said, the whitespace feels like there’s too much there, the left-to-right range of field width is too hard to scan to review the information you’ve entered, and as I mentioned before, the ‘What are you seeing an issue with?” tables are a little too much for me to process.

If I were to redesign it, I’d:

  • Change the wording to be more business-like: “Classify this issue:”, not “How would you classify this issue?”. “Affected Product or Area”, not “What are you seeing an issue with?”. “Bug or Suggestion”, not “What kind of issue are you reporting” (with the bias being towards ‘bug’, since that’s the primary purpose of the tool.) “Reproducing the issue”, not “What steps can we take to reproduce this issue”, and so forth.
  • In the prompt text, I’d eliminate weasel words. “Step-by-step instructions to reproduce this problem”, not “Please provide a step-by-step set of instructions to reproduce the problem (if possible).”
  • I’d cut back massively on the vertical whitespace, allowing more of the report to be seen at once. There’s just too much floaty gray for my taste.
  • I’d apply one of the “optimal line length” studies, which suggests anywhere between 50 and 75 characters per line for text (which is most of what this tool provides) and 80-160 characters for code entry. (I’d also consider a code-specific “related code” field.) The current width is about 98 characters if I counted correctly. It is very hard to track from the right back to the left while maintaining vertical positioning.
  • I’d explicitly mention Markdown/Common Mark support for bullets and numbering, as well as other markup.
  • I’d change the Suggestion/Bug toggle into either a radio control or a visual toggle with Bug, which should be to the left, pre-selected.
  • I’d massively increase the size of the “Cancel/Save/Submit” buttons and move them from the bottom bar to the main field under attachments.
  • Finally, I’d add a specific call out on completion. Thank the developer for taking time from their busy workday and express appreciation for participating in the radar process. Enroll them either in a rewards-for-radars program or a random giftcard giveaway for the month. It’s a small price to sweeten that “Radar or GTFO” message and it lowers frustration of typing into a big, faceless, low-feedback system.

Those are my thoughts. What are yours?

Apple open sources key file-level transformation Xcode components

Ted Kremenek writes on the swift-dev list:

This afternoon at WWDC we announced a new refactoring feature in Xcode 9 that supports Swift, C, Objective-C, and C++.  We also announced we will be open sourcing the key parts of the engine that support file-level transformations, as well as the compiler pieces for the new index-while-building feature in Xcode.

We will be releasing the sources in stages, likely over the next few weeks:

– For the refactoring support for Swift, there are some cleanups we’d like to do as well as some documentation we’d like to author before we push these sources back.  Argyrios Kyrtzidis and his team from Apple will be handling that effort.

– For the refactoring support for C/C++/Objective-C, these are changes we’d like to work with the LLVM community to upstream to the LLVM project.  These will likely be first staged to the swift-clang repository on GitHub, but that is not their intended final destination.  Duncan Exon Smith and his team from Apple will be handling that effort.

– We’ll also be open sourcing the compiler support for indexing-while-building, which include changes to both Clang and Swift.   Argyrios and his team will be driving that effort.  For the clang changes they will likely be first staged to swift-clang, and then discussed with the LLVM community to upstream them to mainline Clang.

– Finally, we will be open sourcing the remaining pieces of the Swift migrator.  Argyrios and his team will be handling the push back of changes there, and those changes will only be impacting the swift repository.

As usually, we’ll also be pushing back changes to have Swift work with the latest Apple SDKs.  We’re expecting that push back to happen early next week.  When that happens we will temporarily lock commit access to the repositories.  Details about that will be sent out later in a later email.  Until then, the downloadable toolchains from Swift.org will continue to work with Xcode 8.3.2.  After we do the push back the downloadable toolchains will be moved to be baselined on the Xcode 9.0 betas.  This shift is necessary as changes to the overlays depend on the latest SDKs.

Xcodes and Kittens: These are a few of my favorite things

Fully redesigned source editor: You can now increase and decrease the source editor font using Command-plus and Command-minus. I have been waiting for this for years. Other highlights include an improved find and replace system, better scrolling, and integrated markdown support.

Better refactoring. Global renaming works across Swift, ObjC, IB, and other file types.  Apple says you can view changes in a unified presentation. The naming strategies for properties, getters, setters, and synthesized ivars are all coordinated.

Better boilerplate. “Fix-it automatically fills in missing cases in switch statements, and mandatory methods for protocol conformance with one click.”

Better Assets including Named Colors. Support for named colors, wide-gamut icons, HEIF images (the ones they discussed during the keynote this morning), and of course, the larger iOS Marketing images.  I suspect “Added option to preserve image vector data for matching Dynamic Type scaling” won’t be as exciting as I’d hope, but I’m looking forward to finding out more.

Github Integration. “GitHub account integration for easy browsing and one-click creation of a project and the associated GitHub repository.”

First class playgrounds. New playground templates designed to run   (depending on the target) on macOS, in the simulator, and on iOS Swift Playgrounds. If you’re looking for them, choose File > New > Playground. They’re not in “File > New” anymore.

What’s New: Things that caught my eye

I love the idea of ARKit, although I wonder about the practicalities of how people will interact with their iDevice while holding it up to look through it. You build a basic AR experience with SceneKit or SpriteKit, and then configure real world anchors based on flat surface destinations. ARKit can pull ambient light estimates for the captured scene, provide overviews of the visualizing camera, and allow you to “hit test” against modeled sufaces.

CoreML looks really really cool. It leverages training data sets to build models that allow you to predict outcomes for new data as it arrives. Apple has introductions to obtaining CoreML models, integrating them into your apps, and importing third-party machine learning to Apple’s framework. The framework is pretty sparse, so it looks like most of the magic will happen behind the scenes.

It was going to happen eventually, and DeviceCheck allows you to access per-device (developer-specific) data that lets you track which devices have previously interacted with your servers and software.

The new Vision framework offers high-performance image analysis and computer vision tech for face identification, feature detection, and scenery classification. Looks a lot like OpenCV-style stuff at first glance.

You’ll be able to create app extensions that help filter unwanted messages using the new IdentityLookup framework, and provide workarounds that respond to unwanted received messages.

The ColorSync framework doesn’t have much there to play with, but its few constants intrigue me.

The FileProvider (and associated FileProviderUI) frameworks are both major components for accessing documents across applications. We’ve seen a bit of this before, but the new fully fleshed out APIs are fascinating.

Finally there’s CoreNFC, which detects and reads NFC tags and their NDEF data. This framework is limited to the iPhone 7 and 7 plus.

Don’t forget to check out the “diff overview” here.

Writing a binary search tree

Tim discusses using Swift enumeration indirect keywords to build binary tree nodes. Read on to learn more about how reference types and value semantics combine…

Today we’re writing a simple binary search tree in Swift. While binary search trees seem to be very powerful in theory, their performance is rather disappointing in practice. Other, more advanced tree-shaped data structures such as red-black trees and B-trees solve some of the practical problems that binary search trees have, and are subsequently much more useful in performance-critical code. Nevertheless, learning about binary search trees is the first step to getting more familiar with this class of data structures.

Probably the simplest way to represent a binary tree in Swift is by using an indirect enum, like so:

enum BinarySearchTree<Element: Comparable> {
    case empty
    indirect case node(left: BinarySearchTree, value: Element, right: BinarySearchTree)
}

While indirect enums use reference types under the hood, they have value semantics by default. So that’s nice.

From all the standard library’s protocols, SetAlgebra and BidirectionalCollection both seem a good fit for our BinarySearchTree type: SetAlgebra for inserting and removing elements, and BidirectionalCollection for traversing the tree (both forwards and backwards, hence the name). However, for the purpose of this post, we’ll stick to only a couple basic methods.

Let’s start with insertion. Because of the way enums with associated values work, it’s easiest to implement the insert method using an under-the-hood inserting method:

extension BinarySearchTree {
    mutating func insert(_ element: Element) {
        self = inserting(element)
    }
    
    private func inserting(_ element: Element) -> BinarySearchTree {
        switch self {
        case .empty:
            // the tree is empty, so inserting an element results in a tree containing only that element
            return .node(.empty, element, .empty)
            
        case .node(_, element, _):
            // the element is already present in the tree
            return self
            
        case let .node(left, value, right) where element < value:
            // the element should be inserted into the left subtree
            return .node(left.inserting(element), value, right)
            
        case let .node(left, value, right):
            // the element should be inserted into the right subtree
            return .node(left, value, right.inserting(element))
        }
    }
}

Now we can insert values into a tree, but we can’t read them in any way. So let’s add a contains method as well:

extension BinarySearchTree {
    func contains(_ element: Element) -> Bool {
        switch self {
        case .empty:
            // an empty tree obviously doesn't contain any elements!
            return false
            
        case .node(_, element, _):
            // the element is equal to this node's value
            return true
            
        case let .node(left, value, _) where element < value:
            // if the element is present in the tree, it must be in the left subtree
            return left.contains(element)
            
        case let .node(_, _, right):
            // if the element is present in the tree, it must be in the right subtree
            return right.contains(element)
        }
    }
}

Let’s try it out!

var tree = BinarySearchTree.empty

tree.contains(5) // => false
tree.insert(5)
tree.contains(5) // => true
tree.insert(3)
tree.contains(3) // => true
tree.contains(5) // => true

Looks good. We can’t actually remove elements, though, but that is a real pain to implement and it’s out of scope for this post.

Finally, to iterate over a binary search tree, we need to implement the IteratorProtocol protocol. We’ll use an in-order traversal algorithm:

extension BinarySearchTree: Sequence {
    func makeIterator() -> BinarySearchTreeIterator<Element> {
        return BinarySearchTreeIterator(self)
    }
}

struct BinarySearchTreeIterator<Element: Comparable>: IteratorProtocol {
    var node: BinarySearchTree
    var stack: [(Element, BinarySearchTree)] = []
    
    init(_ node: BinarySearchTree) {
        self.node = node
    }
    
    public mutating func next() -> Element? {
        while case let .node(left, value, right) = node {
            stack.append((value, right))
            node = left
        }
        
        guard let (element, node) = stack.popLast() else { return nil }
        
        self.node = node
        return element
    }
}

Now we can do all kinds of sequence-y stuff with trees, like so:

var tree = BinarySearchTree.empty
[5, 2, 4, 8, 3, 2].forEach { tree.insert($0) }

for element in tree {
    print(element, terminator: " ") // => 2 3 4 5 8
}

tree.reduce(0, +)                                  // => 22
tree.lazy.map(String.init).joined(separator: ", ") // => 2, 3, 4, 5, 8

And the list goes on.

That’s it for now! If you enjoy this kind of stuff, make sure to check out Károly Lőrentey’s brand new book Optimizing Collections in which he in much detail goes through implementing several data structures in Swift, focusing on performance. As of writing this post, it’s 25% off.

Erica Knows Nothing About Kotlin: Kotlin collections

Cocoa distinguishes NSArray from NSMutableArray, among many other mutable variations on standard types. In Swift, you var or let a collection and let the compiler handle the rest of the details, whether the outcome is mutable or not. Kotlin follows the Cocoa model. It uses distinct collection types based on mutability.

For example, the listOf function returns a new read-only serializable list of elements.

val myList: List<Double> = listOf(1.0, 2.0, 3.0)

You cannot automatically promote typeless literals the way you can in Swift. In Swift the literal “1” doesn’t have an intrinsic type (although it defaults to Int in the absence of any other context). “1” can represent an integer, a double, a float, and more.

Kotlin does not support literal inference. If you use listOf(1, 2, 3) for the preceding example, Kotlin issues an error: “Type inference failed. Expected type mismatch: inferred type is List<Int> but List<Double> was expected”.

Like Swift, Kotlin’s type inference system permits you to drop the explicit List<Double> type annotation from the myList declaration.  The listOf function still produces the expected type, which the compiler assigns to the constant myList. In this declaration, Kotlin’s val is the same as Swift’s let. It produces a constant rather than a (var) variable.

However, the list you produced is not a value type. Switch the list from immutable to mutable, and you’ll still (like an NSMutableArray reference) be able to add new members:

val myList: MutableList<Double> = mutableListOf(1.0, 2.0, 3.0)
myList.add(4.0)
println(myList) // [1.0, 2.0, 3.0, 4.0]

You won’t be able to re-assign myList to a new list, but as a mutable reference type, the underlying instance can be modified because it is a MutableList<T>.

Kotlin also offers dictionaries, which it calls maps. That’s really not a bad name for a type that performs one-to-one mapping, which is all that key-value lookup really does. The underlying types honor that key/value relation. They’re called Map<K, out V> and MutableMap<K, V>.

val myDictionary = mutableMapOf(
    "cow" to "moo",
    "dog" to "woof",
    "pig" to "oink"
)

println(myDictionary["dog"]) // woof
println(myDictionary["kitten"]) // null

Like Swift, Kotlin returns a “not there” result for a failed map lookup, but the meaning of null is distinct from Swift’s nil. A type must be nullable (sort of but not entirely like Optional) to store a null reference.

var string = "Hello"
println(string)
// string = null 
// error: null can not be a value of a non-null type String

var string2: String? = "Hello"
println(string2) // hello
string2 = null
println(string2) // null

The initial value of string2 is not Optional("hello") or something like that. It feels (at least so far, because I know nothing about Kotlin, see the title of this post) more like the Objective-C nil, that is a null-reference in memory rather than a pointer to a reference type. I’m new to this, so I’m still learning.

Speaking of null, the first string example demonstrates what happens when you assign null to a non-nullable type. You end up with a (more or less) null pointer exception, which is a bad thing.

Getting back to collections, Kotlin also supports sets, both mutable and immutable. All three types: lists (arrays), maps (dictionaries) and sets (sets), inherit from Kotlin Collection, and in turn from Kotlin Iterable. All three types have a way to count the number of elements (or entries), they can be iterated over, and Collection offers many methods that may or may not apply to each type. For example, you don’t use dropWhile on a map/dictionary.

The Collections reference page lists which functions apply to which types. It’s a bit hodgepodge compared to Swift’s cleaner, hierarchical, and protocol-based system. That said, all the things you would expect to do to an array, set, or dictionary in Swift, you can do to a list, set, or map in Kotlin. Have a browse through that Collections page to get a sense of the functionality. It’s all pretty familiar.

If anything, the various subtypes (LongArray, ByteArray, IntArray, etc) feel like overkill and the available functions feel a tiny bit bloated. But that’s me looking at this stuff with Swift-ized eyes.

If you like this series of posts, let me know. Drop a tweet, email, or comment if you’d like me to keep going.

Swift Style: WWDC Sale

Celebrate style in a half shell during WWDC week!

Pick up a copy of Swift Style with a nice discount. The ebook will be 25% off the normal price during WWDC. Use the coupon code Swift_WWDC_2017 at checkout to apply this dub-dub discount to your purchase of the Swift Style ebook at Pragmatic Programmers. (If you encounter any problems during checkout, contact support@pragprog.com.)

Thank you for reading my blog and supporting me and my books!

Update: the discount is already live. You don’t have to wait until next week:

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: Kotlin functions

Yesterday, I got my feet wet creating a simple functional chain to calculate the sum of natural numbers that are multiples of 3 or 5 (thanks Jeff):

var result = (1 .. limit - 1)
    .asSequence()
    .filter { item -> item.divisibleBy(3) || item.divisibleBy(5) }
    .sum()

As you can see, Kotlin looks a lot like Swift. And, like any programming language, you can collect a routine into a function (fun rather than func in Kotlin, which makes Kotlin seem like a very “happy fun™” language) for re-use.

Instead of using a temporary result variable (var, just like in Swift, although let is val) and re-assigning it at each calculation, it’s more elegant to create a reusable component to call for each limit.

The simplest way is to build a function that mimics Swift. You declare fun, the function name, parameters, the return type (with a : token), and use the return keyword to establish the return value:

fun Int.divisibleBy(factor: Int) = this % factor == 0

fun euler1 (limit: Int) : Int {
    return (1 .. limit - 1)
        .asSequence()
        .filter { item -> item.divisibleBy(3) ||item.divisibleBy(5) }
        .sum()
}
println("The sum of these multiples is ${euler1(10)}")
println("The sum of these multiples is ${euler1(1000)}")

I also munged the calls directly into the print string using ${}. This is basically the same as using \() in Swift. The new  euler1 function is now almost indistinguishable from Swift.

Kotlin offers a bit more flexibility in its function declarations. You can skip the braces and use assignment to the compound expression, creating an inferred scope for short expressions:

fun euler1 (limit: Int) : Int = (1 .. limit - 1)
        .asSequence()
        .filter { item -> item.divisibleBy(3) ||item.divisibleBy(5) }
        .sum()

Same results, much streamlined declaration.

Like Swift, you can introduce defaulted arguments into your parameter list. This example can be called with zero or one arguments, allowing the printed phrase to default to “Hello World”.

fun greet(phrase: String = "Hello World") = println(phrase)
greet() // "Hello World"
greet("Hello Sailor") // "Hello Sailor"

You can also create functional closures/lambda expressions and assign them to variables, as you do in Swift. And, as in Swift, that closure can then be treated like a normal function:

var add : (Int, Int) -> Int = {item, increase -> item + increase }
println(add) // Function2<java.lang.Integer, java.lang.Integer, java.lang.Integer>
println(add(2, 3)) // 5

Finally, like Swift, you can create infix functionality, such as exponentiation. The first two examples use the infix form, the second two use a standard function call:

infix fun Int.exp(exponent: Int): Int {
    return (1 .. exponent)
        .asSequence().map { this }
        .fold(1) {current, base -> current * base }
}

println(5 exp 3) // 125
println(2 exp 8) // 256
println(5.exp(3)) // 125
println(2.exp(8)) // 256