Body of Water

Jun 08 2013

Yacht on Lake Tahoe

It’s been a while since I’ve entered the PhotoFriday challenge, but I liked this weeks theme — “Body of Water” — and thought I had a good image for it. This was taken a couple of years ago in Lake Tahoe, California.

 

No responses yet

AQGridView to UICollectionView

Jun 06 2013

I recently moved a code base from using AQGridView — a third party library — to UICollectionView. I have nothing against third party components but I’m a big fan of minimising dependencies and reducing the amount of code that need to be understood. In this case I managed to remove about 5000 lines of code from the project. Switching to the UIKit version made sense on both counts.

Both components do more or less the same thing and their APIs fortunately look pretty similar. (UICollectionView can be coerced into doing a lot more but we just need it for a simple grid.) Most of the changes are just renaming methods; I was surprised how little new code needed to be written.

Creating the grid is easy enough, but you need to specify more information up-front:

-    self.gridView = [[AQGridView alloc] init];
+    self.gridView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[[[UICollectionViewFlowLayout alloc] init] autorelease]];

 

(I also took the opportunity to fix a memory leak in the original project.)

One thing that caught me out initially, is that you need to register the classes you’re going to use as cells before you use them:

+    [self.gridView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];

 

Creating the cell looks pretty similar:

-    AQGridViewCell *cell = (AQGridViewCell *)[self.gridView dequeueReusableCellWithIdentifier:cellIdentifier];
+    UICollectionViewCell* cell = [self.gridView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

 

And configuring the cell actually takes slightly less work using a UICollectionView:

-    cell = [[[AQGridViewCell alloc] initWithFrame:cellFrame reuseIdentifier:cellIdentifier] autorelease];
-    cell.selectionStyle = AQGridViewCellSelectionStyleNone;
+    UICollectionViewCell* cell = [[[UICollectionViewCell alloc] initWithFrame:cellFrame] autorelease];

 

The rest is mostly renaming delegate methods:

AQGridView
UICollectionView
numberOfItemsInGridView:
numberOfSectionsInCollectionView:
gridView:cellForItemAtIndex:
collectionView:cellForItemAtIndexPath:
portraitGridCellSizeForGridView:
collectionView:layout:sizeForItemAtIndexPath:
gridView:didSelectItemAtIndex:
collectionView:didSelectItemAtIndexPath:

 

There are two other “gotchas,” one easy and one hard.

Inside a UICollectionView, multiple updates need to be grouped together in a block and called using the performBatchUpdates:completion: method. (Oh, and the insertItemsAtIndices:withAnimation: method becomes insertItemsAtIndexPaths:.)

The last one is about formatting. AQGridView centres cells. UICollectionView, on the other hand, pushes the cells to the far left or right of the frame. This is probably easier to explain with a picture. This is the how UICollectionView flows the cells by default:

Outer Cells

Outer Cells

And this is how we want it to look, and how it does look using AQGridView:

 

Centred Cells

Centred Cells

Now the correct way of dealing with this would be to build a custom UICollectionViewFlowControl, which is the way you can definine custom layouts. That seemed like a lot of work just to centre a few cells! Instead I dynamically adjusted the frame on rotation which gives the appearance of centring the cells without most of the hard work. May be one day I’ll get around to doing the job correctly!

If the formatting has made some of this difficult to follow, you can see the full patch on GitHub.

Overall, the process of converting from AQGridView to UICollectionView was straightforward, which I think is a testament to the quality of the original component. Next time I’m aim to remove a lower quality, more problematic piece of code!

No responses yet

Temperature

May 03 2013

Ice cream, originally uploaded by stephendarlington.

This weeks PhotoFriday theme is “Temperature.” I thought this image from my recent trip to Barcelona fit the bill.

Comments Off

Distance

Mar 31 2013

Distance, originally uploaded by stephendarlington.

This weeks PhotoFriday theme is “Distance.” They said that Junior was independent at the nursery. They weren’t joking. He was half way across the park before we could catch him…

Comments Off

Familiarity Breeds Contempt

Mar 14 2013

This week I did a presentation at the London iPhone Developer Group meeting. Given my experience with using lots of APIs, I thought it might be a good, if dry, topic. I tried to spice it up by complaining about lots of them and trying to condense that negativity into some useful lessons to take away.

Most of the other discussions of this subject that I’ve seen focus on designing libraries but I thought the same lessons could be applied to all kinds of interfaces, from Objective C libraries to REST API’s for connecting to web services. (I don’t mean to suggest that the focus of the two articles I link to is wrong. They’re both very much worth reading.)

You can see a PDF of the slides here (though they might not make much sense without what I was saying at the time), but the gist is as follows:

  • Design your APIs around use-cases. Many appear to be designed around “how can I made the data I have available.” This is the wrong way round
  • Clients need to access data in a predictable, reliable way. Being clever accepting any old junk and trying to do the right thing is often not the right thing to do
  • Communicate how it works and how it’s going to change clearly. Examples and sample code are always useful
  • Think about error cases. “Something went wrong” is not a good error message
  • Think about the devices that people are likely to be accessing your service from. Mobile apps have latency, bandwidth and CPU constraints that desktop computers and other servers do not. The iPad 4 has more resources to throw at a problem than an iPhone 3GS. Your code might need to work on both
  • Be consistent. Make your API look like other, similar APIs and use the patterns of the technology you’re using. That means delegates and return codes for Objective C, inheritance and exceptions for C#
  • And, most importantly, use your own API. Don’t keep special “secret sauce” for your self. How else are you going to know whether it works than by actually using it?

Ideally I’d end a presentation (or blog post) with salient advice on the best way to do something. This is an exception. I don’t think there’s a one-size-fits-all solution and I’m generally weary of Best Practice guides.

So I’ll end by noting that poor APIs result in poor applications. It’s worth investing the time and energy in doing it well. Your users and your future self will thank you.

Comments Off

Meerkat Confusion

Feb 24 2013

Is it any wonder that there's confusion?

I found this while (mis)typing the caption to yesterdays photo competition. Is it any wonder that those meerkats have to keep telling the world about their website to avoid confusion with a comparison shopping site? Even the Mac’s spell checker gets it wrong.

Comments Off

Keep It Simple

Feb 23 2013

Simples

I stumbled across a weekly photo competition on Flickr called FlickrFriday and thought I would enter that this week instead of PhotoFriday.

This weeks theme is “Keep it simple” and, as any British person will tell you, that means meerkats.

But please still consider voting for my entry in last weeks PhotoFriday, “Neglected.” I’m entry number 123.

Comments Off

Neglected

Feb 16 2013

Bike and old TVs

This weeks PhotoFriday challenge is “Neglected,” which is quite appropriate since I’ve neglected to enter the challenge for quite some time now.

My entry was taken in Amsterdam.

Comments Off

No Massive Google Play Privacy Issue

Feb 14 2013

If you follow any iOS technology blogs you might have seen this recent scandal:

If you bought the app on Google Play (even if you cancelled the order) I have your email address, your suburb, and in many instances your full name.

This, they say, is bad because this is not what happens with Apple’s App Store.

However, I don’t think Google are doing anything weird here, and I say this as someone who is not a fan of Android. The commercial relationship between developers and Apple is different from the relationship between Google and developers1.

In Apple’s case, the developer has a single customer (Apple). You licence your code to Apple and Apple sells your app. The end users relationship is with Apple, not the developer. You get royalties, much in the same way that you get royalties when you publish a book. I’m still waiting for my million dollar advance from Apple, but the principle is the same.

Google plays a different role. They’re just an intermediary. The customers buys the app directly from the developer (using Google Wallet). This is why the developer has access to email, location, etc.

Saying that this is a privacy issue is like paying for a latte with a credit card and complaining that Starbucks now has your Amex number and name. Of course they do.

There are always stories of disreputable restaurants skimming credit cards and defrauding consumers. The trick, insofar as there is one, is not to eat at those restaurants. Similarly, if you think a developer is likely to use your data in an underhand manner, don’t download their software. It’s that simple.

Should Google be more upfront about who gets what details? Possibly. It never hurts to be open and honest — dare I say, not evil — about privacy matters. But I don’t think what they’re doing is inherently bad.

  1. Please let me know if I have any of this wrong. I don’t develop Android software but this is my understanding of how it all works. []

Comments Off

Pattern

Jan 13 2013

Oslo Opera House

 

This weeks PhotoFriday theme is “Pattern” and here is my entry, taken in the new Oslo Opera House last year. Can’t say I’m a big fan of opera, but the building was amazing!

Comments Off

Older »