iOS – Customize Table View Cells

Ever wanted to have alternated colors on your table view cells? If so, you’ve probably done something inside of cellForRowAtIndexPath and applied a background color to your cell there.

Would you be surprised to know that’s completely wrong?  Yup.  Wrong.  WRONG WRONG WRONG.

I didn’t know this, but any styles applied to cells based on state or whatever should really be in willDisplayCell – NOT when you configure the cell itself!  Per Apple’s documentation for the Table View delegate –

“A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.”

Keep this in mind especially if you’re using a NSFetchedResultsController with CoreData.  You’ll have to issue a [tableView reloadRowsAtIndexPaths:…] in your didChangeObject method.  For some reason, at least in iOS 4.3.3, the willDisplayCell isn’t firing with the default code Apple recommends when using a Fetched Results Controller.  Adding that reload does the trick.

iTunes Connect – Invalid Binary

I spent the past week pulling out my hair trying to submit an update for Centare’s EyeOnWeather application to iTunes Connect.  I kept getting a reject from the system and all I got for an error message was “Invalid Binary.”  THANKS, THAT’S SOOPER.

Eventually I ended up attempting to contact iTunes Connect Support for further details.  I thought it might have been missing icons, malformed Info.plist, something.  I haven’t changed anything in the project drastically with how it builds, so I was at a loss.  Turns out, I was picking the wrong provisioning profile in my setup.  Man I felt stupid.  Ends up that I’m not crazy – Apple’s documentation on how to set up your project for building still only references Xcode 3.  Awesome for the rest of the world using Xcode 4.  Here are some tips I got from Apple iTunes Connect support for pulling in information to submit to their developer team:

(replace 'path/to/myapp.app" with the actual path to your application):

codesign --verify -vvvv -R='anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and certificate leaf[field.1.2.840.113635.100.6.1.4] exists' /path/to/myapp.app

codesign -dvv /path/to/myapp.app

- This command is useful to see what certificate was used to sign your app. If under the section labeled "Authority" it says iPhone Developer, this means that your app was signed with your Developer Certificate. If it says iPhone Distribution, this means that it was signed with your Distribution Certificate.

codesign -d --entitlements - /path/to/myapp.app

I ended up pulling the EyeOnWeather.app file out of my archive bundle to be sure I was testing what I sent up to iTunes Connect.  You can also just do a “Build for Archive” and then right click your .app in Xcode under Product and “Show In Finder”.  Drag that file into Terminal and it’ll paste the full path & filename.

Running those commands gave me confirmation of this – I was code signing with my developer profile.  Even though you pick the Distribution certificate in the submission window for uploading, it doesn’t change the signature of the app.  The solution was to go into my setup for the build and change the Code Signing Identity for the “Release” configuration to the Distribution profile.  I deleted the old “Distribution” build configuration that I had created back in the Xcode 3 days as it’s no longer appropriate.

This link is the defacto WTF help me document for code signing in Xcode 4:
Technical Note TN2250 – Understanding and Resolving Code Signing Issues

Xcode 4 – Problem submitting App with Static Library

I’m submitting a new version of my Migraine Diary App to the App Store and was running into problems with Xcode 4 giving me the following error: “[Your App Name] does not contain a single-bundle application or contains multiple products. Please select another archive, or adjust your scheme to create a single-bundle application.”

There is an issue or maybe it’s an intentional design thing with Xcode 4 and how it handles statically built libraries being included in your project.  I’m specifically using Core Plot and it’s instruction set hasn’t been updated for Xcode 4 yet.  Here are the things I had to do to get Core Plot to bundle correctly with my App to submit it:

  1. Click on the Core Plot project which should be a child of your App’s project.
  2. Click on the Project CorePlot-CocoaTouch and go to the Build Settings.  Set “Skip Install” to Yes.
  3. Click on the CorePlot-CocoaTouch target and set “Skip Install” to Yes.
  4. Click Build Phases and under Copy Headers, move all of the Public and Private entries to the Project section.

You should then be able to build your project for Archive and submit to Apple.

Thanks to Apple Dev Forums – https://devforums.apple.com/thread/86137

iOS Basics – UINavigation Controller & Back Button Text

I’ve brought an old project out of the moth balls recently, the Migraine Diary application I wrote as part of my master’s thesis.  It was my first “real” iPhone app and I call tell I didn’t know what I was doing entirely looking through the code.  What this has forced me to do, however, is re-learn some of the basics of iOS development and of Apple design patterns.  I have been spending some time back in the Apple developer documentation and will probably be posting some of the gotchas that tripped me up two years ago and I’m solving now with the better, more elegant solution.

Navigation controllers are very useful things to have in your app, and are probably the easiest thing to implement WRONG.  Two years ago, I assumed any time I needed a navigation bar up top that I needed to create a UINavigationController and make my view the root controller of it.  Silly me.

One of the problems I was facing in the Migraine Diary app was changing the back button text when I was one or more levels deep into a navigation controller.  My main view was titled “Journal Entries” and my child view “Journal Entry”.  By default, the controller will title the back button as “Journal Entries” which you can see clutters up the screen.

I found a lot of ways of hacking the title online, but there is really only one “right way” according to Apple.  The button titled “Journal Entries” is actually owned by the parent view.  Before you push the child view onto the navigation controller, do something like this:

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@”Back” style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backButton];
[backButton release];

Take note that you’re referring to [self navigationItem] not [[self navigationController] navigationItem] since you are in the PARENT controller.

That’s it!

Mac OS X – Adding a loopback alias

I do a lot of local web development on my MacBook Pro.  Frequently I had multiple tiers of servers running – a Jetty instance running the web tier and a JBoss/EJB server doing the business tier behind it.  The problem is JBoss opens up so many ports on a particular network adapter and trying to get JBoss and Jetty to share a single IP is a nightmare.  So the easier way is to just create a new IP or alias your localhost (127.0.0.1) into something like 127.0.0.2.  When you start up Jetty, you pass in the binding IP of .2 and then JBoss and Jetty place nice with each other.

The Mac OS command (at least 10.6) to create an alias is:

ifconfig lo0 alias 127.0.0.2

and to delete:

ifconfig lo0 -alias 127.0.0.2

This is not persistent – the alias will not survive a reboot.  I don’t need the alias often even to require it to be permanent.  If you’re curious how to keep it permanent, let me know and I’ll post that.  This is the hacker way to do it on the command line.  There is a much easier way to do it through the GUI but this way doesn’t stick around on the reboot, which is one of my requirements for my project – no retaining traces. 🙂

CDMA / Verizon iPhone

There has been quite a bit of press about the upcoming Verizon / CDMA iPhone.  I’m happy to hear that AT&T will finally lose the monopoly on the iPhone in the United States, but I’m disappointed that nothing has come out yet about T-Mobile carrying the GMS version of the phone.  AT&T needs the competition to spread out the massive amount of users onto another network because frankly, they can’t handle the amount of growth they’ve experienced.  The iPhone is a great device, and I’ve had nothing but a positive experience for the most part with AT&T.

I’ll probably never switch from AT&T over to Verizon for the simple fact that GSM provides SIM cards, whereas CDMA does not.  I like having the option available to me to swap my SIM into a different device, like when I go camping, so that I don’t risk damaging the $400+ device when I don’t need to.  Of course, the iPhone 4’s micro-SIM provides its own unique challenges, but a simple physical adapter allows it to be used in an older traditional SIM card holder.

CDMA phones, at least in the USA, require the phone provider to activate each device and you cannot swap on a whim.  Most people could care less.  I on the other hand like being able to switch around equipment when needed, and not having to pay the provider to do it.

Installing MySQL 5.5.8 on Mac OS X Snow Leopard

Installing MySQL should be a no brainer on any operating system, especially with how mature of a product it is.  Apparently that assumption is incorrect.  I tried installing the most recent GA release of MySQL on my new Snow Leopard machine, and found I couldn’t start the blasted server.  I’ve become lazy the older I get – I don’t want to screw around with shell scripts, hacking this tweaking that.  If I’m provided a Mac-based installer I WANT IT TO WORK.  So, if you’re like me and are frustrated as all hell with not being able to get MySQL to start via System Preferences after installing the 64-bit version (maybe 32-bit as well), do the following:

  1. Drop into Terminal.app
  2. Type: sudo /Applications/TextEdit.app/Contents/MacOS/TextEdit /usr/local/mysql/support-files/mysql.server
  3. Find the line starting with basedir and datadir and replace with:
    basedir=/usr/local/mysql
    datadir=/usr/local/mysql/data
  4. Save the file
  5. Start MySQL using the System Preferences pane button.

I’m amazed this is the fix and that the MySQL team overlooked the configuration change in their packaging.  Very irritating.  Enjoy.

iPhone Migraine Diary

I may have mentioned it before, but I created a Migraine Diary application for the iPhone as my master’s captone/thesis project.  The school year finished out for me and I submitted the application to Apple on the 29th.  Two days – TWO DAYS – later they approved it and it’s listed in iTunes!

Head on over to Net Workz LLC to find the app.

I still have a lot of work left to do before I’m really happy with it.  Help screens, more graphing, and encryption are two things I really need to get out there.  Until then, enjoy!

Xcode SCM & build directory

Xcode has a build directory inside of your project, which you shouldn’t be including in your source code management repository.  Simply said, those files change so much and are “discardable”.  There is no way to easily exclude this directory from your repository.  The accepted way to fix this (after some digging) is to simply move the build directory for Xcode to a temporary folder.

To move the build directory, click on the Xcode menu in your menu bar, and click on Preferences.  Change the folder under “Building” to a temporary folder.  I created a tmp directory in my user folder.

Xcode Preferences Build

Thoughts on the iPhone 3GS

Everyone is giving their two cents about the iPhone 3GS.  I’m excited to see that Apple is releasing a faster phone that still feels like the first generation iPhone.  Developers are used to a specific screen size for instance.  Drastically changing the environment will create the discord other cell phone manufacturers feel when it comes to 3rd party applications.

I do suspect, however, that next year will bring drastic change to the iPhone.  Apple is still getting to where they really wanted the 1st generation iPhone to be.  They realized that its easy to make their own hardware and software, but its hard when dealing with so many third parties.  Cell phone carriers like AT&T stand in the way of real progress.  Why doesn’t Apple follow suit with Virgin and create their own private label cell phone company?  I suspect that would give them a lot more flexibility in pricing and give them the ability to put whatever carrier they want behind the name.

Overall, I am happy with AT&T at the moment.  I am pissed to hear MMS and tethering won’t be available this coming week for the iPhone 3.0 launch.  I refuse to pay any more money for something that I can get for free by putting my SIM card into an OLDER phone.  Silly AT&T, you’re the death of the iPhone in the US.