Protocol Extension and Protocol Oriented Programming in Swift

What?

Swift 2 brought with itself protocol extensions. Before this, a protocol was an abstract contract to which structs and classes could confirm. With Swift 2, a protocol can also have code in it. This brings a whole new level of abstraction to Swift and in this article I’m going to show you how we leverage it’s power at Aftonbladet.

Defining a news article

Let’s start to define a news article using protocols. We want an article to have the following properties:

  • Title
  • An optional image
  • Text
  • A list of tags (such as “politics” and “sport”)
  • A URL (that points to the article on the web)

So let’s define these in separate protocols:

protocol WithTitle{
    var title: String {get}
}

protocol PossiblyWithImage{
    var image: UIImage? {get}
}

protocol WithText{
    var text: String {get}
}

protocol WithTags{
    var tags: [String] {get}
}

protocol WithUrl{
    var url: NSURL {get}
}

Then we are going to define an immutable article that conforms to these protocols:

struct Article : WithTitle, PossiblyWithImage, WithText, WithTags, WithUrl{
    let title: String
    let image: UIImage?
    let text: String
    let tags: [String]
    let url: NSURL
}

We can then of course initialize an article like so:

guard let url = NSURL(string: "http://goo.gl/qFvFlv") else {return}

let article = Article(title: "Zlatan om mötet: Alla har förstått", image: nil, text: "Article text", tags: ["sport", "zlatan"], url: url)

Defining a Spotlight indexable item

The goal for us here is to allow an object of type Article to be able to be indexed in Spotlight on an iOS device, so that the user can just search for an article using its title or text, right on their “desktop” on their iOS device. Let’s define a protocol for a Spotlight indexable item:

protocol SpotlightIndexable{
    var spotlightTitle: String {get}
    var spotlightDescription: String {get}
    var spotlightKeywords: [String] {get}
    var spotlightImageData: NSData? {get}
    var spotlightUrl: NSURL {get}
    func index()
}

This protocol defines what a Spotlight indexable item requires. A title, description, keywords and possibly an image represented as data (NSData).

Now, how do we go about making our Article object indexable? We could just go and make Article conform to SpotlightIndexable but then we have to define the properties that SpotlightIndexable requires. If we had to make more objects conform to SpotlightIndexable, then we have to define the same properties over and over again. That won’t work very well and is a pain. So how do we solve this?

Making a protocol require other protocols

We know that for an article to be indexed in Spotlight, we have to make it conform to SpotlightIndexable protocol but we don’t want to define those properties that are in this protocol manually. Instead, what we want is for SpotlightIndexable to be able to read those properties from any object that conforms to it. This is a shift in our way of thinking. Now a protocol will require any object that conforms to it, to conform to a series of other protocols. Look at this new SpotlightIndexable protocol:

Sprotocol SpotlightIndexable : WithTitle, PossiblyWithImage, WithText, WithUrl{
    var spotlightTitle: String {get}
    var spotlightDescription: String {get}
    var spotlightKeywords: [String] {get}
    var spotlightImageData: NSData? {get}
    var spotlightUrl: NSURL {get}
    func index()
}

Now our SpotlightIndexable protocol requires any type that conforms to it, to also conform to WithTitle, PossiblyWithImage, WithText and WithUrl. Does this sound similar to any other types that we defined earlier? Yes, the Article type!

Extending our SpotlightIndexable protocol with code

What we need to do now is to translate the protocols that SpotlightIndexable requires (such as WithText), to the properties that it requires.

extension String{
    var words: [String]{
        return characters.split{$0 == " "}
        .map{String($0)}.map{$0
        .stringByTrimmingCharactersInSet(NSCharacterSet
            .punctuationCharacterSet())}
    }
}

func + (lhs: [T], rhs: [T]) -> [T]{
    var array = [T]()
    array.appendContentsOf(lhs)
    array.appendContentsOf(rhs)
    return array
}

extension SpotlightIndexable{
    var spotlightTitle: String{
        return title
    }
    var spotlightDescription: String{
        return text
    }
    var spotlightKeywords: [String]{
        return title.words + text.words
    }
    var spotlightImageData: NSData?{
        guard let image = image else {return nil}
        return UIImagePNGRepresentation(image)
    }
    var spotlightUrl: NSURL{
        return url
    }
    func index(){
        //Code this
    }
}

Putting it together and final words

Now that we have our SpotlightIndexable protocol and protocol extension, we can simply make our Article struct conform to it to make the article spotlight indexable:

struct Article : WithTitle, PossiblyWithImage, WithText, WithTags, WithUrl, SpotlightIndexable{
    let title: String
    let image: UIImage?
    let text: String
    let tags: [String]
    let url: NSURL
}

That was it really. The Article struct doesn’t have to implement anything related to SpotlightIndexable since the code resides in the protocol itself which on its own looks at Article to make sure it conforms to a series of protocol such as WithTitle and WithText.

I think protocols and protocol extensions are a welcome addition to Swift and they enable a level of abstraction unheard of.

/Vandad — glhf


A Holistic View on Developer Productivity

What does developer productivity mean, really? Is it churning out more code or less code? Is it to have less bugs in production or shipping code more often? Is it doing a lot of things or just one thing? Let’s think about this for a moment. I believe developer productivity is about getting more things […]


Improving the usability of Aftonbladet Video-clip pages

We have recently started the process of improving the usability of video-clip pages. In order to get an idea of where Aftonbladet stands compared to other world-class online video/news providers, we conducted an online test answered by 110 visitors of Aftonbladet TV. In this test we compared their perception of an Aftonbladet TV video-clip page […]


Schibsted’s 1st iOS Deployment Meet-up

Schibsted’s 1st iOS Deployment Meet-up Thursday, 28th of April 2016: getting to know each other, guests arrive Friday, 29th of April 2016: the meet-up date We here at Aftonbladet had been planning on having a meet-up with iOS developers across various Schibsted companies for many months. We had a range of topics in mind for […]


Hackday: The Future of Storytelling is social, engaging and rewarding

We gathered students, journalists, developers and designers to get together and conceptualize something new for the news industry. This was our first organized hack event – The Future of Storytelling Hack. The hack was a team-based, news-media-focused prototyping and experimentation event within storytelling over two days at Kungsbrohuset, Schibsted and Aftonbladets headquarter in Stockholm. A good story used to […]