Feb 2, 2013

Issue Those Pull Requests

I’m the maintainer of a few Open Source github projects. Mostly iOS and Mac OS X Cocoa projects. I don’t open these projects because I’m expecting contribution from the community. I open them because I feel they may be useful to others.

That said, people do contribute back and I’m extremely grateful for these contributions. The main mechanism for contributing is via github pull requests. Unfortunately I see a lot of forks of various projects of mine containing improvements to the original project, improvements that have not had pull requests issued. These improvements will probably be lost unless the author issues a pull request.

Even if I notice these changes (and I do occasionally go through my project “network” to find interesting changes) the chances are the original project has probably divulged significantly since the changes were made. Merging these old changes into the original project becomes far more laborious than it should be.

Issuing pull requests is a great way of showing your support and thanks to the original project author (or authors). Pull requests are great. Timely, well defined pull requests with limited scope are even better.

(originally posted on schwatopia.quora.com)

Dec 2, 2012

Source code

If you’re looking for my source code you should look on my github pages:

My various other googlecode and bitbucket repositories are long gone.

Jan 12, 2012

New Start

I got tired of Mysql and Apache2 taking down my server running a blog that I haven’t updated in a year. So I migrated my Wordpress blog to one of these new fangled static blog generators. I’ve been very slowly writing my own (how hard can it be, it’s just a bunch of text files?) but in the end couldn’t be bothered to finish it. So I ended up using pelican. I did use my own wordpress to markdown import script (pelican only does Wordpress to Restructured Text). I’ll post the script I used on github soon.

Now I just need to make sure the disqus can find all the comments now, the RSS feeds still work, the images work and none of the posts are too corrupted in the conversion.

Dec 21, 2011

NSLunch

I haven’t interacted enough with my fellow Cocoa developers (outside of work that is) since moving to the Bay Area. So I’ve started NSLunch (yes, totally original name). A regular lunchtime meet up with your fellow San Francisco area Cocoa developers. We’ll see if it’s a success or if I end up eating lunch alone.

Dec 13, 2011

UIStoryboard Issues

Background

In August I joined a new start-up as lead (and only) iOS Developer. I managed to convince the founders that targeting iOS 5 was a good idea and as such I’ve embraced a lot of new iOS 5 only technologies in the app including UIStoryboard.

After a few months of development with UIStoryboard I’ve decided that the technology just isn’t mature enough to be used in a complex iOS application and have now replaced all* UIStoryboard with traditional NIBs.

(* I have left in standalone storyboards for parts of the app heavily in flux, but will be replacing this usage with NIBs in the future).

Storyboard Editor

The storyboard editor in Xcode 4 combines all the problems of the Interface editor (e.g. broken keyboard navigation, somewhat broken selection semantics, amnesia for useful settings like “show bounds”, etc) with the inability to edit interfaces on a small (17”) screen. Once the storyboard expands beyond a half dozen or so view controllers the storyboard editor becomes very hard to use, with constant panning and zooming to find the view controller you want to edit.

One problem with storyboards with lots of view controllers (my app had around 30 view controllers in a single storyboard) is that everything looks the same. Visually a lot of view controllers end up being some kind of variation on a white rectangle (esp. when zoomed out). I found myself tending to rely on a knowledge of the storyboard “geography” to find the view controller I was looking for. And even familiar with the layout of the view controllers I still found myself hunting and pecking for the right view controller (“oh no wait, that’s the parent UINavigationController, I must want the child instead”).

A somewhat related but inverse problem is that it seems to be impossible to use UITableView static cells & prototype cells outside of a storyboard. This seems strange. Being forced to use storyboards if you want to use this very useful feature is serious problem. I have to assume this is an oversight.

Spaghetti” Segues

With moderately complex storyboards the view controllers and their segues begin to resemble spaghetti. I found this especially common when I had multiple “detail” view controllers that could be accessible from each other (think of a twitter app - you can view people in a people table and tweets in a tweet table, and drill down in people/tweet detail screens. But you can also access a person detail screen from an individual tweet detail screen and vice versa). I wonder if the master view controller source list (presented on the left of storyboard editor) should not be the primary view for the editor, with the ability to focus on one view controller at a time?

Segue Identifiers

It becomes readily apparent that the segue identifier field (settable in the editor) is the best way to differentiate between segues in large prepareForSegue: implementations (see more on this later). It would be very handy if Xcode 4 supported a “warn on missing segue identifier” option when storyboards are “compiled” into individual NIBs. (feature request)

View Controller Identifiers

It is possible to assign view controllers in a storyboard an identifier. Unfortunately this identifier property is not exposed in the UIViewController class. This makes it very hard to perform safe introspection of the view controller hierarchy at runtime. It would be really nice if identifier was exposed for view controllers as well as for segues. (Feature request)

Push-only Segues

Segues are by default “additive” only: you can push a view controller onto the navigation stack or present it modally but it isn’t possible to perform other common navigation tasks without resorting to custom segues. For instance you can’t jump to a view controller further down the navigation stack or change the tab of a tab bar. And the ability to jump to an arbitrary view controller in the view controller hierarchy (without a push) doesn’t seem possible at all.

Custom segues do allow you to do some of this. In fact I have written a custom segue to jump to a different tab in UITabBarController, but it was rather hacky code to get around the fact that the segue automatically created a new destination view controller for me.

I think it would be handy if these, more complex segues, were built into the UIStoryboard system by default.

Misuse sender field.

A common iOS design pattern is to create a new detail view controller, populate it with the relevant detail and then present it (either push onto the navigation stack or present modally). Generally I’d accomplish this with a custom “initWithFoo:” method on the detail view controller.

CUser *theUser = [self.fetchedResultsController objectAtIndexPath:indexPath];
CUserProfileViewController *theViewController = [[CUserProfileViewController alloc] initWithUser:theUser];
UINavigationController *theNavigationController = [[UINavigationController alloc] initWithRootController:theViewController];
[self presentViewController:theNavigationController animated:YES completion:NULL];

With storyboarding there’s no clear way to pass data to a detail view controller. The best I could come up with was by abusing the sender parameter to pass the data the detail view controller needs, e.g.:

CUser *theUser = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:@"ID_USER_DETAIL" sender:theUser];

The performWithSegue: method would then take the data and hand it to the already created destination view controller:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([segue.identifier isEqualToString:@"ID_USER_DETAIL"])
        {
        UINavigationController *theNavigationController = AssertCast_(UINavigationController, segue.destinationViewController);
        CUserProfileViewController *theViewController = AssertCast_(CUserProfileViewController, theNavigationController.topViewController);
        theViewController.user = sender;
        }
    }

(Note I use my AssertCast_ macro to make sure my assumptions about the view hierarchy are correct, I’ve been bitten too many times in the past by bad view controller hierarchy assumptions to not be paranoid here)

Not only is this a lot of code and complexity to replace something that was rather simple before, it seems to be an abuse of the “sender” parameter. Sender should really be (at least according to tradition) the button or the table cell or the map annotation, etc that triggered the segue and not the data the destination view controller needs to configure itself.

I tried to build my own performSegueWithIdentifier:sender:userInfo: and prepareForSegue:sender:userInfo: methods in a UIViewController category but it was clear it was going to have to do some nasty things (like define a prepareForSegue:sender: in the category in question) and I decided it was a no-go.

Perhaps I’m missing something here and there is a better way to accomplish this.

Bloated prepareForSegue:

My root view controller has become a source view controller for lot of segues and therefore its prepareForSegue: has become a stupidly large method filled with a lot of “if (segue.identifier isEqualToString:@”…”)” statements in a row. I don’t like this. I much preferred the way the same code was distributed to many view controllers instead.

I find this problem causes the code to become more brittle and less flexible. If I change the view controller hierarchy I need to find the relevant block of code in the source view controller and move it to the new view controller. Previously I didn’t have to do this at all. This totally eliminates the flexibility that storyboards can provide.

No user defined relationships

This was really the nail in coffin for storyboards for me.

I needed to create a new container view controller type that could flip between multiple child view controllers (rather like a UITabBarController but with different UI and animation). I implemented the view controller with a child “viewControllers” property and got the transitions and UI working and then realised that I couldn’t wire it up in a UIStoryboard successfully. I quickly realised that only UINavigationController and UITabBarController could have non-segue relationships to other view controllers (*). This basically made it impossible to use one large storyboard and would need to use traditional techniques (static view controller instantiation in this case) and break my single monolithic storyboards up into smaller storyboards that I could load root view controllers from as needed. Unfortunately because of the spaghetti problem I discussed previously this was going to be ugly.

At this point, combined with the other problems and issues I’d encountered up to now I decided to rip out my storyboard and replace it with the traditional one (or more) NIB per view controller.

No code size benefits

I spent almost a day replacing my storyboard (and related code) with NIBs (I am sure I have introduced new bugs into the app in the process that will take further time to find and fix). In doing so I actually reduced the line count by about 400 lines of code. It’s pretty clear that storyboards wont reduce the total of number of lines code in the app and due to the problems with prepareForSegue: discussed previously I don’t think storyboards will allow you to iterate designs more quickly than using NIBs.

Is this my fault?

So I’m left wondering if this could my fault, that I’m missing something or just don’t understand how I should be using storyboards. I don’t think so. I do think that I could learn to stop worrying about the sender/userInfo issue and perhaps I could work out a smart way to solve the prepareForSegue: bloat problem. But really, I don’t have the time for this, I need to be able to implement UI in a speedy manner without having to solve the “how do I make this work with UIStoryboards” problem.

Summary

I do think the UIStoryboard technology has a lot of potential but as I’ve discussed there are some rather severe issues with the current implementation that make it burdensome to use. That said I look forward to further iterations of the technology. Also if anyone has worked around these problems or think I’m doing it wrong please let me know.

Jun 5, 2011

Calling a Turd a Turd

Apparently my previous post is getting called out as “defensive” on the MacIndie blog. Well, again I assume it’s my post because the author so far hasn’t bothered to mention my post directly. Oh well. We’ll read between the lines and assume the author is targeting me. I’m not really worried if the post came over as defensive or not - it was merely stating why I believe that criticising and being open to criticism is a good thing.

I think the author is going along with Marcus’ original point: in that it is the almost solely senior members of the community who were critical. This is ignoring all the criticism from folks like John Gruber, Khoi Vinh, PC Mag (eww), The Daily Telegraph (double eww) and even the App reviews themselves (which as all good developers know - should be utterly ignored out of hand, because the peons know nothing!).

So this shows that it wasn’t just the old “grey beard” section of the Cocoa dev community(tm) - it was pretty much everybody. The app was wildly slammed by everyone because everyone saw it. It probably had the largest launch of any iOS app - and everyone saw it to be unpolished, slow, buggy and at the end of the day owned by a psychopath who makes Bond villains look huggable. In comparison the criticism from the old timers was relatively small (and if I recall correctly, tame).

Anyone parroting the “grey beard” line is either forgetting the mainstream criticism or is incapable of critical thinking.

I’m also a little bit confused because, no one officially knew who worked on the The Daily (although I’d say it was moderately common knowledge a few days after the launch). How can the community be accused of turning on one of its own if we had no clue who worked on the app? As far as we knew Murdoch probably outsourced it to indentured iOS child programmers in the jungles of Peru (no offense to real Peruvian child slave programmers - I’m sure you do great work).

A quick thought experiment: let’s say you were the client paying for the contractors (and sub-contractors) who worked on The Daily. Would you personally have been happy with the state it was in when it was released? I wouldn’t have been. I would have pushed as much as possible to move the deadline so that the blatant problems could be fixed. The fact that it was released anyway means to me, as is often the case with software, that making the deadline trumped the product quality.

I’d be really surprised if anyone was happy with the quality of the app when it was released (the same can almost always be said for any software release). So should we shut up when something is released with great fanfare and yet it, well quite frankly, isn’t very good? These hypothetical kids in Peru have it shit already, they’re working for the anti-christ as it is. Do they really need all these old timers they look up to and respect shitting on something they’ve poured their time and energy into?

The truth is children didn’t write the app. Grown adults did, adults who should expect and desire criticism from their peers. Not wanting or accepting criticism means you just want false platitudes. You don’t have to go too far to find them on the internet. Yes, writing software is hard work, we get it — but we all do it. Working as a sub-contractor to the anti-christ sounds like absolutely fucking miserable work, we get that too — but if you’ve got the stomach for it — good for you. But just because something is hard, or unpleasant to do — doesn’t mean that the end result doesn’t deserve criticism if it just isn’t very good.

That doesn’t diminish the fact that criticism is hard to take. It is, I’m personally awful at taking criticism. And developer egos are very fragile things and easily crushed. Having them crushed by your peers is certainly harder still. But without strong criticism, you end up applauding mediocrity. Fuck that. Give me a snarky bastard developer who tells me what I’m doing is crap. I’d take that any day over someone who tells me every single thing I do is wonderful.

I’ll end this post with words from Winston Churchill. who was much better at crafting them than I could ever hope to be:

Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things.”

Jun 4, 2011

90% of Everything is Crap

Time to bring this blog back from the dead with a little pre-WWDC controversy!

Apparently there’s a disturbing trend going on in the Cocoa development community. We old timers aren’t being excellent to each other & newcomers to the community. Marcus Zarra in his blog, “Cocoa is My Girlfriend”, declaims against the criticism his work on The Daily iPad app received when it was released and is dismayed this criticism is coming from predominately the “grey beards”.

I think I’m firmly in the group of “grey beards” Marcus rails against, because of two facts: I am a miserable old curmudgeon and when The Daily first came out I was very critical of it (and in fact a critical tweet of mine managed to get the product I work on grubered).

Marcus spends a significant portion of his blog post elaborating on this trend, explaining how the older developers are turning on one another and their creations. For the rest of the blog post Marcus explains, well defends really, his work on The Daily.

You can read it all on his blog here: http://www.cimgf.com/2011/06/03/why-so-serious/

I think Marcus is wrong. I’m not going to accept his portrayal of this portion of the Mac OS X/iOS development community. I think the veterans in the community are no more or less critical today than they have ever been. As a general rule I think developers are highly critical by nature and by training, we have to be. And as a flip side to that, developers have to learn not to take all criticism personally.

We spend all day being told (by a program no less) how many errors we’ve just made writing a certain piece of code. When we finally fix all the obvious mistakes and can run the software, we hand the fruits of our labours off to folks whose very job is to be painstakingly critical of our work. When they find problems with our work (and they do, guaranteed) we track these mistakes in databases that grow to be huge mountains of preserved failures.

This is how good software is made. We become very critical of our work and of the software itself. We have to be critical so we know what we can fix and improve. If we took all this criticism personally, software developers would all be nervous wrecks. We learn to treat criticism not as accusation of failure, but as part of the process of making something good. But sometimes it is hard to do this and you get personally attached. That’s when the criticism feels like an attack on you.

Despite the dangers of taking it personally, I actually like this process. I think strong criticism is a good thing. You can’t improve something if you think it is perfect and often the creator is too involved with their creation to be able to recognize the flaws. I want to know when something I have worked on is broken, or just isn’t that great or could be done better. This is how I improve and learn. And I actually think society could benefit from becoming more critical, it seems to have become impolite to be critical. I hate to break it to you but your child is not gifted and talented.

I think Marcus is taking these criticisms personally, it probably is hard not to. He has poured a lot of time and energy into this product and it was put into the spotlight and promptly demolished by the community. The best thing he, or anyone else this position could do at this point is to prove the critics wrong. Fix the bugs or the performance problems, fix those cosmetic issues, make the software really fucking excellent. Blaming portions of the community for being overly critical is divisive and doesn’t make you or your software look any better.

I don’t envy Marcus the job though, I’ve worked as a contractor for large, megalomaniacal corporations and you can’t always control the outcome. Sometimes you have to shrug your shoulders, smile, nod and just do as the client asks, even if you know it is going to produce a substandard outcome. That’s the nature of software consultancy.

And in the spirit of accepting criticism, comments are on for this post! (Don’t forget to criticise my indent style!)

Jul 31, 2010

I name that UIColor in three!

You’re working on a custom iPhoneOS view and you want it to use colours from the standard iPhone OS colour palette. Your first impulse is to check the defined colours in UIInterface.h - but there are only a grand total of five colours defined in that header. Your next and probably last impulse is to break out the colour picker and use the eye-dropper tool to sample the exact RGB value from the screen itself.

There are two problems with using an eye-dropper tool. The first problem is that by sampling the on screen pixel value you can only get the composited red, green, blue values; you cannot get the alpha value at all. If the original colour had an alpha value then the final colour you might get will not much the original colour at all. The second problem is that you can’t easily be sure that a colour you sample directly off the screen uses the same colour profile as the original.

I decided instead to use Intruments to probe the application and find out exactly what RGBA colour was being used by UIKit. I modified my project to display the element I wanted to find out the colour of (in my case it was the colour of a UITableView’s section footer label) and then ran the application through Intruments.

After a little trial and error (and some help from Kevin Ballard to work out exactly how to output the RGBA values) I had an Instrument that would display all parameters passed to [UIColor initWithRed:green:blue:alpha] (Screenshot)

As you can see from the screenshot, this works almost too well, with Intruments displaying almost too much information. But it is actually quite easy to narrow down the data to exactly what you’re looking for (screenshot).

Note that you wont get all colours. Just those created via [UIColor initWithRed:green:blue:alpha:] but the same technique can easily be used to probe for colours created via other methods or even via CG functions. It’s also pretty easy to use gdb to break on the relevant symbol and print out the parameters - however once you have this instrument in place it’s really quick and easy to run through an application and capture all colours. You can even export the colours into CSV file for easy manipulation.

You can download the Instrument here, copy it to

~/Library/Application Support/Instruments/PlugIns/Instruments
and then drag the instrument from Instruments Library into your workflow.

Jun 25, 2010

I wouldn’t hire an iPhone developer who charges less than $999.95/hour

If you followed the link from Mike Lee’s “motherfucker” blog to here, welcome! You’re probably looking for the iPhoneSWPro link. There you’ll be able to find out how to hire competent, professional, ego-free (for certain values of free) iPhone (and iPad) developers (for somewhat south of $1000/hour).

Of course, if you want the best iOS developer money can buy, then please, hire Mike. Rest assured, you will get the best of the best. Don’t believe me? Just ask Mike.

Dec 17, 2009

Add to Pinboard

In my previous post I suggested adapting my Python script for use in a Snow Leopard service. I decided to quickly whip this up myself. So here is a (Snow Leopard only!) service that can add URLs to pinboard.in. Unzip the file and copy it to ~/Library/Services then run this little shell script to set up a keychain item for your pinboard account:

1
2
3
4
5
6
#!/bin/sh

HOST=api.pinboard.in
read -p "Username: " USERNAME
read -p "Password: " -s PASSWORD
security add-internet-password -U -r http -s "$HOST" -a "$USERNAME" -w "$PASSWORD"

And the script also uses the BeautifulSoup 3rd party python module to extract the title of the webpage you’re linking to. You’ll need to install beautiful soup:

sudo easy_install beautifulsoup

If you’ve correctly installed the service you can enable/disable it and assign it a keyboard shortcut from the Keyboard preference pane:

[Screen shot 2009-12-17 at 10.09.36][] When enabled you should be able to see an entry in the application’s service menu: [Screen shot 2009-12-17 at 10.03.06][] [Screen shot 2009-12-17 at 10.09.36]: http://www.flickr.com/photos/61285556@N00/4192220957 “View ‘Screen shot 2009-12-17 at 10.09.36’ on Flickr.com” [Screen shot 2009-12-17 at 10.03.06]: http://www.flickr.com/photos/61285556@N00/4192209095 “View ‘Screen shot 2009-12-17 at 10.03.06’ on Flickr.com”

Next → Page 1 of 24