I've been coding against Facebook's Graph API the past few days, and it turns out - not unreasonably - that like Twitter, some of their error messages request you to retry (or to back off, wait and retry if you're a good web citizen and don't want to get your App hell banned).
This is easy peasy in synchronous code, you just loop and increment some counters and you're done, but in today's asynchronous world, things get a little trickier. Many async APIs require you to provide a completion handler and when you get a back off/retry error in your completion handler, you have to issue your request again, which means you have to pass - you guessed it - your completion handler. Which means you're recursing. Recursive blocks are allowed, though you might have a bit of a 'mare figuring out the syntax that allows them (or indeed, to do anything else with them).
Here's a pattern that i came up with this afternoon. I'm sure there's all sorts wrong with it, and it will likely blow up in the first bit of real world code I use it in, but it chunters along happily in its Foundation CLI tool, and it doesn't issue any compiler warnings. Food for thought at least.
And no, I'm not at all sure about that
sleep() either. Share and enjoy :-)
Update Thu 26 Jun 2014 (original code)
I worked on this a bit more this morning and got rid of some of the
__weak / __strong dance line noise. For context, I'm basically mocking out a small part of FB's graph API here, I'll post full code when I've integrated and tested it. It will still be pretty ugly, much uglier than this nice clean(ish) POC, I imagine.
In part 1 I wrote up a method of finding out what version of your iOS app a user originally installed that works great, provided you can get a network connection and the App Store servers are up.
But if you can’t rely on that being the case, and you don’t want to wait for it to be true before you take whatever action you’re basing on the original version number, you can get the receipt data locally and process it.
So, for whatever reason – lets say that you want to experiment with a free download and IAP monetization model in an existing paid app but you don’t want to double charge existing users, or maybe you need to do some clever user defaults or data model updates – you decide that you need to know what version of your app was originally purchased.
So far as I’ve been able to discover so far, there are basically two ways to go about this. Well, one way, but there are two ways of getting the data. Well, N ways actually, but let’s not get all forked up at this point. This is (one possible implementation of) the easy way.
Assuming you have a receipt (and you may well not, in your dev version at least, in which case you need a bit of SKReceiptRefresh magic) then you can find it in your app’s bundle, and (assuming you have some network connectivity, and can talk to it) you can fling it at the App Store servers and they’ll parse it for you and fling back some JSON.
It looks a little like this.
Before I show you the one weird trick, a caveat or two. There isn’t a framework method anywhere to do this, and while this code doesn’t involve touching any private APIs it does have a number of other issues. From an app store review perspective, it could easily be argued that if Apple wanted you to be able to detect this stuff, they’d have put an API in for you. While I do intend to try it out, I suggest that if you do use this code in a production app you ready yourself for rejection and have a backup plan. From a technical point of view, it seems likely that you will need that backup plan as this possibly rather less than robust. I’ll get to that in a minute, you want to see the code now right ?
If you’ve worked in or studied UI design – or, if you’re a bit longer in the tooth like me, Human Computer Interaction – ‘Affordance’ is a term that you’re probably quite familiar with. Wikipedia gives the basic definition as :
An affordance is a quality of an object, or an environment, which allows an individual to perform an action. For example, a knob affords twisting, and perhaps pushing, while a cord affords pulling.
If you’ve done the HCI/UI thang though, what you’re probably more familiar with perceived affordance as defined by Don Norman in The Design Of Everyday Things, which is a much more context dependent kind of a concept.
If there’s one thing we’ve learned from the big iOS 7 reveal at WWDC it’s that designers, even more so than developers – and so help me, I didn’t think that was even possible – think they are special snowflakes.
Having met tons of developers, but never spent much time with designers, I genuinely didn’t believe it at first so I asked around people who do spend a lot of time around designers and they said “I can tell you don’t spend a lot of time around designers” …
From the intro to the WWDC 2013 Keynote :
The first thing we do is ask, what do we want people to feel ? Delight, surprise, love, connection. Then we begin to craft around our intention.
Wow. I mean, blech, right ? So much design luvvie navel gazing wankery, right ? Only, well ...
This week, I upgraded from my ageing iPhone 3GS. I knew I needed to do it, but I've been putting it off for a while. I didn't want a new phone. I've been carrying that 3GS around for over two years. When I first got it, surprise and delight were the exact emotions it evoked in me.
On the eve of WWDC, knowing that I had to upgrade, that the advent of iOS 7 would finally render it obsolete - or maybe just force me to admit that it was already - I actually had an anxiety dream about the new phone being dreadful. I like tech, I've been rampaging through platforms and devices since the early 1980s, but that never happened before. That's how visceral the connection was. Love ? By many definitions, I believe you could call it that.
And then, the WWDC Keynote. Surprise. And on Tuesday morning, at 9am, I finally became an iPhone 5 owner. Delight. By Wednesday - and it would have been sooner if not for a DSL fault - I was an iOS 7 user, and my partner, who was up until that point carrying an Android, was also an iPhone 5 owner. Love. And since then, it's barely been out of my hand, or hers. Connection.
That's why Apple is making all the profit in the mobile sector. That's why Apple has the loyalest customer base. That's why the 5,000 developers sitting in that keynote so uncynically and enthusiastically cheered the intro.
Because it isn't just a wanky marketing statement. It's not even a promise. It's a simple statement of fact. Those are design goals that Apple achieves.