Fabric + Rubymotion

Making Fabric Play Nice with RubyMotion

EDIT: THIS NO LONGER WORKS. DIGITS AUTH CRASHES WITH A MEMORY LEAK IN RUBYMOTION, AND TWITTER HASN’T COMMITTED TO A FIX.

Twitter’s new mobile app development framework was built with Xcode in mind. Here’s how to get it work for RubyMotion

Twitter recently announced their Fabric framework, an SDK for mobile app development that seeks to solve a number of pain points experienced by mobile developers. Much has been written about the framework itself, and Twitter’s ambitions to be a developer tools company, so I won’t beleaguer those points. I’m not completely sold that this is the future of mobile app development, but in order to at least have an opinion on the framework I felt like I needed to play with it.

Waiting on line

I found it pretty odd that, as a developer tool, Twitter would roll out Fabric as an invite only / limited access release. There was a pretty substantial wave of initial press, and developer tools like this aren’t exactly sexy topics that stay in the news or on the top of minds for long. I’m sure they wanted to work out bugs and make sure they could support the initial partners they launched with, but I very nearly lost interest. When I did get access (a few weeks and a few “I’m interested!” form submissions later) I decided to at least give the framework a spin. Hopefully Twitter rolls out wider access and this will be useful to someone.


I knew from the press that Fabric was very much drag-and-drop, plug-and-play fare, but you never really know what to expect when journalists write about developer tools. I use RubyMotion to write my iOS apps, and I integrate a lot of 3rd party services, pods, frameworks, static libraries, etc. usually with little trouble. I’m certainly a RM evangelist, and I imagine if you’re reading this you probably also use / are familiar with RM. If not, in a sentence, RubyMotion is a toolchain for building fully native iOS (and Mac and Android) apps in Ruby. The Android work is in the early stages, and I haven’t gotten into Mac development, so I’ll focus on iOS throughout.

I was rather surprised and disappointed at the extent to which Fabric is intended to be used only with Xcode. Twitter seems to have made the decision that an easy to use set of tools is preferable to one that might have a bit steeper of a learning curve but which is more flexible. The interesting bit is that I think certain parts of Fabric are better suited to a drag and drop setup — particularly the advertising kit powered by MoPub. I doubt many engineers want to get too hands-on implementing ads. Rather, those asks usually come from the business side of an organization, and engineers just want to drop it in and let the marketing team control how it works through some sort of web UI. But other aspects of the framework, particularly authentication through Digits, seem to be the meat and potatoes of an app, features that engineers want to get exactly right and exactly to their liking.

Regardless, I’d much prefer Twitter take the training wheels off and just give me the damn .framework and some solid documentation. The framework instead ships as a Mac application that runs from the menu bar and employs a wizard-like walkthrough to implement various parts of the SDK.

Once you log in, Fabric asks you to pick an Xcode project. None of my Xcode projects are real projects. The first sign of trouble!!

To be fair, the wizard walkthroughs are really slick, but this was the first sign of trouble for me as a RubyMotion developer. I thought maybe they’ll just give me downloads once I choose a project, so I fired up Xcode and created a new project. That ended up not being exactly true as a bit more work went in to actually getting the SDK to work with a Rubymotion app beyond grabbing the .framework once I could. So I guess we’ll make this Step 1 of our tutorial.

Step 1: Create an Empty Xcode Project

It’s pretty self explanatory, but open up Xcode and create a New Project. It should be an iOS Application, and I chose Single View Application for simplicity’s sake.

We’re not actually going to use Xcode to build the app, but it does help us grab the framework and some other settings we need to pull in to our RubyMotion project. Go ahead and click next.

One important step here that’s necessary to get your RubyMotion app wired up to the Fabric dashboard has to do with naming the app and the bundle identifier.

If you already have a Rubymotion app with a bundle identifier(that’s the “com.yourcompanyname.yourappname” string as a combination of your organization identifier and app name) then you’ll want to enter those values here:

If you haven’t set up your Rubymotion app with these values yet via the Apple Developer Center, then make note of these values for later — you’ll need to put them in your Rakefile like so:

app.identifier = “com.yourcompanyname.yourappname”
app.seed_id = “YOUR_SEED_ID”
app.entitlements[‘application-identifier’] = app.seed_id + ‘.’ + app.identifier

Step 2: Go Through the Fabric Motions

Once you’re set up in Xcode, pop back to the Fabric app and choose the Kit you want to integrate. I’m going to use the TwitterKit, which includes phone number based auth through Digits, as well as some Twitter integrations like embedded Tweets. The wizard is really good for developers using Xcode, and especially because I don’t use Xcode and wouldn’t know how to “Add a Run Script Build Phase”, I did really appreciate this assistance.

Walking through the wizard

On the third screen above is where we are going to go off the beaten Fabric path. Follow the instructions the wizard gives, but in addition drag that wiggling folder to your Desktop or a Finder window. It will drop 2 .framework files for you: Fabric.framework and TwitterKit.framework. We’ll pull these into our RubyMotion project next.

Step 3. Vendor the Fabric Frameworks into Your RubyMotion Project and Add the Social Framework

Drag the Fabric.framework and TwitterKit.framework files into the vendor directory in your RubyMotion project. If you’ve ever integrated third party frameworks or SDKs, this should be pretty familiar to you. You’ll then need to add the following lines to your Rakefile to pull the frameworks into your project:

app.vendor_project(‘vendor/Fabric.framework’, :static, :products => [‘Fabric’], :headers_dir => ‘Headers’)
app.vendor_project(‘vendor/TwitterKit.framework’, :static, :products => [‘TwitterKit’], :headers_dir => ‘Headers’)

At this point I decided to try and build the project. None of the Fabric features will be integrated, but at least we’ll find out if RubyMotion is able to build the project with the Fabric frameworks. Go ahead and rake your app, and lo and behold, an error!

Undefined symbols for architecture i386:“_OBJC_CLASS_$_SLComposeViewController”, referenced from:objc-class-ref in TwitterKit(TWTRComposer.o)
...

I’d seen that TWTRComposer class before, and I recalled that iOS has some deep Twitter integrations. So I went and added the Social framework to the app.frameworks array in the Rakefile:

app.frameworks += [‘Social’]

Let’s rake again, and another error:

*** Terminating app due to uncaught exception ‘FabricException’, reason: ‘[Fabric] Value of Info.plist key “Fabric” must be a NSDictionary.’***

So it appears the Fabric Mac app adds some plist settings to Xcode when you drop the framework in. Pop back over to Xcode and check out the Info.plist, which can be found in the Supporting Files directory in the project navigator. Look for the Fabric setting. Mine looked like this (with the api key and consumer key and secret obfuscated):

Step 4: Add the Fabric .plist Settings to the Rakefile

In order to get your app to build, you need to convert these settings into Ruby that can be added to the Rakefile. Again, here’s what I did that works with my consumer key and secret redacted:

app.info_plist[‘Fabric’] = { ‘APIKey’ => ‘your API key',
‘Kits’ => [{‘KitInfo’ => {
‘consumerKey’ => ‘your consumer key’,
‘consumerSecret’ => ‘your consumer secret'},
‘KitName’ => ‘Twitter’}]}

If you added different or additional Kits this setting would need to reflect that fact. Go ahead and rake, and your app should build just fine!

Step 5: Initialize Fabric in App Delegate & Try a Feature

The code on Twitter’s Fabric documentation is slightly different than the code the Mac app offers for Fabric initialization. The lines that I got to work are here:

Twitter.sharedInstance.startWithConsumerKey(“your key”, consumerSecret: “your secret")
Fabric.with([Twitter.sharedInstance])

Again, if you were using different or additional kits, those would be included in the Fabric.with([]) array argument.

The feature I’m most interested in is Digits, the phone number based authentication, so I followed Twitter’s documentation, transcribing the Objective C over to Ruby as I went. Here’s what I ended up with in a UIViewController:

btn = DGTAuthenticateButton.buttonWithAuthenticationCompletion(proc{|session, error|
})
btn.frame = [[25.0, 463.0], [270, 40.0]]
self.view.addSubview(btn)

Here’s the result. As you can see, the button gets added. It’s even functional. But something is definitely missing.

The button conforms to UIButton, so you could add a label with setTitle:forState:, but I’ll save you the trouble.

There’s one last important step to get this all set up, and it requires bringing in localization files to the RubyMotion project.

Step 6: Add TwitterKitResources.bundle to Your RubyMotion Project

If we return to Xcode, we’ll see another resource has been added without our knowledge. The second item from the bottom, TwitterKitResources.bundle, sounds like something coming from Fabric, so ctrl-click and Show in Finder.

You’ll want to copy that whole bundle into your Resources directory of your RubyMotion project.

Building throws another error, something related to RubyMotion not being able to parse the localization file for en-gb. Open it up and you’ll see that it’s empty. My solve was to simply copy over the contents of the en.lproj into en-gb.lproj. I think you could even customize copy here, but the terms for Fabric were TL,DR; so you might want to look into that before doing so. Like I mentioned earlier, the button itself conforms to UIButton, so you can customize like any button, and the Fabric docs show that you can use your own button to launch the Digits modal view controller.

Step 7: Profit

Can someone help me make these better?

That’s it! You should now have a functioning Digits authentication button. Naturally you’ll have to actually do something with the authenticated session you receive in the callback, but it should all work now. The simulator obviously won’t receive a text message, but I sent it to my device and plugged it into the simulator just fine.

Next time maybe we’ll take the session received in the callback and use it to build out a messaging app using the user’s phone number and address book.

In Conclusion…

We did sort of skip over one part here. It doesn’t seem to matter if you’re just using Digits, but both the Crashlytics Kit and the MoPub Kit require this step to really use them properly.

When we left the Fabric wizard for RubyMotion, we should have walked through the whole wizard to the point of running our dummy Xcode app in the simulator. That runs a script that pings the Fabric servers and registers the App in your Fabric dashboard. This is probably something worth figuring out through Rubymotion so that things are actually connected properly. There might be other info gets pushed up that might be necessary for these things to function in production. I haven’t been able to figure out how to run this script as part of the RubyMotion build process.

I should mention that @hemal from the Crashlytics/Fabric team at Twitter has been really helpful in helping me get off the ground with this. Thanks also to @colinta, iOS developer and community manager for RubyMotion, for reading a draft of this and providing his feedback.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.