December 03, 2015

Swift blog: Watching the language evolve

Now that Swift is open source, we have a lot of visibility inside the project. That includes new features and discussions that can help us be prepared for new features or important changes on the language itself.

If you go over to https://github.com/apple/swift-evolution/tree/master/proposals you can get a pretty good idea where the language is headed to, and, as Daniel Jalkut mentioned, potentially help you overcome bad habits and save you a ton of time writing code that you'll have to change later.

I'd keep an eye on that page and read each proposal thoroughly. These people are very smart and they know what they're talking about — I'm sure I can learn a lot from them and their reasoning behind their proposals.

My favourite so far: Removing currying func declaration syntax


December 03, 2015

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.


November 20, 2015

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


November 13, 2015

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!