June 27, 2016

Developer Insights, from Apple

With all the chatter around making a living on the App Store, and the recent changes to the App Store subscription model for apps, it seems that Apple is now trying to tell us how to create a successful business on top of their platforms.

This one is definitely worth a read.


June 23, 2016

Swift 3 Migration issues

This is a post that I'll be updating continuously with all the bumps that I find on the way while developing with Swift 3 and iOS 10.


CloudKit's database fetchAll methods are missing annotations on Swift 3

Swift 3 API design guidelines favor clarity over brevity. To accomplish that, many of the API's that we interact with on a daily basis changed radically.

For instance, this method that we've known for a long time:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)  

changed to:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)  

These changes are important as help us write more legible code.

On Apple's CloudKit framework, with Swift 2, you could call

func fetchAllRecordZonesWithCompletionHandler(_ completionHandler: ([CKRecordZone]?,  
                                                       NSError?) -> Void)

to get all Record Zones for a given database, or call

func fetchAllSubscriptionsWithCompletionHandler(_ completionHandler: ([CKSubscription]?,  
                                                         NSError?) -> Void)

to get all Subscriptions.

However, the API changes on Swift 3, now both methods are named almost the same, with the completion handler's parameters types being the only ones that change:

func fetchAll(completionHandler: ([CKRecordZone]?, NSError?) -> Void) // to get Record Zones  
func fetchAll(completionHandler: ([CKSubscription]?, NSError?) -> Void) // to get Subscriptions  

Trying to use any one of those functions make the compiler choke because it doesn't have enough information to know what you're trying to fetch, unless you type the parameters yourself:

db.fetchAll { (zones: [CKRecordZone]?, error) in  
    // ...
}

To me, this is a clear example where the API design guidelines are not being respected, favoring brevity over clarity.

Submitted as rdar://26977470.


June 15, 2016

Updating my codebases to Swift 3

Apple officially released the first beta of Xcode 8 this past Monday, which includes Swift 2.3 (an updated version of the language to work with the new APIs on iOS 10 and macOS 10.12), and Swift 3, the latest big release for the language.

Swift 3 basically breaks your project. If you're writing Swift and planning to continue doing so, my suggestion is: take the plunge right now and start migrating your project to Swift 3 right away.

That is, of course, providing you've got the time and the resources to do so.

In my case, I downloaded Xcode 8 and ran the migrator on a small project (about 1000 lines of Swift 2) with little success. The API changes that Swift 3 brings, such as removing namespaces, are big.

What I'm doing instead of trying to incrementally change my codebase (because the project wouldn't even try to compile to show errors), is to update each part one by one on a new project, which eventually will replace my codebase.

It may not be the best route for everyone, specially if you're dealing with large codebases.

This fall is shaping to be a busy one.


April 22, 2016

› Rewrite from Scratch - Autopsy of a Failed Software Project

This post brought a ton of memories back to mind. I've wanted to start a project from scratch far too many times more than I'd care to admit.

What I've found in my experience as a software developer is that trying to call the right shots from the beginning is a core part of the development process. Often this is the hard path, but I've found myself in situations where I need to change something, and thanked my past self for doing what he did.

Also remember that software is never finished.


April 12, 2016

Let's Encrypt leaves beta

Finally.

Encryption has never been easier. Such important sponsors put my mind at ease now, I'm going to be using Let's Encrypt for my projects from now on.


March 30, 2016

Another favourite from Xcode 7.3

In previous versions of Xcode, if you were working with Swift and tried to override a var from a super-class, you had no auto-completion suggestions. Most if the time, I had to go into the super declaration to copy the signature and then just add override in front of it.

Xcode 7.3 changes that, for good.

Yay! 🎉


March 23, 2016

#selector

One of my favourite changes in Swift 2.2 is that Objective-C selectors now are first class citizens in the Swift ecosystem. So long to error-prone selector names as Strings.

Swift 2.2 lets you use the #selector expression to reference a selector from your Swift code.

class MyView: UIView {  
    private lazy var button: UIButton = {
        let b = UIButton()

        // Swift 2.1 and earlier
        b.addTarget(
            self,
            action: "buttonTapped:",
            forControlEvents: .TouchUpInside
        )

        // Swift 2.2
        b.addTarget(
            self,
            action: #selector(MyView.buttonTapped(_:)),
            forControlEvents: .TouchUpInside
        )
        return b
    }()

    func buttonTapped(sender: UIButton) {
        // ...
    }
}

My only complain about this is that the actions still need to be declared either internal or public, declaring the action as private returns the error Argument of '#selector' refers to a method that is not exposed to Objective-C, which makes sense if yout think about it.

EDIT: I should have read the error message more carefully.

Turns out that if you want your selector to be private, you only need to add the @objc attribute to the function declaration, and you're set:

extension Selector {  
    static let cancelButtonTapped = #selector(MyView.cancelButtonTapped)
}

class MyView: UIView {  
    @objc private func cancelButtonTapped() {
        // ...    
    }
}


March 03, 2016

On Leveling Up as a Developer

I just read this post from David Bryant Copeland at naildrivin5.com.

This resonated with me:

[...] This may seem like a lot, but these meetings are crucial. Having dedicated time with your manager every week is important. So is having a weekly time to talk with the people for whom you are building software about priorities. And if you aren’t part of these discussions, they are still going to happen, but they will lack your input. That could go bad for you.

I've been on both ends of the spectrum before. Neither of which is good, you have to strive to find a balance there.