If you’re an iOS dev and are interested in health apps, I’ve just posted some code for working with BLE heart rate monitors. If you’re interested in helping out, I could really use some people with more devices, as I only have one that I’ve tested with.

New Stuff

Well, I guess at this point, anything I post is new. Does the previous post really reference something called “Hudson”? Wow.

Anyway, I’m in the middle of revamping my flash card app, cardGRIND. Check out the new marketing site here:

Also doing the mailing list thing if you’re inclined, see the form in the header.


Saving Time & Money Through Build Automation: Intro to Hudson

Just gave a quick talk yesterday at BarCamp San Diego 8 about using Hudson for build automation.  You can check out the slide deck here on Slideshare.

Read More

Fun with CGRect

I saw this post on Dr. Touch today on CGRect tricks. Very good stuff, as he mentions, CGRect is probably one of the most used structures in iPhone programming, especially when doing UI work, since the frame property of UIView is the basis for determining how things are laid out on screen.

Dr. Touch’s article goes over the following, read his article for more on these subjects:

  • Creating with CGRectMake()
  • Transforming with CGRectInset() and UIEdgeInsetsInsetRect()
  • Intersection tests with CGRectContainsPoint() and CGRectIntersectsRect()
  • Creating and loading from a dictionary representation with CGRectCreateDictionaryRepresentation() and CGRectMakeWithDictionaryRepresentation()

The topic of CGRect is on my list of blog post ideas, so I’ll go ahead and add a couple of my own CGRect tricks I’ve found useful.

Null, Empty/Zero, and Infinite rectangles

There are three CGRect constants that can come in useful: CGRectNull, CGRectZero and CGRectInfinite.  These are matched by three comparison functions, CGRectIsNull(), CGRectIsEmpty(), CGRectIsInfinite().

CGRectNull and CGRectIsNull() deal with the concept of the null set, i.e. the result of unioning two disjoint rectangles.  CGRectInfinite and CGRectIsInfinite() are all about a rectangle with no bounds.

There is a subtle difference between the functionality of CGRectZero and CGRectIsEmpty(). CGRectZero is simply a rect with an origin of 0,0 and a size of 0. CGRectIsEmpty(), however, returns true for either CGRectZero or CGRectNull, which is an important distinction to make.

Comparing CGRects

Since CGRect is a structure, comparing for equality isn’t as simple as 

if(rectA == rectB)

But never fear, CGRectEqualToRect() is here! CGRectEqualToRect() compares to CGRects, and returns a bool letting you know if they are equivalent (equivalent in this context meaning the two rectangles have the same origin, and the same size).  

Here’s a snippet of example code:

//is the tab bar controller's frame the same as when we initialized?
    //then we whip it into shape.
    tabBarController.view.frame = tabBarFrame;

The problem being solved here was that the frame of a UITabBarController was being mysteriously being reset by “mysterious forces” (which turned out to be presentModalViewController:animated:). The above snipped of code is called when a change in the frame is observed, forcing the frame back to a state I specified during initialization.

CGRectUnion is UIScrollView’s best friend

So here’s the scenario: you have a UIScrollView with a bunch of subviews, which can dynamically resize and lay themselves out. That’s all well and good, but how do you set the contentSize of the scroll view so that the user can see all the subviews?

If you know the top-left most and bottom-right most view, the answer is simple, use those points to define a rectangle, then add some padding.  Which in Core Graphics terms, means CGRectUnion() and CGRectInset():

// get the rectangle that encompasses all of the dynamic content
CGRect theUnion = CGRectUnion(topLeftView.frame, bottomRightView.frame);
// add some padding to top and bottom (negative value adds padding, positive is an inset)
CGRect paddedUnion = CGRectInset(theUnion, 0, -20);
// in the end, we really only need the size of the rect
contentScroller.contentSize = paddedUnion.size;

Easy enough!

We interrupt our regularly-scheduled substantive discourse to bring you 2 1/2 minutes of nerding out.

How To: Quickly Organize Groups in Xcode

I must have missed the bus on this one. So, one of my biggest hang-ups with Xcode is the weird disconnect between what it calls “Groups” and folders on the file system. I do my bestest to keep my code organized in Xcode as well as on the disk, which sometimes requires removing and re-adding files in the IDE. This can lead to really disorganized and cluttered groups, which makes it hard to find files.

Anyway, I was struggling to keep a 200+ file group sorted in Xcode one day, and stumbled upon, completely by accident, a really, really simple way of doing it.

Say you have a group like the following, which you’d like to get into alphabetical order:

Now, in the left panel, click on the name of the group (here, “Pill Images”), and make sure the top right files panel is pulled down. Click on a file in the top right, and hit Command-A to select all.

Now just drag that set of files back into the group in the left panel, and boom, ordered group:

Easy enough, right?

Looking for iPhone, Android and Blackberry developers!

Hey everybody - looking for some developers (especially iPhone) for some big projects coming up. Drop me a line if you know somebody, or even better, are somebody!

How Xbox Achievements Work’s Engineering Blog has an interesting piece on how the Achievements system was implemented. Very interesting read, even as a non-Xbox developer.  I’ve always been curious how console development worked, and how that software has to integrate with services such as Xbox Live.

Seeing as how the iOS platform is due to get its own social gaming platform, Game Center, it will be interesting to see how the two systems compare.

Dear Future James: The iPhone Simulator is Case Insensitive, iPhones are Case Sensitive

July 20, 2010

Dear Future James,

If you are reading this, you have probably forgotten (again) that the iPhone Simulator is for some reason case insensitive.  As you might recall (probably not), all iOS devices are case sensitive, and are, in fact, very picky about case.

I’m writing to remind you of this, so that you don’t spend another hour tracking down a “but it works in the simulator!” type bug.  We did it today, we did it a couple months ago, and we really need to stop doing it.

Today’s bug involved a lack of a launch image, but only on the device.  This is “First Day on the Job” type stuff, Jim.  A monkey with Xcode has a good chance of getting this right. Anyway, you were clever enough to remember that the launch image needed to be a PNG file, but named it “default.png” instead of “Default.png.”  This, of course, works in the simulator, but not on the device.

So next time, be sure to engage that amazing attention-to-detail you have, and name the damn file correctly. Or even better, just set the UILaunchImageFile in the info.plist. Then you can name the file whatever you’d like!

Past James 

Quick Thoughts on the iPhone 4 “Antennagate”

  1. I don’t care.
  2. People will still buy iPhone 4s, and all of the other iOS devices.
  3. a = The number of people who own iPhone 4s and complain about the antenna
    b = The number of people who don’t own iPhone 4s and complain about the antenna

    a < b