Swift blog: Swift is now open source!

Today Apple surprised us by finally making Swift an open source project.

At Swift.org you can find all the information about it.

4 main projects are being made public:

  1. Compiler and Standard Library, comprised by Swift itself and a repository of documents related to the language’s evolution.

  2. Core Libraries, comprised by the foundation libraries, libdispatch and XCTest.

  3. Package Manager (!), comprised by the package manager itself and swift-llbuild, the build system that the package manager uses internally.

  4. Cloned Repositories, comprised by the LLVM, Clang, lldb and CommonMark projects for Swift.

Apple says this is all available on Github, but it isn’t just yet. However, this is huge. We already know the implications of Swift being open source, and now that it is a reality, there’s nothing left to do other than start cracking on it!

Read everything at Swift.org.

Swift blog: Protocols are not always the way to go

I keep forcing myself to use protocols more and more when coding Swift.

Today’s issue came from the following scenario:

I have a (static) table view with 4 prototype cells defined on Interface Builder. Each cell has its own identifier and UITableViewCell subclass assigned to it.

The requirement: each of cells must have a specific property from where it will automatically populate its fields:

var foo: Foo? {
    didSet {
        barTitleLabel.text = bar!.title
    }
}

Since I was quickly prototyping how everything would work, I had the following mess on my UITableViewDataSource implementation:


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
	return 4
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
	switch indexPath.row {
	case 0:
		let cell = tableViewdequeueReusableCellWithIdentifier("FirstCell", forIndexPath: indexPath) as! FristCell
		cell.foo = currentFoo
		return cell
		
	case 1:
		let cell = tableViewdequeueReusableCellWithIdentifier("SecondCell", forIndexPath: indexPath) as! SecondCell
		cell.foo = currentFoo
		return cell

	case 2:
		let cell = tableViewdequeueReusableCellWithIdentifier("ThirdCell", forIndexPath: indexPath) as! ThirdCell
		cell.foo = currentFoo
		return cell		
		
	case 3:
		let cell = tableViewdequeueReusableCellWithIdentifier("FourthCell", forIndexPath: indexPath) as! FourthCell
		cell.foo = currentFoo
		return cell
		
	default: return UITableViewCell()
	}
}

So, there’s an obvious issue. Lots and lots of code duplication. If you pay close attention, the only thing that’s really changing is the identifier and the type, on each case everything is the same. Also, having that default clause there really bothers me.

Lets put protocols to good use.

Fixing the issue

I thought that I could map each String identifier with a unique value that identified that cell. Since each specific cell will be on the same spot every time, that was easy. I just created an enum:

enum Cell: Int {
	case FirstCell = 0
	case SecondCell
	case ThirdCell
	case FourthCell
}

extension Cell: CustomStringConvertible {
	var description: String {
		swith self {
			case .FirstCell: return "FirtCell"
			case .SecondCell: return "SecondCell"
			case .ThirdCell: return "ThirdCell"
			case .FourthCell: return "FourthCell"
		}
	}
}

It simplified the cell creation… kind of:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
	let cellType = Cell(rawValue: indexPath.row)! // the actual implementation does not use an explicitly unwrapped optional.
	
	let cell = tableView.dequeueReusableCellWithIdentifier(cellType.description, forIndexPath: indexPath)
	
	switch indexPath.row {
		case 0:
			var aCell = (cell as! FirstCell)
			aCell.foo = currentFoo
			return aCell
			
		case 1:
			var aCell = (cell as! SecondCell)
			aCell.foo = currentFoo
			return aCell
			
		// And so on...
		
	}
}

Not quite what I was hoping for, actually. Then I thought that it would be cool if, just as Cell can return the identifier for the appropriate row, it returned the type of the cell for the appropriate row. So I dug into it.

First approach

My first approach was just to have a variable that gave me the Type I was expecting:

extension Cell {
	var type: AnyClass {
		case .FirstCell: return FirstCell.self
		case .SecondCell: return SecondCell.self
		case .ThirdCell: return ThirdCell.self
		case .FourthCell: return FourthCell.self
	}
}

Everything seemed ok — it compiled correctly, but when I tried to implement it:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
	let cellType = Cell(rawValue: indexPath.row)! // the actual implementation does not use an explicitly unwrapped optional.
	
	let cell = tableView.dequeueReusableCellWithIdentifier(cellType.description, forIndexPath: indexPath) as! cellType.type // ERROR!!!
	
	// ...
}

Which made Xcode spit thie error cellType is not a type. Turns out the type casting operator can’t process statements on its right side. So that’s an issue, that automatically discarded my option of making Cell generic on subclasses of UITableViewCell [1].

Second approach

After a lot of thinking about the most elegant way to solve this, I came up with the following: create a protocol that all my cells conformed to, so that way I don’t have to worry about the cell’s actual type:

protocol Fooable {
	var foo: Foo? { get set }
}

“Let’s use the magic of inheritance, and have every UITableViewCell subclass be Fooable,” I thought to myself:

extension UITableViewCell: Fooable {
	var foo: Foo?  // ERROR: “Extensions may not contain stored properties.”
}

Ok, so… “Extensions may not contain stored properties,” huh? Let’s change the protocol, then:

protocol Fooable {
	func setFoo(foo: Foo)
}

extension UITableViewCell: Fooable {
	func setFoo(foo: Foo) {}
}

It sounded great on my head, but you can see the issue here… It would require every UITableViewCell subclass to override the setFoo: method, and also, it would require them to define a custom var foo: Foo?, which, by the way, is not cool because that requirement is not expreesed anywhere. Ah, and also, this polutes UITableViewCell on the whole app context.

“Aha!” moment! Create a UITableViewCell subclass. That way, I could define te foo var on the protocol itself, and avoid poluting all UITableViewCell:

protocol Fooable {
	var foo: Foo? { get set }
}

class BaseCell: UITableViewCell, Fooable {	var foo: Foo?
}

class FirstCell: BaseCell {
	override var foo: Foo? {
		didSet {
			// ...
		}
	}
}

// And so on...

So, my UITableViewDataSource now looks something like this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
	let cellType = CellType(rawValue: indexPath.row)!
        
    let cell = tableView.dequeueReusableCellWithIdentifier(cellType.description, forIndexPath: indexPath) as! BaseCell
    cell.foo = currentFoo
        
    return cell
}

Ahhh… much cleaner!

And then it hit me! I don’t need a protocol for this! So, 10 seconds later, Fooable disappeared and everything still worked correctly.

What I learned

  1. Protocol-Oriented-Programming is so fun and powerful that may make you forget certain aspects of Object-Oriented-Programming. Although it is useful, it is not always the way to go, as I found out today.

  2. Remember that Cocoa’s architecture is built with OOP, so POP may bite you in the ass if you try to force it.

  3. I’d still use my original approach with the enum if it was possible. This is related to what Samuel Giddins wishes comes with Swift 3.0. I certainly wish it too.

  4. This was a fun experiment!

  5. I found this answer on StackOverflow. However, I didn’t like that this approach depends creating a class from a string. I want strings the least possible, I want the actual type.


  1. This has been reported to Apple as a suggestion: rdar://23622714 ↩︎

Swift blog: Why is my Hashable implementation crashing on an iPhone 4s?

Today I found what I thought of as a bug that had me scratching my head for about an hour.

My app ran just perfectly on my iPhone 6S Plus. However, when I sent a build to my designer for him to do proper testing, it always crashed on the same spot.

Ran it on the iPhone 4s simulator and the crash looked like this:

No output on the console nor the debugger. Tried to run instruments to catch the crash, with no luck.

Did a bit of research, and finally got to the official Swift documentation.

Using overflow operators (&+, &-, &*) fixes the issue:

public var hashValue: Int {
    return firstValue &+ secondValue
}

Numbers can overflow in both the positive and negative direction.

Which is exactly what may happen if you run your app on a 32 bit device, as the iPhone 4s and 5.

So, heads up! Make sure you do proper testing!

Swift blog: Wrangling protocols

The app I’m working on has a set of interesting requirements on the data layer.

Let’s try to break it down: I have a set of data that can be represented on 2 different ways, although is the same type of data.

My Protocol-Oriented-Programming training kicked in:

protocol CriteriaItem {
	var title: String { get set }
}

struct SingleCriteriaItem: CriteriaItem {
	var title: String
}

struct MultipleCriteriaItem: CriteriaItem {
	var title: String 
}

I want to handle every item as a CriteriaItem, regardless it being Multiple or Single.

The server spits a set of strings, which then need to be converted to CriteriaItems:

let criteriaItemTitles = ["One", "Two", "Three", "Two"]

let criteriaItems: [CriteriaItem] = criteriaItemTitles.map { SingleCriteriaItem(title: $0) }

Now, let’s define a function to filter an array to get only unique values from it:

func uniq<S:SequenceType, E: Hashable where E == S.Generator.Element>(source: S) -> [E] {
    var seen: [E:Bool] = [:]
    return source.filter { v -> Bool in
        return seen.updateValue(true, forKey: v) == nil
    }
}

// uniq([1, 3, 2, 3, 2]) # => [1, 3, 2]

Great, so now we’re ready to get only an array of unique CriteriaItems:

let uniqueItems = uniq(criteriaItems) 
# ERROR: Cannot invoke `uniq` with an argument list of type `([CriteriaItem])`

If we check the type constraints on the generic uniq function, we know that:

  1. uniq is generic on S and E
  2. S, which is the parameter passed to the function, needs to be a SequenceType-conforming type.
  3. The Element on the sequence’s Generator should be the same type as E, the function’s output type.
  4. E, which is the output type of the function, should be Hashable.

Lets verify what we have:

  1. Arrays on Swift conform to CollectionType which inherits from SequenceType, so our criteriaItems constant is good ([CriteriaItem]).
  2. We expect an array of CriteriaItems as the function’s output, so we comply with the 3rd point.
  3. CriteriaItem is a protocol, and today you can’t make a protocol type conform to another protocol.

The solution: wrap the protocol on a struct that conforms to Hashable:

struct BoxedItem: Hashable {
	let item: CriteriaItem
	
	var hashValue: Int {
		return item.title.hashValue
	}
}

func ==(lhs: BoxedItem, rhs: BoxedItem) -> Bool {
	return lhs.hashValue == rhs.hashValue
}

So, now, to be able to extract only the unique CriteriaItems, we need to wrap every one of them in a box:

let boxedItems = criteriaItems.map { BoxedItem(item: $0) }

let uniqueItems = uniq(boxedItems).map { $0.item } // 3 => [{title "One"}, {title "Two"}, {title "Three"}]

Extras

There seems to be a bug with Swift, were the compiler won’t be able to infer the type of a collection of protocol implementations:

protocol A {
	var a: String { get set }
}

struct X: A {
	var a: String
}

func takesAs(aas: [A]) {
	// Something
}

let letters = ["A", "B", "C", "D"]

let xs = letters.map { X(a: $0) } // xs is of type [X]
takesAs(xs) // Cannot convert value of type `[X]` to expected argument type `[A]`

let xs2: [A] = letters.map { X(a: $0) } // xs2 is casted to type [A]
takesAs(xs2) // Works as expected

However, passing a protocol-comforming type instance alone works as expected:

func takesA(a: A) {
	// Something
}

let x = X(a: "A")

takesA(x) // Works as expected

This was reported to Apple as rdar://23499056.

Did I miss something or want to share some insight on this post? [Drop me a line.](mailto:oscar@swanros.com?subject=Swift blog 1)

Swift app size

I’ve been writing Swift for the most part of the past 6 months. Mostly playing with it, nothing serious.

But today, I submitted my first Swift app to iTunes Connect (currently in beta review), and was reminded of the fact that Swift apps have embedded libraries.

8.6MB of libraries.

My actual code is less than 6KB.

How to run networking code on Swift Playgrounds

I’m sure most of you know this by now.

If you’re mocking your network calls using Swift on a Playground, it is important to tell the Playground that it can run code asynchronously.

Import XCPlayground and call XCPSetExecutionShouldContinueIndefinitely with a true argument.

import XCPlayground

XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)

› Functional View Controllers – Wrapping View Controllers in a Functional Way

Chris Eidhof:

When working with UIKit, view controllers are the opposite of isolated: they are connected to everything. The view controller often pulls network or database data, populates and interacts with views, and finally, it pushes other view controllers onto the navigation stack (or presents them in a different way). In this article, we’ll look at view controllers that do only one thing: they populate the views and interact with them. They don’t load any data themselves, nor do they present other view controllers.

Great approach to reducing View Controllers complexity using functional paradigms.

Also, check out objc.io #1 ‘Lighter View Controllers’ if you haven’t already.

› Numbers and Swift

Dalton Cherry at vluxe.io:

Swift favors speed and safety by reducing the number of errors that can be made. Objective-C on the other hand was designed to be simple.

Swift was designed to make you trip with the cord and fall on the safe side before you can jump the bungee.

However, I don’t think Objective-C was designed around simplicity. Ask anyone new to the language.