*

Our Beautiful Faces is Jeremy Hunt Schoenherr and he does iPhone development, for now.

Sep 1

Day Job - MLB.com At Bat now with Push/In-App Purchases

Just a quick update. MLB.com updated the iPhone app to have Push Notifications and In-App Purchasing to stream individual games. Pretty fun stuff to work on, and big thanks to all the different teams at MLB.com that brought this together, especially Warner, Emily, Mohammad and Tracy who all did some great dev on the actual client.. Great stuff.

TUAW weighs in on it.

iTunes link.


Comments (View)
Mar 26

DevTip: Abuse threads

Sometimes your interfaces can become clunky. You hit a button, or slide a slider and things get all stuttery. No good. People hate that and so should you. Usually this is because when your control (button, slider, tab, etc) calls back to your handler, there is too much work going on.

Just start a new thread. This sounds simple, but sometimes people over look it. I ran into this when I was adding the volume control on the new audio stream player for MLB.com At Bat. I thought, yeah, no problem, I can make a call to the audio session and store the value in my user defaults in real time. Easy! But no, it made the volume control sticky, so I had to spawn threads. See below.

In Interface Builder, connect your control to your handler for the given event the IBAction below, and then in that method, start a thread and don’t wait around for the result.

- (void) threadedTargetMethod:(id)object {
   //Do you time consuming stuff
}


- (IBAction) targetMethod:(id)sender {
   [self performSelectorOnMainThread:@selector(threadedTargetMethod:) 
                          withObject:nil 
                       waitUntilDone:NO];
}


Comments (View)
Mar 5

Comments (View)
Feb 26

Comments (View)
Feb 25
So, update from the day job at MLB.com. It’s the first day of Spring Training. Go grab the At Bat Lite iPhone app.
Everyone who had At Bat last year should have this as a free update. The Lite version will give you a pretty Scoreboard + Gameday for spring training games and WBC games that have it. In a few weeks, we’ll have At Bat 2009 out there. Gameday Audio + Gameday + In-Game video highlights to make you happy for the whole season.

So, update from the day job at MLB.com. It’s the first day of Spring Training. Go grab the At Bat Lite iPhone app.

Everyone who had At Bat last year should have this as a free update. The Lite version will give you a pretty Scoreboard + Gameday for spring training games and WBC games that have it. In a few weeks, we’ll have At Bat 2009 out there. Gameday Audio + Gameday + In-Game video highlights to make you happy for the whole season.


Comments (View)
Feb 20

DevTip: Always check your distribution builds

Old post, but very useful, Craig Hockenberry walks you through testing your distribution builds.  Do this to make sure you know exactly what you are submitting to iTunes Connect.  Sometimes build settings vary between targets/build configs, and the only way to know what you have is to run what you submit.


Comments (View)
Feb 7

DevTip: Don’t always recycle UITableViewCells

So, Our Beautiful Faces is one thing, and my day job is another. During the day I work for MLB.com, mostly working on their iPhone app At Bat and other mobile stuff. Anyway, I am in the middle of refactoring At Bat for this season, and have been trying to optimize certain things.

One thing that always needs to be optimized is table scrolling. Choppy is bad. Real bad. Drives people crazy.  And it inevitably happens. You have add a lot of subviews because there is a lot of data to display in each UITableViewCell, and eventually, you get to a point where rendering these cells take a little too long.

There’s lots of things you can do for this. You can stop using subviews and just draw everything to the cell’s contentView when drawRect is called. Sounds like a lot of work.  You can make everything opaque. This does render faster, but I’ve never noticed it making much of a difference visually. You can only update subViews if they’ve actually changed. If you have a UIImageView as a subview, don’t blindly call setImage on it over and over, unless that image is actually different.

But there’s something else you can do which is a little less obvious. Cell reuse is awesome and for the most part, should always be used. Especially for UITableView’s of arbitrary length. However, if you always have a reasonable number of cells, let’s say 5-50, and you know you will never really need more than that, then why not have all of them in memory? It’s not gonna break the bank to have them all ready so why keep making it render all the new information each time?

So, what do you need? Not much. Basically, instead of trying to dequeue cells from the UITableView, keep track of them yourself in a dictionary. See in the following code snippet.

NSMutableDictionary *myDictionary;

...

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{

    NSString *cellId = [NSString:stringWithFormat:@"id_%d_%d];

    UITableViewCell *cell;

    if ([myDictionary objectForKey:cellId]) {

        cell = (UITableViewCell*)[myDictionary objectForKey:cellId];
        //update cell if necessary

    } else {
        cell = [self createYourCell:indexPath];
        [myDictionary setObject:cell forKey:cellId];
    }
    return cell;

}

Obviously, if you have too many cells, this won’t work. Also, make sure your prepareForReuse method on your cell isn’t wiping things out. The only reason this helps out at all, is because it doesn’t need to redraw all the subviews. So, if you wipe them all out by resetting them in your prepareForReuse, then you are defeating the purpose.

One thing, the first time you scroll, it may still be a little choppy. This is because we are still creating the cells as we scroll. Yuck. So how do we get around this? Easy, after the UITableView loads, or maybe after you have loaded your data from the network and parsed it, iterate through all the cells manually. Create an NSIndexPath for every cell you will need and then call your method that is creating the actual cell. In the example above that method is  [self createYourCell:indexPath]. Then store the result in the NSMutableDictionary. Done.

This is a simple way to make scrolling fly when developing on the iPhone SDK if you have a reasonable number of cells that don’t change too often.

Hopefully I’ll have more developer tips as time go on, but I found this particular thing to really help me out, and hopefully it will help you as well.

//jeremy


Comments (View)
Jan 30

Comments (View)
Jan 29

Death Cab for Cutie app released!

So, at long last, the DCfC app is finally live in the App Store. It was a fun project. Props to Zeitgeist Management and the Band for making it such a fun experience. Oh, and big ups to Dan VonB for pointing them in my direction. :)

The app gives you all the DCfC info you could want. 10 full songs packaged in the app (not streaming) so you can listen whenever you want. Tours (with some sweet maps), Discography, Photos, Videos, and some other fun stuff.

Click here to download.


Comments (View)
Page 1 of 1