Shared posts

19 Mar 11:05

Comment by bbum on Butterfly flapping its wings

by bbum
You need to provide examples of what you have tried and why it didn't work as desired.
13 May 08:18

Apple’s App Analytics

by Drops

Developers received mail from app inviting them to join the waiting list for their new app analytics service. Such a service is long overdue and several businesses are based solely on there not having been any offering by Apple so far. That is about to change.

Apple is working to close the gab between what developers what and what the platform provider should provide.

  • Public Beta testing – we are very happy with TestFlight which offers this since fall 2014.
  • Crash Reporting – Xcode 6.3’s Organizer window is able to retrieve symbolicated crash logs for BETA tests. iTunes Connect lets you download crash reports for published apps
  • Analytics  – this was announced at WWDC 2014 but has yet the materialize

People have come to understand multiple kinds of things when talking about App Analytics: Click Tracking (external links to the app store page of your app), Conversion Tracking (who downloads the app after viewing it, who buys IAPs?), Engagement Tracking (once downloaded how often is the app opened?) and In-App Analytics (what areas of your app are looked at how often)

Apple’s coming App Analytics promises to deliver all but the last one of these kinds of analytics but this might change in the iOS 9 SDK. Tracking user activities around an app probably needs iOS system hooks to do easily. For example Google Analytics tracks pages and events. A page is essentially anything that you can assign a path to (e.g. “/contacts/new”). An event is anything that a path does not make sense for (e.g. “downloaded asset”). With Google Analytics you have to integrate an SDK and send messages whenever there is something you wish to track.

I can see Apple hooking In-App Analytics directly into the view controller hierarchy, similar to state restoration. Say if you use state restoration and all your view controllers have restoration IDs, then Apple’s In-App Analytics could be forming the VC path automatically from those IDs.

Even without In-App Analytics, Apples coming offering is a big deal. They promise:

  • See how often customers visit your app’s page on the App Store
  • Find out how many of your users open your app over time
  • Check your app and In-App Purchase sales
  • Create custom campaign links and follow the success of your marketing campaigns
  • Understand which websites refer the most users

Ahead of the launch, Apple invited all developers to join the Beta waiting list. This marks the first time that Apple has a waiting list for a new feature. Apparently they fear – rightfully so – that an enormous amount of people will want to get the data they promise.

Apple App Analytics

Third-party analytics providers are quick to say that they are providing many more features than Apple will, to justify charging ongoing membership fees. Certainly developers who do pay for those will have to reevaluate the sensibility of paying for external services when Apple’s offering will be “it just works” and good enough for the majority of usage scenarios.

Like for example finding out if the purchase rate is bad in certain countries and thus you might want to look into improving your iTunes description, add this countries localization and make better screenshots.

Personally, I hope that Apple will “sherlock” all kinds of third party developer services as those feel to me like small parasites which are turning a dime because of Apple’s success.

Flattr this!

03 Feb 07:46

Protocols and Swift

by Ash Furrow

The other day I posed this (somewhat cryptic) question to Twitter:

Best way for pure Swift objects to have optional conformance to some contract? Optional protocols/protocol members are @objc-only.

— Ash Furrow (@ashfurrow) January 28, 2015

I heard back from a lot of different people with a lot of different opinions. Most were confused by my necessarily terse question (it may have been better to post a longer, more detailed question on a medium that provides more than 140 characters).

I shared my actual question and with help from other developers, I found an answer for my specific case.

So, hooray I guess? But something about the answer seemed unsatisfactory to me. It is too specific for the general case, so I thought I’d dig deeper to see if I could figure out something better.

So let’s back it up a bit.

Here’s the problem: you have two types that want to talk to each other. If you directly reference the type of one from within the other, you’ve just tightly coupled the two types together — and any software engineer worth their salt knows that Coupling is Bad.

Most modern languages have a way to deal with this problem. In Objective-C — and indeed, in Swift — we call them protocols. As a high level concept, protocols are like contracts. If a type conforms to a protocol, it has essentially signed a contract to implement the methods specified in that protocol. Revisiting our earlier problem of the two types that want to talk to each other, we can use protocols so that they remain blissfully unaware of one another. All they care about is the protocol. Let’s look at a concrete, incredibly pedagogical example.

Say we want to model some animals and food. Animals eat food. We can have each animal type be aware of all the different food types, but that would tightly couple the types together. Instead, we can use the following Food protocol.

protocol Food {
    var caloriesPerGram: Double { get }
}

Then, we can define our Cat type.

struct Cat {
    var calorieCount: Double = 0
    mutating func eat(food: Food, grams: Double) {
        calorieCount += food.caloriesPerGram * grams
    }
}

Nice.

Ode to Spot

In order to feed our cat, we need a type that conforms to the Food protocol.

struct Kibble: Food {
    var caloriesPerGram: Double {
        return 40
    }
}

Super. Using the two together is really easy:

let catFood = Kibble()
var dave = Cat()

dave.eat(catFood, grams: 30)

Awesome. Note that we’re using pure Swift types – none of that Objective-C cruft.

This is my actual cat, Dave.

(I know that this is fundamental stuff that you probably already know, but it’s important to make sure we’re on the same page before we continue.)

Here’s the problem I ran into: in a pure Swift environment, I want to have optional methods in my protocol so that objects that conform to it may opt-in to certain functionality. It turns out that this is really really hard.

Let’s revisit our example of the cat and the food. Cats – turns out – have not evolved to eat kibble; they rely on moisture from their food to hydrate themselves. (That’s why kitties often have problems with urinary tract infections – they’re dehydrated.) Some foods, like canned cat food, have moisture. Some foods, like kibble, have none. Since I believe this difference is fundamental enough to different foods, I’d like to expand my protocol to have an optional amount of moisture. That way all the foods that don’t have any moisture don’t have to bother implementing those part of the protocol. Easy, right?

protocol Food {
    var caloriesPerGram: Double { get }
    optional var milliLitresWaterPerGram: Double { get }
}

Er, no, actually. This code produces a compiler error advising you that the ’optional’ keyword can only be a applied to members of an @objc protocol. Huh, that’s weird.

omg swift

Fine, so we put @objc at the beginning of our protocol declaration.

@objc protocol Food {
    var caloriesPerGram: Double { get }
    optional var milliLitresWaterPerGram: Double { get }
}

But then we run into another problem: Swift structs, like Kibble, cannot conform to Objective-C protocols.

It seems like quite the pickle. I want to use all the cool awesome new Swift features, but my solution requires the use of legacy Objective-C. So what do I do?

I tried creating a second protocol and asking if the food parameter conformed to it, like so.

protocol WetFood: Food {
    var milliLitresWaterPerGram: Double { get }
}

struct Cat {
    var calorieCount: Double = 0
    var hydrationLevels: Double = 0
    mutating func eat(food: Food, grams: Double) {
        calorieCount += food.caloriesPerGram * grams

        if let wetFood = food as? WetFood {
            // do something here
        }
    }
}

But the compiler still errors: Cannot downcast from ‘Food’ to non-@objc protocol type ‘WetFood’. Swift protocols are just not designed to be used in this way.

Whomp whomp.


After playing around for a while, things seemed a bit hopeless. Eventually, I realized that I was trying to solve a Swift problem using Objective-C methodology – something that can only lead to tears. I’ve been saying for a while that we need to reevaluate our approaches to familiar problems with Swift, and it was time to follow my own advice.

Let’s revisit the high-level problem I’m trying to solve: I have two types and I want them to talk to each other without coupling. Justin Spahr-Summers, as usual, has an answer:

@ashfurrow Split out the optional bits into one or more separate protocols that can be conformed to if desired.

— Justin Spahr-Summers (@jspahrsummers) January 28, 2015

OK, cool. I can see that being really useful for table views, for example. He even later pointed out that was the case. So let’s take a break from Cat and Food and look at table views. How might they look in pure Swift?

The table view delegate/datasource protocols have always mystified me – no one has ever given me a satisfactory rule dividing what is a datasource method from what is a delegate method. The datasource protocol alone has eleven methods, all but two of which are optional.

The methods are optional because the creators of UITableView wanted the behaviour to be opt-in (hey, just like our Food example!). By having optional components of their contract, table views behave differently. If you don’t implement the methods to reorder the table view, it doesn’t show the reordering controls (for example).

So let’s take Justin’s advice.

Imagine Apple has hired you to rewrite UITableView in pure Swift. Let’s start with the existing protocol implementation. Currently, UITableView has an optional dataSource property.

unowned(unsafe) var dataSource: UITableViewDataSource?

Ok, now how about that UITableViewDataSource protocol?

protocol UITableViewDataSource : NSObjectProtocol {

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

    optional func numberOfSectionsInTableView(tableView: UITableView) -> Int

    optional func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    optional func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?

    // Editing

    optional func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool

    // Moving/reordering

    optional func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool

    // Index

    optional func sectionIndexTitlesForTableView(tableView: UITableView) -> [AnyObject]! 
    optional func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int 

    // Data manipulation - insert and delete support

    optional func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)

    // Data manipulation - reorder / moving support

    optional func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
}

Yikes! I’ve included some of the comments from Apple’s header files to show you how complex this protocol is. For example, the “Moving/reordering” function determines if a given row can be moved, but is only invoked if the datasource also implements the final method in the protocol. One wonders why these two interdependent methods are so far apart in the header file.

If we were going to write a new, purely Swift TableView type, we’ll need a data source to get information about the content we’ll be displaying. By following Justin’s advice, it’s not hard to see how things could be rewritten (let’s assume we have Swift equivalent types for NSIndexPath, UITableViewCell, etc).

class TableView {
    var numberOfSections: Int = 1

    weak var dataSource: TableViewDataSource?
    weak var titlesDataSource: TableViewTitlesDataSource?
    weak var editingDataSource: TableViewEditingDataSource?
    weak var reorderingDataSource: TableViewReorderingDataSource?
    weak var indexSataSource: TableViewIndexDataSource?

    // TODO: Finish re-implementing UITableView
}

protocol TableViewDataSource: class {

    func tableView(tableView: TableView, numberOfRowsInSection section: Int) -> Int
    func tableView(tableView: TableView, cellForRowAtIndexPath indexPath: IndexPath) -> TableViewCell
}

protocol TableViewTitlesDataSource: class {

    func tableView(tableView: TableView, titleForHeaderInSection section: Int) -> String?
    func tableView(tableView: TableView, titleForFooterInSection section: Int) -> String?
}

protocol TableViewEditingDataSource: class {
    func tableView(tableView: TableView, canEditRowAtIndexPath indexPath: IndexPath) -> Bool
    func tableView(tableView: TableView, commitEditingStyle editingStyle: TableViewCell.EditingStyle, forRowAtIndexPath indexPath: IndexPath)
}

protocol TableViewReorderingDataSource: class {
    func tableView(tableView: TableView, canMoveRowAtIndexPath indexPath: IndexPath) -> Bool
    func tableView(tableView: TableView, moveRowAtIndexPath sourceIndexPath: IndexPath, toIndexPath destinationIndexPath: IndexPath)
}

protocol TableViewIndexDataSource: class {
    func sectionIndexTitlesForTableView(tableView: TableView) -> [String]!
    func tableView(tableView: TableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int
}

I’m not saying that this is necessarily how I would actually write things – it’s only supposed to show you how dividing areas of concern into separate protocols makes things a lot more clear.

First, we moved the section count into the TableView type itself. All we need to populate the table view is to give it an object that conforms to the TableViewDataSource protocol.

Extending behaviour is very easy: you want to have cell reordering in your table view? Then set the table view’s reorderingDataSource property to something that will handle reordering. You want titles? Go ahead and use TableViewTitlesDataSource. And so on.

Sure, you’ll probably have only one object that conforms to all the protocols you need (and be honest – it’s probably a view controller, isn’t it?). But the power of this technique is not that we can divide the various data sources into different objects. Instead, the advantage is that we don’t have additional semantic coupling between functions in the protocol. Of course canMoveRowAtIndexPath can only be called if moveRowAtIndexPath is also implemented – they’re in the same protocol.

(Of course, UITableViewDelegate could benefit from a similar rewriting, but as it contains no fewer than thirty three functions – all optional – I will leave that as an exercise for the reader.)

(Also note that the : class suffix of the protocols. This specifies that the protocols may only be conformed to by classes and not structs or enums – those two types cannot be weakly referenced.)

OK, so UITableView sucks and like most things that suck in Objective-C, they’re way better in Swift. So what?

So, Swift programmers, you have a choice now. The next time you write a protocol and it needs optional functions, don’t just add @objc to the declaration. Split it out into multiple protocols like a responsible adult. There, that’s better. Your mother and I are so proud of you.

We really are.


But wait – what about my first example? With the cat and the food and everything? What do we do there? Well, just like my Twitter question the other day, the answer isn’t so simple.

Remember, the problem isn’t “I need optional protocol functions blah blah blah” – those are a means to an end. The problem is “I need two types to talk to one another without coupling.” Let’s solve this problem the Swift way: with protocols.

(Wait, weren’t we just using protocols? Didn’t protocols get us into this mess? Yes, but protocols are like XML – if they don’t solve your problem, then you’re not using enough of them.)

Our problem before is that the Cat struct didn’t know if the Food it was passed in contained water it should keep track of. Not all foods have water in them, after all. But wait a second – everything that consumes food has a current calorie count and hydration. Let’s flip things around: instead of making the Cat responsible for updating its state when it eats something, let’s make the Food responsible for updating the state of whatever is consuming it.

protocol FoodConsumer {
    var calorieCount: Double { get set }
    var hydrationLevel: Double { get set }
}

protocol Food {
    func beConsumedBy(consumer: FoodConsumer, grams: Double) -> FoodConsumer
}

struct Cat: FoodConsumer {
    var calorieCount: Double = 0
    var hydrationLevel: Double = 0
}

struct Kibble: Food {
    let caloriesPerGram: Double = 40

    func beConsumedBy(consumer: FoodConsumer, grams: Double) -> FoodConsumer {
        var newConsuner = consumer
        newConsuner.calorieCount += grams * caloriesPerGram
        return newConsuner
    }
}

struct FancyFeast: Food {
    let caloriesPerGram: Double = 80
    let milliLitresWaterPerGram: Double = 0.2

    func beConsumedBy(consumer: FoodConsumer, grams: Double) -> FoodConsumer {
        var newConsuner = consumer
        newConsuner.calorieCount += grams * caloriesPerGram
        newConsuner.hydrationLevel += grams * milliLitresWaterPerGram
        return newConsuner
    }
}

This is a lot better. The different foods are responsible for doing their own thing to whatever consumer comes their way and the consumer itself is only responsible for things that are common to all food consumers: calorie count and water levels.

(We could have also opted to use an inout FoodConsumer parameter to pass in &dave and modify the struct itself. I prefer this immutable approach.)

And how might we use this code? Well, we have a few options. Here’s one that I like.

extension Cat {
    func eat(food: Food, grams: Double) -> FoodConsumer {
        return food.beConsumedBy(self, grams: grams)
    }
}

let catFood = Kibble()
let wetFood = FancyFeast()
var dave = Cat()

dave = dave.eat(catFood, grams: 30) as Cat
dave = dave.eat(wetFood, grams: 20) as Cat

You get a lot more flexibility with this method, since you can have foods that don’t have calories (diet soda) or don’t have either calories or water (as far as I know, twist ties contain neither, but it’s possible that my cat knows something I do not).

(It would be nice to be able to extend the FoodConsumer protocol to add an eat(Food) method that could just call through for us, but Swift doesn’t support such an extension – at least not yet.)

Om nom nom.

This approach obviously isn’t suited for every case, but it is a useful tool to have at your disposal.


Remember that the general problem is “how do I get different types to talk to one another without coupling?”

The answer is “it depends.”

Swift and Objective-C are interoperable, but are still fundamentally different languages. One prefers static typing and the other is dynamic. Solutions that work well in one aren’t necessarily going to work well in the other. However natural it is for us to try and use Objective-C solutions to solve Swift problems, we should always be on the lookout for new or better ways to solve problems. If something is difficult in Swift (and it’s not related to constant compiler crashes), it’s likely that you’re trying to use it in a way it is not intended to be used. Pay attention to the friction you experience when writing Swift – if something feels overly difficult, there probably is a better way.

05 Sep 08:09

Swift Enumerations and Storyboard Segue

by John Muchow

Andrew Bancroft walks through his approach for encapsulating Storyboard segue identifiers using a Swift Enumeration. By creating an Enumeration that stores raw String values, I was able to encapsulate what would otherwise be “magic strings” in a type-safe construct for (…)

Read the rest of this entry »

iOSDeveloperTips.com

25 Aug 20:44

Technology for Excellence 2014

by Fraser Speirs

Later this year, I will be running an EdTech conference in Glasgow along with my friends and colleagues Andrew Jewell and Abdul Chohan.

Andrew works with me at Cedars and is an Apple Distinguished Educator. He is one of the most creative classroom teachers I know. Abdul is a director at ESSA Academy, Bolton, an ADE, and a world-wide consultant on educational technology.

The focus of the conference is on the transition to 1:1 computing provision in your school. I have become concerned over time that many 1:1 deployments are being done on quite an ad-hoc basis.

Attendees from all over the world will be welcome and will find it relevant and useful. It's not iPad-specific, although the reality is that iPad dominates this conversation. Although it's in Scotland, it's not specific to the Scottish education system.

We would love to have you at the conference! Please visit the website to find out more about the schedule and register. We have early-bird pricing available, as well as payment by invoice for those teachers at schools without credit cards.