git-pull-everything, including submodules

If you have a submodule inside your git repo, it’s often handy to just pull all the changes from remote, including your actual git repo, but also all your submodules. If you are on git 1.7.3 or later, you can just add a ~/.gitconfig alias like the following:

[alias]
    pullall = !git pull --recurse-submodules && git submodule update --recursive

The 2nd command (git submodule update) is needed to actually check out the new commits (the ones your master repository points to) in the submodules.

Example:

$ git pullall
remote: Counting objects: 24, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 13 (delta 7), reused 0 (delta 0)
Unpacking objects: 100% (13/13), done.
From gitcube:/home/git/pchess
   9f19a46..915ba55  master     -> origin/master
Fetching submodule server/libs/erlyweb
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
From github.com:ettore/erlyweb
   a319f79..6e0ac0c  master     -> origin/master
Updating 9f19a46..915ba55
Fast-forward
 server/bin/pchess_rollout.sh              | 13 +++++++++----
 server/libs/erlyweb                       |  2 +-
 server/pchesslauncher.erl                 |  5 ++---
 /snip/
 8 files changed, 47 insertions(+), 192 deletions(-)
 delete mode 100644 server/pchess/rsrc/apn_dev.pem
 delete mode 100644 server/pchess/rsrc/rsrc.contents.txt
 delete mode 100644 server/pchess/rsrc/yaws_out.log
Advertisement

When to (not) use UIViewController::loadView

It is pretty confusing how one is supposed to use the loadView method. My initial understanding was “do not implement loadView if you have a nib file, do implement it to create your view controller’s view in code.” Fine. But what if you are writing a middle layer UIViewController subclass that programmatically constructs part of the view hierarchy? Where should you do so? The answer is the UIViewController::loadView documentation, so let’s study it line by line (more or less).

- (void)loadView

You should never call this method directly. The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.

So if you refer to [self view] early on you may trigger loadView if your view controller’s view property is still nil.

If the view controller has an associated nib file, this method loads the view from the nib file. […] If the view controller does not have an associated nib file, this method creates a plain UIView object instead.

This is key: loadView IS called even if your v.c. uses a nib file. We can infer that UIViewController’s implementation of loadView NEEDS to be reached since that’s the only place that can possibly do “load the view from the nib file.

If you use Interface Builder to create your views and initialize the view controller, you must not override this method. You can override this method in order to create your views manually. […] Your custom implementation of this method should not call super.

Ok, this makes sense: if your v.c. uses a nib, do not override loadView. However this has subtle ramifications. If you have a hierarchy of view controllers such as AppVC : MyFrameworkVC : UIViewController, it follows that MyFrameworkVC must ALSO NOT override loadView. If it did, its custom implementation is required not to call [super loadView] which would imply that the [UIViewController loadView] logic (that parses the nib, see above) will not be invoked. And that would be wrong.

So this means that loadView is just meant to build the view hierarchy from scratch. Nothing else. It is an application-level method and should be extended once in application code only.

Finally,

If you want to perform any additional initialization of your views, do so in the viewDidLoad method.

leaves it open to programmatically create new subviews in viewDidLoad, if needed, whether you’re using nibs or not.

Final corollary

All of this made me realize something perhaps obvious to many: Apple docs are targeted toward application coders, not much framework developers. That’s more likely their target audience. Once you make this realization (totally not obvious to me) the docs make more sense.

Summary

– if you’re writing framework code, never implement loadView. You can’t make the assumption your clients will use nibs or not. Do not choose for them: you’ll end up with clusterfucks like Three20, which does everything wrong (plenty of [super loadView] there). If you have some view initialization code that your subclasses might benefit from, put it in a new method, such as loadBaseView.

– if you’re writing application code and you use nibs, never implement loadView. Stick to viewDidLoad.

– if you’re writing application code and you do NOT use nibs, implement loadView and don’t call [super loadView]. Your loadView code should produce a functional and complete view hierarchy and assign the v.c. view property.

Localizing Nibs

Localizing Nib/Xib files is tedious and error prone. You want to reduce the manual edit to a minimum. (Basically, just the traslation.) Oversights and other weirdness may still happen though. This is the process I follow.

  1. Save Nib in en.lproj folder.
  2. In Xcode, select the Nib, open the Utilities pane and select the first tab (View > Utilities > File Inspector) and add a localization (e.g. Italian). Xcode will create a new file in the right location (it.lproj folder).
  3. From Terminal:
# extract all strings from original nib file
$ ibtool --generate-strings-file text.strings en.lproj/MyNib.xib 

# open file in Xcode, translate all the strings and save
$ open text.strings

# create a new nib exactly like the original but with the localized strings
$ ibtool --strings-file text.strings --write it.lproj/MyNib.xib en.lproj/MyNib.xib

Finally, Run the app. If the localized Nib is not displayed, it’s because iOS is holding a cache of the Nib file. Remove the app from the simulator or the device and reinstall it. Now it should show the new localized Nib.

How to view XML source in Mobile Safari

I see a lot of XML code at Goodreads while working on their iOS app, but some time ago I realized I didn’t have an easy way to see the XML source of a given API response on the iPad. Incidentally, when I realized that I was in bed, and the iPad was the only device within my reach.

So I found this script on ravelrumba.com which worked fine for HTML pages, but not so much with pure XML content.

Being not a JavaScript expert, it took me a while to make the script work on Mobile Safari, but the following fix seems to do its job. The trick was to replace the usage of document.documentElement.innerHTML with XMLSerializer:: serializeToString(), which serializes a XML tree to a string.

Here’s the whole thing. Just add it as a bookmarklet on your Mobile Safari bookmarks bar:

javascript:(function(){var a=window.open('about:blank').document;a.write('
Source of '+location.href+'');a.close();var b=a.body.appendChild(a.createElement('pre'));b.style.overflow='auto';b.style.whiteSpace='pre-wrap';b.appendChild(a.createTextNode((new XMLSerializer()).serializeToString(document.documentElement)))})();

Steve Jobs

apple.com 2011-10-05 at 10.43.35 PM
apple.com 2011-10-05 at 10.43.35 PM

When Steve Jobs died, the world lost a complex visionary. The asshole who declared floppy disks obsolete in circa 1989. The weirdo that gave us the NeXT cube, with its absurd magnesium body, its beautifully architected OS and this obscure language no-one else was using, Objective-C. The man who gave a name to those strange devices called “MP3 players” that nobody was using, and who insisted on the necessity of single-button mice. Not forgetting the businessman unafraid to admit his LSD experiences.

You don’t see too many people like that. More holistically, this guy made me understand that engineering and business can meet with art and idealism, and for that I am grateful.

iOS 4.2 update and the Base SDK Missing error

If after updating to iOS 4.2 SDK you get a “Base SDK Missing” error:

  1. open Project settings and choose “Latest iOS” under Base SDK for All Configurations
  2. open your target and make sure the settings applies to it (in case you overrode it)
  3. (yes, somehow the “Base SDK Missing” error seems to stick)
  4. shutdown Xcode and reopen.

The SDK now is set.

Building Erlang OTP R14B on OpenBSD 4.7

Summary: OpenBSD is not GNU/Linux!

I just spent the last 20 minutes baffled by some weird errors as I was building Erlang on an OpenBSD box I am setting up.

$ make
make: "/home/acces/otp_src_R13B04/Makefile" line 88: Missing dependency operator
make: "/home/acces/otp_src_R13B04/Makefile" line 89: Missing dependency operator
...
100 similar lines follow
...

The problem is… that when you type make, OpenBSD — and probably NetBSD and FreeBSD — all use BSD make by default, NOT GNU make! Silly me. I even had just installed GNU make a couple hours earlier!

So anyway:

$ pkg_add -i -v gmake
...
[download, unzip, configure Erlang OTP]
...
$ make # WILL FAIL!
$ gmake

GitHub love

I imported some of my open source code over to GitHub. I have to say I was surprised how easy and smooth the import went from my old svn repository. The whole history seems to have been imported nicely.

Beside importing SimpleTimer (my first Cocoa app: beware, its code might not be the prettiest!), this is the first release of CLutils, my collection of C/C++/Objective-C functions built over the years. There’s not much structure in it, beside subdividing it by deployment platforms (Mac OS X, iOS and cross-platform code) and OS X APIs (Carbon, Cocoa).

http://github.com/ettore/SimpleTimer/
http://github.com/ettore/CLutils/

FlashBuilder quirks

I ran into the following weird compile error recently:

compile error:
1071: Syntax error: expected a definition keyword (such as function) after attribute override, not protected.

in relation to the following code:


override 
protected function createChildren():void {}

The solution?


override protected function createChildren():void {}

Don’t even get me started.

Updating your Apple Push Notification Service certificates

Just a quick checklist to get up to speed when your APN certificates expire.

  1. Login into the Provisioning Portal, click “App IDs” on the left side column
  2. Click “Configure” on the App ID of your app
  3. Click Revoke for the expired Push SSL certificate
  4. Open Keychain Access on your Mac. Click the “My Certificates”, find the expired cert and just delete it.
  5. From the Provisioning Portal, start creating a brand new Push SSL certificate. Just follow the instructions.
  6. Don’t forget to download the signed cert and double-click it to install it (aps_developer_identity.cer) in your default keychain.
  7. Select My Certificates, find the newly created cert, click the disclose triangle. Then:
    • Right-click on the private key entry without selecting the parent, and select Export. A .p12 file will be saved.
    • Right-click on the actual certificate without selecting the child key, and select Export. Another .p12 file will be saved. UPDATE 2017: it looks like you don’t need to do this anymore. The cert file includes a bag with both cert and key, so deploying that should work.
  8. If your server requires .pem style certificates, run this:
    $ openssl pkcs12 -in apn_cert.p12 -out apn_cert.pem -nodes
    $ openssl pkcs12 -in apn_key.p12 -out apn_key.pem -nodes
  9. Deploy the .pem files in the right location accessible by your application server that will be sending the Push notifications.
  10. UPDATE (2015): it seems like each exported files contains both key and certificate now and therefore are identical. I don’t recall that being the case at the time of this writing.

Now push notifications should be up and running once again.