clever/you - thoughts about mobile

  • Archive
  • RSS
  • Ask Me

Parse / Facebook: What Now?

You’ve probably read that this week Facebook acquired Parse, the mobile BaaS service. I’ve been using Parse for quite a well in production, and if you’ve read any of my previous posts you’ll know I quite like the service (see here, here, and here).

So what now? Does Facebook acquiring Parse change anything? Well, if you go by the press releases, no - it doesn’t. But perhaps there’s more too it than that. What should you be doing if you’re either an existing customer (like me), or someone who’s been thinking of using the service? Here’s my own thoughts on the subject.

You Already Use Parse

A lot of what you do next is going to depend on your own gut feeling. Some people have quite a visceral reaction to Facebook - I’m not one of them. What I will say is that the last time Facebook bought something I used (face.com) they ended up shutting down the APIs. But Parse is considerably bigger, and more importantly is used by some sizable customers. I personally don’t see Facebook cutting them off - and I suspect new customers will be welcomed for some time as well.

The bottom line is this: whenever you use any third-party provider to manage critical infrastructure in your apps you’d better have an escape plan. Companies get acquired, go bust, or retire products all the time. This isn’t an issue unique to Parse. If you’re not planning for the worst you’re sowing the seeds for a big headache in the future.

Parse already offer a mass-export feature that gives you all your data in JSON. You can use this, along with the Parse APIs, to migrate over to another provider fairly easily (although some scripting on your part may be required). One provider (Stackmob, who I’ve reviewed here before) even have a semi-automatic migration tool available.

You’re Deciding on a BaaS Provider

Again, this is going depend on how you feel about Facebook. If you’re not a fan, you’ve probably already made your choice. Here’s my two cents: even if Parse keep supporting existing customers, it’s almost certain that at some point in the future the product is going to change in a fairly significant way. I don’t see Facebook gaining any value from running Parse as an entirely separate entity.

I really like Parse as a product - I’ve used it in several production apps. Would I use it now? I’m not sure. I don’t necessarily think any of the competitors out there (Stackmob, Appcelerator, Kinvey, Fat Fractal, to name a few) are any more secure. If anything, financially speaking Parse is now top of the pile.

So…what?

I appreciate I haven’t really provided many direct answers. One thing this should really re-inforce, regardless of your BaaS provider, is that you need a back-up plan. To help with that I’ll be posting a new backend-as-a-service comparison in the coming weeks, updated to take into account all the recent changes in the marketplace.

    • #parse
    • #baas
    • #StackMob
    • #facebook
    • #ios
    • #backend
    • #backend development
  • 3 weeks ago
  • 2
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Mantle: Easy JSON Models in Objective-C

OK, so it’s not a very exciting topic - but still, it can often be a pain to convert JSON into Objective-C objects. There’s a lot of boilerplate code, and you invariably end up with something like this:

…and that’s just to decode from JSON. If you need to subsequently archive your object back to JSON you’ll end up with even more brittle and lengthy code, thanks to encodeWithCoder and its counterparts. Finally, you’d better hope your JSON never changes, because in the example above if there’s no url field in the dictionary an exception is going to get thrown.

I had to deal with this problem recently - I was working with a quite complex JSON API, and I needed something to help me manage my models. Fortunately, Github have open-sourced a framework used in their own Mac application called Mantle. Mantle aims to simplify the process of working with JSON in Objective-C, particularly in places where something like Core Data might be overkill. It works without NSCoder, and uses @property declarations to provide default implementations.

Here’s an implementation of the Article example above, but rewritten to use Mantle:

A really simple JSONKeyPathsByPropertyKey method maps JSON to properties, and reversible transformers allow things like dates, URLs, or other custom formats to be both encoded and decoded easily. The value transformers also handle missing or nil fields, meaning you don’t have to worry about exceptions.

I’m really enjoying using Mantle, and it’s made my code cleaner to read and easier to maintain. The source for Mantle, along with pretty comprehensive documentation, is available on GitHub, and you can use it in your own projects via the ever reliable CocoaPods.

    • #github
    • #mantle
    • #iOS SDK
    • #ios
    • #ios 6
    • #json
  • 3 weeks ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

iOS Debugging: Three Timesaving Tools

Debugging is twice as hard as writing the code in the first place
Brian Kernighan - The Elements of Programming Style

Debugging your own code may be a chore, but debugging somebody else’s can be downright painful. A particularly bad experience last week reminded me that debugging is as much a skill as writing code itself - and just like programming, there are lots of tools that can make it both easier and even enjoyable.

Here are three really useful tools that I use when debugging iOS applications.

Technical Note 2239

Hidden away on Apple’s developer site is Technical Note 2239, or iOS Debugging Magic. It’s packed full of tips and tricks to help the frustrated iOS debugger get to grips with XCode. Unfortunately, it’s also slightly out of date, written for iOS 4.1, XCode 3, and GDB (rather than the newer LLDB debugger now standard for iOS development).

Still, it’s still broadly applicable, and it’s the only place on Apple’s site where recursiveDescription, a category extension on UIView that lets you print out a view’s complete hierarchy, is documented. This alone justifies its existence:

DCIntrospect

Command line debugging is extremely powerful, but as many web developers will tell you being able to visually debug can be just as useful. Although Apple provide some tools to do this (such as the Core Animation Instrument), a number of third party options are available to help with layout problems.

DCIntrospect is one such popular library - designed to be used with the iOS simulator, it enables a number of keyboard shortcuts to allow dynamic manipulation of views.

Installation is particularly straightforward, so DCIntrospect is a good option if you need to quickly debug more complex view hierarchy or display problems.

PonyDebugger

PonyDebugger is one of the more complex iOS debugging tools - it requires both a client on device and a server on your development machine - but it’s arguably worth it in the long run. Once installed, you can remotely debug network traffic, Core Data, and view hierarchies using Chrome’s Developer Tools. It’s maintained by the good people at Square.

The networking traffic tools in PonyDebugger supplement, rather than replace, a traditional proxy. Because networking traffic is forwarded rather than sniffed traffic sent over HTTPS/SSL is viewable without needing any special certificates. The Core Data browser is also a nice touch, and is directly integrated into the traditional Chrome dev tools ‘resources’ tab. One particularly nice feature of PonyDebugger is its ability to convert an app’s view hierarchy into a HTML-like format that can be immediately edited, just as you would a normal web site within Chrome’s developer tools.

All of these features do come at a cost, namely a somewhat complex installation - I’d recommend using CocoaPods to handle the client library. You should take care for both DCIntrospect and PonyDebugger to only enable them in your debug builds, as you definitely don’t want either library to end up in your production code.

    • #iOS SDK
    • #debugging
    • #cocoa
    • #ios
    • #iphone development
    • #xcode
    • #cocoapods
  • 1 month ago
  • 1
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

State Preservation & Restoration

One of the new features in iOS 6 that hasn’t exactly been shouted out from the rooftops is state preservation, probably because on paper it’s far from exciting. However, having implemented it into an app I’ve realised there are some great benefits - not least of which is making your users happier.

What it does

State preservation is designed to solve the problem of app termination. The majority of iOS users don’t know the difference between application backgrounding and application termination. Anecdotally, many people who test the apps I work on are unaware that removing apps from the ‘recent apps’ list terminates them completely.

This can result in quite a confusing and frustrating experience: sometimes coming into an app will take you back to where you were last, and at others you’ll be back to square one. Some developers had attempted to solve this by keeping track of the current app state and attempting to restore it upon relaunch. Inevitably this led to a number of different approaches, some good and some bad.

The good news is that iOS 6 now offers state preservation out of the box, and enabling it is a simple two step process:

How to enable it

Step 1: Label your Controllers

To keep track of a user’s journey through an app you need to provide restoration identifiers for your view controllers. You can identify as many or as few controllers as you wish, but only controllers with restoration identifiers present will automatically instantiated and navigated to by iOS upon launch.

If you’re working with XIBs you can add identifiers within Interface Builder - and with Storyboards it’s even easier (since Storyboards already track a user’s progress through an app). In code you can simply set the restorationIdentifier property.

Step 2: Opt In to Restoration and Preservation

Currently, state preservation is ‘opt in’. To opt in you need to implement three methods in your application delegate, described below:

- (BOOL)application:shouldRestoreApplicationState:
Sometimes you might not want iOS to automatically restore the user’s state: perhaps your app has had a major UI update, and the area of the app your user was last in no longer exists. You should return YES to enable restoration.

- (BOOL)application:shouldSaveApplicationState:
As above, except this method is called when you application is terminated. Again, return YES to allow iOS to save the most recent state information.

- (BOOL)application:willFinishLaunchingWithOptions:
To support state restoration a new launching method has been introduced that complements the more traditional didFinishLaunching. willFinish is called before the state is restored, and didFinish is called afterwards. You’ll probably therefore want to split your launching code across these two methods: code that is required for your app to run should go in willFinish. Final completion code should go in didFinishLaunching. What counts as ‘final completion code’? Things like checking whether a user is logged in, where you might want to display a modal login page rather than your app itself, for example.

Backwards Compatibility

If you’d like to support iOS 4 and 5 users (where state preservation is not supported) you’ll need to watch out for a few things. Firstly, be sure to test that restoration identifiers are supported using respondsToSelector (if you’re using IB you can skip this step):

if ([self respondsToSelector:@selector(restorationIdentifier)]) {
        self.restorationIdentifier = @"Home Controller";
}

However, a more serious issue is how to deal with the new willFinishLaunchingWithOptions method, which is only available on iOS 6, into which you’ve moved most of your launching logic. You could put your launch code into both willFinish and didFinishLaunching and conditionally test the current version of iOS, but this is unnecessary duplication.

Instead, you can use this great little trick which Apple recommend in their WWDC videos:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self commonLaunchInitialization:launchOptions];

    // Code that must execute in didFinishLaunching whether state restoration is enabled or not
    return YES;
}

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self commonLaunchInitialization:launchOptions];
    return YES;
}

- (void)commonLaunchInitialization:(NSDictionary *)launchOptions {
    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
    // Your launch code here
});

If you are not familiar with Grand Central Dispatch you’re probably wondering what this code does. The dispatch_once GCD call is a clever method that is typically used when doing singleton work: it will execute it’s code block once only, and no nothing for any subsequent calls. This allows us to guarantee our launch logic will only be executed once, even though we’re calling commonLaunchInitialization in both didLaunch and willLaunch.

A Note on Testing

For reasons that will become quickly apparent, there are a few ‘gotchas’ involved with testing state restoration. Confusingly, terminating an app from the app switching pane disables restoration. Why? To prevent a mis-behaving or broken app from keeping a user stuck inside a loop. Perhaps the app has some terrible networking code that keeps the user locked inside a loading screen - resuming to that state would not be beneficial. Similarly, as you might expect state will not be resumed if your app didn’t terminate cleanly (i.e, it crashed).

So how do you test app switching? Well, when attached to the debugger you will want to exit to the home screen (by pressing the home button) and then terminate the app from Xcode (by hitting the ‘Stop’ button).

    • #ios
    • #ios6
    • #Mobile Development
    • #state preservation
    • #ios sdk
    • #iphone development
  • 2 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Oops: Snapchat Flaw Leaks Personal Data

Snapchat has been getting a lot of press recently, so I decided to take a look at the app. In doing so, I came across a security vulnerability that allowed anyone to obtain a Snapchat user’s cellphone number and e-mail address without their consent. This is a serious security issue, as many Snapchat usernames are publicly available.

The Problem

Snapchat lets you find out if any friends who might have you in their contacts are using the service. To do this it needs your phone-number: on Android, this is obtained automatically. On iOS, however, you need to verify your number by sending a SMS to Snapchat with a unique code (partly to prevent abuse, but mainly because unlike Android, iOS does not allow system access to the device’s phone number). The Snapchat app makes a web service call to discover whether this SMS verification has succeeded or not. The call looks like this:

POST https://feelinsonice.appspot.com/ph/settings
username=john.smith
timestamp=1357768038866
req_token=13f413fwrf4[…]

The req_token is a little strange (it’s an obfuscation of two separate hashes), but fundamentally it contains the user’s authorisation details. If you’re interested you can find out more about how the req_token is generated here.

In response to that call you receive the following back:

{
    "message": "+16175551212",
    "param": "[base64 encoded username]",
    "action": "[base64 e-mail (optional)]",
    "logged": true
}

This information is used to display a user’s account information inside the app. Notice that the phone number for the requested user is returned. Normally the supplied req_token would be checked and compared with the supplied username to ensure a user’s private information wasn’t being handed out freely.

Unfortunately a bug in Snapchat’s backend system meant this call wasn’t being authenticated - by changing the username parameter of the POST request it was possible to retrieve any user’s phone number. The req_token simply isn’t checked or even looked at: given a username the system blindly returns a phone number.

As a good number of Snapchat users are using the service anonymously this is a very serious vulnerability. Many people have even posted their Snapchat usernames in reviews, tweets, or tumblrs. Depending on what you are doing in Snapchat you may not want other users to identify you. However, by taking advantage of this vulnerability anyone could easily find out a Snapchat user’s phone number and e-mail.

Disclosure

I disclosed this vulnerability to Snapchat shortly after discovering it, on Tuesday January 9th 2013. Snapchat were very responsive, and the issue was patched in less than twenty-four hours. I have confirmed that it is now fixed, and you can no longer abuse the call to obtain users’ personal information.

Conclusion

Security issues are to be expected with any large app or web service with millions of users. However, this error was very basic and shouldn’t have happened. That said, Snapchat were very receptive to disclosure, and it was patched almost immediately. Snapchat has grown exceptionally quickly, which I suspect has exacerbated some of their recent security problems.

Snapchat’s API is on occasion quite strange, and as security blogger Adam Caudill has pointed out out relies quite a bit on security through obscurity. I agree with Adam that Snapchat should consider using some of their recent funding to externally audit their systems and reduce the risk of this sort of thing happening in the future.

    • #snapchat
    • #security
    • #ios
    • #app
    • #PII
  • 4 months ago
  • 2
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Collection Views

Making Life Easier Since 2012™

One of the great things about Cocoa / iOS development is also one of its downsides: you don’t need to know exactly what’s going on behind the scenes. Judging from some of the questions that come up on StackOverflow with surprising regularity, a sizeable number of users don’t realise that a UITableView is actually recycling views and cells to conserve memory.

This introduces a lot of problems when developers come to implementing things like galleries. Almost every other day there’s a question along the lines of “I put ten images into a scroll view and my phone crashed, what’s going on?”. Inevitably it’s down to memory simply running out. Until iOS 6 you were faced with several far from ideal options to fix this: write your own recycling system, use one of several open-source options (of varying quality), or hack a UITableView to pieces.

Collection views change that, in a good way. Some people describe them as “gallery views”, but that’s actually not the case - UICollectionView goes deeper than that. Unlike a table view, the display logic (how your items are laid out on the screen) is totally decoupled from the recycling logic. A collection view is paired up with a layout class that describes where and how elements should be positioned.

The most common layout - a gallery - is provided through the built-in UICollectionViewFlowLayout class, but by substituting your own layouts you are free to display your items however you want: cover flow, 3D-like layouts, circular layouts, pile layouts (à la Mail) - they’re all easily achieved by switching out the layout class.

Version Parity

There is, of course, a downside to all these benefits: collection views are only available on iOS 6. To be honest, for many people this shouldn’t be a problem. Some of the apps I work on show over 80% of users running iOS 6, and that’s only two months after it was released.

However, there’s good news for those looking to implement flow and gallery layouts - Peter Steinberger has put together a great drop-in replacement class for iOS 4.3-5 that has a 100% compatible collection view API.

Stop Writing Custom Galleries

The upshot of this is it would be absolutely crazy to implement your own recycling gallery view from scratch, even if you have to sub-class a collection view or write your own layout to get the effect you want. Setting aside the fact that in the vast majority of cases using a collection view will save development cost and time, you’re also backed by code that’s received far more testing time than your custom written class ever will.

The take away lesson: collection views are a fantastic addition to iOS, and you should be using them wherever possible in your apps rather than custom or third-party code. Learn to love them, and you will be rewarded.

    • #mobile development
    • #ios 6
    • #ios
    • #iphone sdk
    • #ios sdk
    • #UICollectionView
    • #collection views
    • #UITableView
    • #iphone
  • 5 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
A broken slinky

Getting to know Auto Layout

Like a slinky, the first few minutes with iOS’s springs and struts view layout system seems reasonable, but a few hours later your precious slinky is broken, and you’re filled with resentment and seething rage.

Perhaps for you it’s not quite that bad - for many developers it gets the job done - but it is certainly far from ideal. When you compare iOS to Android it becomes apparent how poor the layout system really is, especially if you have to design views for varying screen sizes and widths. And let’s be honest - it’s looking pretty likely that the next iPhone may well have a different aspect ratio.

Fortunately salvation is at hand, in the form of auto layout. Whilst new to iOS, auto layout was actually introduced to OS X last year. The Cocoa Touch implementation was announced by way of a ‘blink and you’ll miss it’ slide during Apple’s WWDC keynote, and since the technical implementation details are already public we can talk about its core concepts without fear of retribution from Apple’s legal department.

In many ways auto layout is to your views as ARC is to memory management. Like ARC it’s designed to make your life easier, but unless you want some nasty surprises down the line its best to understand a fair bit about the underlying concepts involved.

Springs and Struts

iOS, like OS X, uses a ‘springs and struts’ system. This term might be new to you, since in code these are referred to as autoresizing masks - properties such as UIViewAutoresizingFlexibleWidth and UIViewAutoresizingFlexibileRightMargin that determine how your view lays itself out in response to the superview changing its bounds.

Springs and struts is best described as ‘primitive’ - views are laid out relative to their superview, and you can’t express complex relationships between individual views. Springs allow views to expand and contract when their parent changes size, and struts define whether the views should have fixed or flexible margins. As we’ll see, the inability to dynamically resize views in response to their content can cause some big problems.

Auto layout

Fundamentally, auto layout lets views express relationships between themselves using equations. These are called constraints. A constraint takes the form y = m*x + b, but it might be easier to think of them as commands such as “place me 50 points above this button”, or “no matter what my width make sure there’s a 20 point margin between me and the edge of the screen”.

Constraints

There are a few things about constraints you should know - firstly, they can be inequalities - rather than y = m*x + b' you could say 'y <= m*x+b. Constraints can also, unlike springs-and-struts, cross view hierarchies. However, the flexibility of constraints does introduce some problems. What happens if a view has two competing constraints, or if there aren’t enough constraints to determine what should happen when the view is resized? These are dealt with through priorities and ambiguous layout respectively.

Priorities

It’s possible for a view to have competing constraints - perhaps a button has a constraint that determines its maximum width and a constraint that resizes the button to fit to its content. If the content width is greater than the maximum width value you’re going to have a problem.

Fortunately, you can indicate which constraint you’d like to ‘win out’ by assigning a priority value. Constraints are evaluated in order of their priority.

Ambiguous Layout

We’ve seen that constraints are fundamentally a series of equations that define the layout. For the layout to work, the equations must have a definite solution. An equation with multiple solutions could introduce ambiguous layout. For example, x + y == 100 has a number of possible solutions (an infinite number, actually). We need to define either x or y to solve the equation properly.

In auto layout such unsolvable equations introduce what’s called ambiguous layout.

In Practice

Here’s a classic if slightly contrived problem with springs-and-struts - a simple dialog view with two buttons, “Quit” and “Save and Quit”. We lay our view out like so:

So you release your app, and it’s a big success - but you’re set on conquering the world. This means you’re going to have to translate your content into other languages, like German. Your German translator send back all your nicely translated localized strings, and you start integrating them back into the app. Unfortunately, there’s a problem - the German for “Save and Quit” doesn’t quite seem to fit:

Ouch. This happens a lot when localising applications: some languages (such as German) can be quite verbose, meaning your labels and buttons may frequently clip. How do we solve this? Well, until now we’ve had a few options:

  • Localize our NIBs - but when we make an interface change we’ll have to update every single localised NIB.
  • Code around it - if we haven’t used NIBs maybe we can come up with something in code. This is probably going to be quite unwieldy, and hard to maintain
  • Do nothing - because nothing shows your international users you care like a broken layout

None of these are ideal. However, with auto layout we can have our cake and eat it - just plug in your localized strings file and that’s it (most of the time). We can tell the buttons to dynamically resize relative to each other, meaning we can be sure that the “Quit” button will be positioned nicely, and the “Save and Quit” button will vary its width to suit the content. The result is like so:

Autolayout can make internationalization easy. We’ve already seen how auto layout can resize interface elements in response to changing content sizes - but that’s really just the start. Many languages such as Arabic and Hebrew run right-to-left (‘RTL’), and supporting these frequently becomes an exercise in compromise. Ideally, your entire interface should really ‘flip’ itself, but this is easier said than done. Not so with auto layout - there’s in built support for RTL languages.

On the Mac, auto layout is also used to handle differing screen sizes, a problem that may well be rearing its head on iOS fairly soon. I’m looking forward to implementing auto layout in my own apps, and hopefully you will be too. It really is a huge step forward from the previous system.

If you’re interested in learning more about auto layout you can view Apple’s public documentation here. Registered developers will also have access to Apple’s WWDC 2012 session videos and associated documentation, which go into much more implementation detail about auto layout.

Image credit: Tangled Slinky image

    • #ios
    • #autolayout
    • #cocoa
    • #apple
  • 11 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

iOS Betas: Don’t Pay For Them

Every year, Apple release a new version of iOS…and every year, people try to make some money selling access to iOS betas.

I would like to implore developers and the public alike to stop the madness:

Public: Don’t Pay for It

iOS Betas are buggy, buggy, buggy

It’s not unknown for beta versions of iOS to severely cripple your battery life, crash regularly, and generally cause problems. It isn’t worth it. I promise you.

It makes developers sad :(

There have been several instances when non-developers installed betas and gave apps that didn’t work poor reviews on the store. This was particularly apparent when the iOS 5 betas came out: Apple made significant changes to how UI elements were customised, which caused many apps to break. Developers were understandably annoyed by this, since the whole point of the betas is to allow developers to fix these problems.

Betas expire or lock

Apple can and do ban developers who they discover are selling access - and will also lock any devices running betas that are registered to those developers. You will need to go back to iTunes and downgrade your phone to the most recent public version of iOS to get up and running again - and since selling access to betas is definitely not kosher, don’t expect a refund. This is the minority of cases: what’s more likely is your beta will expire, and you’ll end up having to re-install another one (or downgrade). It’s not worth the extra effort, particularly if your phone stops working when you’re out on the road or in the middle of nowhere.

If you MUST have it…

…I suspect some people in this world just really want the latest thing on their phone. So if you choose to ignore all my advice above, just promise me this:

  • Don’t review apps that aren’t playing nice - wait until iOS 6 is released to the public and give developers a chance to fix any problem.
  • Avoid paying for beta access if you can. Paying simple encourages the problem.

Developers: Don’t Do It

You will be found out

OK, you probably won’t be found out, but that’s only because there are a number of developers considerably dumber than you. One of my favourite is the person behind iosreg.com, which offers beta access for the ‘low’ price of ~$10 (that’s a $900 profit off each developer account, by the way - even more if you’re using an enterprise account).

Now, given that selling beta access is absolutely, totally in violation of your developer agreement you’d think you’d take steps to hide who you were. Not so here, because the person behind iOSReg.com has used his real name and address rather than an anonymous proxy when registering the domain. These are the people who will be found out - there are many, equally foolish, people and sites out there that don’t deserve the pagerank.

What’s clear is that Apple have in the past punished developers who sold iOS beta access. Of course, money is involved, so appealing to any sense of decency or good faith is probably a lost cause here: if you’re selling beta access you’re probably not a true iOS developer, but someone out for some fast cash. If you truly cared about iOS development you wouldn’t sell beta access because you’d understand the need for a period to allow developers to adjust their apps in private. So for that reason alone I hope this post at least encourages one person not to buy beta access.

(I wrote this rather quickly in response to a tweet: apologies for any omissions, but I just had to get it down while I was still mad!)

    • #ios
    • #developers
    • #ios6
    • #beta
  • 11 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

iPad Magazine Fails: Text

Glamour Magazine is published by Condé Nast, and is one of the top ten newsstand apps in the UK. It’s also a ‘page reader’ magazine - as far as content goes you get the print edition transferred wholesale to iPad, with nothing extra.

One problem that the new retina display iPads have exposed is just how lazy publishers have been with their magazine apps. If you’re going to insist on during a ‘page reader’ app you should at least be using PDF as your source material. Why? Because using PDFs will usually result in your text being rendered as vectors, and making it clear, sharp, and readable no matter what the resolution or screen size.

Not so with Glamour: each issue is a series of images, images that may have displayed perfectly well on the original iPad but perform badly on the new retina displays. How badly? Here’s a un-altered selection of text from the Glamour iPad App:

Increasing the size of the images isn’t viable: to match the retina resolution you’d be looking at a drastic increase in each issue’s download size. More failures in tablet magazine production to follow!

    • #magazine
    • #newsstand
    • #ipad
    • #ios
    • #text
    • #glamour
    • #condé nast
    • #tablet app
  • 11 months ago
  • 1
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Erratum

@steveflack has pointed out that my Twitter avatar has an error in it: since appeasing the Twitter Gods by joining last week I had a quick hunt around my laptop for a suitable photo and found a three year old grab of some code that I’d photographed for some reason (the reasons for doing so escape me).

Steve correctly points out that in my avatar [super dealloc] is called before everything else. In mitigating circumstances, svn blame informs me that I was not behind this particular sin. By sheer coincidence I was working on the codebase the picture came from today, and it’s now happily fixed. I would offer to buy Steve a beer, but I believe he brews his own which are probably of a much higher quality.

Perhaps I should correct the avatar too, but for posterity maybe it should stay!

    • #twitter
    • #ios
    • #dealloc
  • 1 year ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
Page 1 of 2
← Newer • Older →

About

I'm Nick, by day a mobile software engineer in London. Mainly I work on iOS and Objective-C, with some dabbling in Android. My views here are my own, not my employer's.

Me, Elsewhere

  • @objclxt on Twitter

Twitter

loading tweets…

  • RSS
  • Random
  • Archive
  • Ask Me
  • Mobile
Effector Theme by Pixel Union