This post references MacRuby 0.5, used with Xcode 3.2 on Snopard (10.6.2); the general technique will likely work on other OS/Xcode version, tho. Just saying.
At some point in my project I needed to access OSX' Keychain to store sensitive userdata. Unfortunately, due to the lack of void pointers in MacRuby 0.5 (see Trac ticket), I couldn’t use standard methods like
SecKeychainAddGenericPassword
. The guys on the mailing list told me to use a wrapper instead. Doing some reading and poking around the interwebs I finally figured it out, and since it’s a neat trick I thought I’d scribble it down, so maybe it will safe someone in a position like me a bit of time. ;)
I’ve decided to go with ExtendMac’s EMKeychain class because it’s simple, clean, free and has a liberal license (MIT license, if I’m not mistaken).
Disclaimer: I’m not a Obj-C person, and what you’re about to read is what works for me. I’ve tinkered until everything was moving in the right direction. There might be better ways (I’m pretty sure there are), and if what I’ve done here is bollocks, I’d be delighted if you would share your knowledge with me. :) Also, I’d enjoy a comment with your thoughts about this here article. Any opinion will do. Just curious is all.
Step 1: Build the wrapper, EMKeychain.dylib
First, we’ll have to make EMKeychain into a dynamic library. Download it from the site, unzip it, and fire up Xcode. There, start a new project of the type “Cocoa Library”.
When asked for the name, call it “EMKeychain”. It kind of makes sense. This is what you’ll end up with:
In the screenshot you’ll notice a file called EMKeychain_Prefix.pch
. That’s a so-called “precompiled header”; Xcode creates it automatically for you on project creation.
Next, add the files EMKeychain.m
and EMKeychain.h
to your project by dragging them from the download folder to the “Classes” folder.
Since the EMKeychain documentation said the class needs to be linked against Carbon and Security frameworks, do that by right-clicking on the “Linked Frameworks” folder in the tree and selecting Add Existing Frameworks…:
Following the related MacRuby tutorial’s advice, add a constructor to the end of EMKeychain.m
:
void Init_EMKeychain(void) { }
Next, adjust the build settings – switch the base SDK to 10.5…
… and enable GC.
Build a release, and you’ll have your wrapper.
Step 2: Using it
Now for the fun part.
- Add the just built
EMKeychain.dylib
to your MacRuby project. (Don’t forget to copy the file over.) - Add
EMKeychain.dylib
to Targets ➔ [project name] ➔ Copy Bundle Resources.
And that’s it. If all went well, you should now be able to use EMKeychain’s
EMGenericKeychainItem
.
Step 3: Mopping up
It’s very likely that when running your release build it’ll crash and burn and complain about a missing /usr/lib/EMKeychain.dylib
. In this case, you’ll have to adjust the built executable accordingly using
install_name_tool
.
You can do that by adding a new Run Script build phase to the target, which should contain this code.
install_name_tool -change /usr/lib/EMKeychain.dylib \
"@executable_path/../Resources/EMKeychain.dylib" \
"$TARGET_BUILD_DIR/$PROJECT_NAME.app/Contents/MacOS/$PROJECT_NAME"
It’s possible that on the next build the executable will mope about a missing
/usr/local/lib/EMKeychain.dylib
now. Duplicate the snippet and adjust the second one accordingly.
Step 4: Get yourself a beer
Because if all went according to plan, you’re done. :)