Rapture In Venice, LLC

:: Freelance iOS Development & Team Augmentation

Google is Winning the Developers; How Apple Can Win Them Back in an Instant

Google I/O went very well this morning. While I’m predominantly an iOS developer, I also write Android apps and, boy, was I blown away by Google’s intoxicating love for developers like me. Starting with the recent ability to reply to your Android app reviews (OMG), the announcements today were just as aweesome.

Google Play Services that also support iOS! WHOA!
Android Studio! OHMIGOD!!!
Integrated analytics, revenue graphs, alpha and beta testing on Play Store! SWEET!!!
Localization Services! YES! …that aren’t free and you still have to wait a week. WAIT, WTF?

That last dud aside, I’m pretty stoked. The crowd was stoked. The cheers were loud and authentic. Don’t mistake it for fanboys, these are exciting announcements!

These last couple years, conversely, Apple hasn’t really gotten my juices flowing. Following in the footsteps of Nintendo, who last peaked with the announcement of their glass-free 3DS technology, Apple has been about new laptops and new iPhones that aren’t much different from their predecessor. They’re a hardware company. If anything, the lightning cable has made life more annoying as evidenced by the older plug that sticks out of all the exercise equipment in my apartment’s gym. Doh! Better bring your adapter with you!

Google is winning the developers. The tools are outpacing Apple’s XCode which still suffers from excruciatingly long wait times to get the most obvious, and obnoxious, bugs fixed up. Storyboards are a duplication of XIB’s without replacing them. Autolayout is an unmitigated disaster. The App Review process is as frustrating as ever, providing no clear indication when a review will occur and providing plenty of inconsistent examples of what’s good and what’s bad. It famously drove Joe Hewitt away completely. Given all that, Apple can still win the day, and the cheer, with one simple announcement:

“We will no longer subject our developers to app reviews. When you submit the app to the App Store, it will process immediately.”

Some may say Apple would never do this, but why not? Of their rejections, what percentage of them are functionality? Very few. Let’s be honest, they don’t test the apps very much. So why can’t they conduct the testing for copyright violations and other bullshit (yes, bullshit) on a more passive basis? Let’s say every day they test out 5,000 apps, looking for their usual violations. Should they find an offense, they report it to the developer who has 1 week to submit a fix. What’s wrong with that?

Also, think about the waste. On a recent project, we would have a new update lined up every week. In fact, we had to WAIT for Apple to review the previous app before submitting the new app. Why? Because if we re-submitted a new binary, we’d go back on the waiting list. Apple had to review the first app, then we’d re-submit, and a week later review the next version. They wated their time! By reviewing on a passive basis, they can skip interim updates and even prioritize their efforts on new apps rather than update after update. On top of that, it pisses off developers to no end that companies like Twitter and Facebook (and whoever else has a buddy at Apple) get precedence when there’s a glaring error.

In terms of an app that crashes, Apple rarely runs into that. So what if they let developers update apps immediately? Well, if the app crashes, guess what…THEY CAN UPLOAD A FIX IMMEDIATELY. I guarantee you Apple catches far, far less than 50% of the app crashes…so why punish developers by making them wait a week for an update to process while they helplessly watch their app reviews drill down to 1 star?

(No, I won’t get into the urgent update process, which is hardly ever worth doing considering the long-term effects.)

This one announcement would get the WWDC crowd to its feet, set the social networks on fire, and re-energize a devoted developer base that has watched the other side get all the good Christmas presents while we’re still trying to figure out how to get iCloud to work correctly.

  • Print
  • Facebook
  • Twitter

, , ,

How to Link to your App in the App Store (WHY WAS THIS SO HARD?!)

This is, historically, one of my favorite iOS topics because of the ridiculous number of solutions to it: What if I haven’t published the app before? What if I don’t want it to go to iTunes?! Can I link without redirects??

So here’s the final solution for every conceivable situation, only very recently solved by Apple. (Finally!) Where a specific name is necessary I’ll use Task List Pro and Rapture In Venice as the example since each is a messy name with spaces, but you should swap in your own app or publisher name, obviously.

Linking to an app via App Store/iTunes:
http://appstore.com/TaskListPro

Linking to developer/author via App Store/iTunes:
http://appstore.com/RaptureInVenice

Is the app is already in the App Store, this handy Apple page will generate links for you that work in a browser when on desktop:
http://itunes.apple.com/linkmaker/

Apple has let this be an “issue” for too long, fostering endless threads about links that redirect and what to do about punctuations. Finally, they made their Link Maker, but that only led to more confusion because it doesn’t address apps that are not yet in the App Store. (What do you do if you’re creating v1.0 of your app?) Contrast this with Android where things have always been much simpler:

https://market.android.com/details?id=com.centura.emm

Google may have taken a long time to get their UI right, and they still can’t solve their versioning problem, but they’ve always gotten developer-oriented things like this right at least.

  • Print
  • Facebook
  • Twitter

Using RaptureXML in RubyMotion

One of the cooler features of RubyMotion is that you can bring in your favorite 3rd-party Objective-C code. Without this ability, you wouldn’t be able to use essential libraries such as Cocos2D, Sparrow and SDWebImage. Could you imagine?

Although the process RubyMotion requires to bring this code in is easier than you’d expect, it can be tricky and sometimes technical. That being said, if you’re looking to use RaptureXML in ruby form, here’s a sample Rakefile and usage. First, you need to copy the entire RaptureXML source directory into your app’s vendor/ directory. Then, use the following:

Rakefile

# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'

Motion::Project::App.setup do |app|
  app.name = 'ExEmEl'
  app.libs << '/usr/lib/libxml2.dylib'
  app.vendor_project "vendor/RaptureXML", :xcode

end

Source Code

    xml = <<-eos
      <scores>
          <student name="Jane">80</student>
          <student name="John">95</student>
          <student name="Joe">60</student>
      </scores>
    eos

    # load xml
    rxml = RXMLElement.elementFromXMLString(xml, encoding:NSUTF8StringEncoding)

    # calculate average test score
    total_score = num_scores = 0

    rxml.iterate("student", usingBlock:lambda { |e|
      total_score += e.textAsInt
      num_scores += 1 
    })    

    NSLog("Average score: #{total_score / num_scores}")

After updating the vendor code specification, I like to run a rake clean because sometimes RubyMotion doesn’t pick up the code correctly if you don’t. If you did everything right, you now have the power of RaptureXML in RubyMotion!

  • Print
  • Facebook
  • Twitter

, ,

What’s the point of your library if you won’t tell me how to use it?

Friday morning. 9:00 AM. Last day of the work week. Your Trello board says there’s one more feature to add to Rocket Smack! and that’s the ability to post your high score to Facebook. You’ve never integrated with a social network before and you have a whole day to get it working. You’re excited to get started! You’ll get to use the Facebook SDK for the first time!

Oh, you poor sap. You’ll be working through the weekend and you don’t even know it yet.

Among developers, the Facebook SDK is notorious for being an incredibly complicated framework to work with. I can go on all day with the reasons why:

  • The documentation doesn’t cover all of the standard use cases.
  • A lot of standard boilerplate you’re told to put in your code leaves you wondering why it wasn’t simply included with the library in the first place.
  • A lack of clarity about the architecture of the API. What’s Facebook Connect? What’s the OpenGraph? Just tell me how to post a pic!
  • The documentation is talking about three different versions of the library at once. Extremely misleading.
  • There’s multiple ways to handle authentication.
  • The native iOS 6 implementation only partially replaces the original Facebook SDK. Try posting a status to your own Application with the native UI.
  • The iOS version of the library installs with a package manager! WTF?!

Sadly, this isn’t a blog about how to use the Facebook SDK. I don’t have enough hair left to dare get into that. No, this is a blog about how Facebook could have gotten it right by teaching how to use it effectively.

Mogenerator: even if you figure out what it’s for, you won’t know how to use it

My first case study is a tough one for me because it’s one of my favorite iOS libraries and I use it, without hesitation, in every app where I use Core Data. It’s indispensable, brilliantly executed, and works extremely well.

But, oh @rentzsch, you did a great job of trying to keep it a secret from me!

If you’re not familiar, let me tell you what Mogenerator does and the problem it solves. You see, if your iOS app is going to use Core Data, you’re going to want to have Objective-C classes that represent each entity in your data model. So, for example, if you have a User entity, you’ll want a User.h and User.m to serve as a concrete class instead of using NSManagedObject everywhere. In addition, good OOP principles suggest that you should add methods to this User class that will operate on it. All of this is straightforward until you realize that XCode does a horrible, horrible job of making this easy for you. For one thing, generating the User class can be tricky to do and, once you do it, any future re-generations will completely overwrite what you had before. This means that if you added a method such as -fullName (a readonly concatenation of the User’s first and last name), the re-generation will delete it! Mogenerator fixes this by using the classic two-class design pattern where a private base class is overwritten when the User model changes and a derived class that contains your own methods is left alone.

Cool, huh? Now, if you google for Mogenerator you’ll find the GitHub page and be presented with this README:

mogenerator is a command-line tool that, given an .xcdatamodel file, will generate two classes per entity. The first class, _MyEntity, is intended solely for machine consumption and will be continuously overwritten to stay in sync with your data model. The second class, MyEntity, subclasses _MyEntity, won’t ever be overwritten and is a great place to put your custom logic.

Great. The problem is that’s all it says! The pretty homepage is even more useless. No info on how to generate the classes, where to do it from, options, or anything…well, there’s a link to somebody’s blog that explains how to do it (and the author’s quite a handsome man), but that didn’t get written until years after Mogenerator was created!

How did I learn Mogenerator? I saw it implemented in a codebase at work. How did they learn how to use it? I think they knew the developer personally. This explains why I am always running into iOS developers who don’t use Mogenerator and should be. This could’ve all been fixed with a better explanation of the problem Mogenerator was designed to solve and a simple walkthrough of how to add it to your project and use it.

Brilliant work by the developer is nearly lost due to a criminal lack of documentation.

Sinatra: teaching an entire framework in just 19 words

The Sinatra framework can teach Mogenerator a lot of things about how to introduce itself. With just 19 words, 4 lines of code, and 4 lines of console output, the Sinatra homepage will leave you infatuated, informed, and psyched to use it!

Don’t believe me? Take a look for yourself.

If you’ve never heard of Sinatra, and you clicked that link above, then in the blink of an eye you just learned that Sinatra is a web service DSL that lets you create endpoints by simply fetching a gem, writing a block, and running a script. All so brutally easy and intuitive you’ll want to break down and cry. Think about how easy this is compared to, say, using a Java WAR with Tomcat. Heck, this even makes Rails look like a bloated piggy.

It’s rare to find such a beautiful example of conveying the intentions of your platform in such a simple way and with such charming character, but it’s real easy to find something that does the exact opposite.

GDataXML: oh hai, here’s that XML/YouTube/Picasa/Finance/Code Search library you wanted that we deprecated so JSON?

Deprecated? How about defecated? In the early days of iOS development, you might have gone looking for a high-level XML library to use and found Google’s own GDataXML. What a piece of dog crap! (You should be using RaptureXML anyway.) Google decided that the best way to serve something so narrow in focus is by combining it with a pile of other libraries you’ll likely never care to use. Look at this list! Blogger, YouTube, Contacts, and Maps? I just want to parse some XML! To top it all off, the whole thing is further complicated by a smattering of deprecations and strange JSON superseding. That’ll teach you for wanting to do something so simple.

Now, assuming you can even get the library to compile (HINT: it won’t), you’ll then be participating in the cat and mouse game of their documentation. Want to parse some XML? Here’s the YouTube API! Wait, no it’s deprecated, you should use the JSON version. What, you don’t want to parse JSON? OK, how about Picasa? What? OK, OK, if you want XML you need to look at this directory. You happy, now?

Google’s problem isn’t that there’s no documentation, it’s that’s it’s all over the place! Every page is dry, monotonous and overloads your sensory organs with links, links, links! Now go back and compare this with Sinatra to appreciate the difference.

By the way, I once tried to use the YouTube stuff for an app and after an hour I just decided to use the REST API instead. Why? The REST API documentation is much more concise, on a single page, and the documentation for our next platform is an absolute pleasure to read.

ASIHTTP: what would you like to do? great! here’s how!

I was conflicted on whether to go with ASIHTTP or AFNetworking for this, but I chose ASIHTTP because it preceded AFNetworking by several years and served as the shining model for documenting a network API. Plus, the docs for AFNetworking weren’t so good early on and only recently have improved greatly.

OK, so ASIHTTP is a high-level networking API designed for Mac and iOS that takes the low-level stuff Apple was feeding us and makes it, *cough*, usable. What makes the ASIHTTP documentation so brilliant is that the designer, Ben Copsey, didn’t write it for network engineers…he wrote it for users.

What do I mean?

Go ahead and look at the setup instructions where screenshots and arrows literally point the way. I’ve never had a problem integrating it into my projects. It just works.

Now, how to use it? Simple. Look at How to use it. Here, Ben lists all the most common use cases. Synchronous, asynchronous, blocks, queues, cancellation, GET, POST, files…it’s all there and the API has some wonderful method naming. The language he uses is for those of us that just want to hit a web service and get some data. Sure, there’s plenty of advanced stuff to read about if you like, but the basics are perfectly laid out. Want to access Amazon S3? Extra modules are easy to access and you get even more tutorials that’ll show you how to use it.

If only everything was presented this well! ASIHTTP succeeded because it knew its audience wasn’t interested in ASIHTTP itself. They just wanted to send a tweet or access temperature data from a server. It shows you how and gets out of your way. Next, we look at a library that implements a simple concept and then so spectacularly over-communicates how to use it that all we can do is laugh!

RegexKitLite: how to use regular expressions in 1,000 pages of brutal detail

I don’t hate regular expressions. In fact, I love them! I began my career as an expert Perl ninja and used regular expressions as often as I took a breath. Unfortunately, Objective-C doesn’t implement regular expressions natively and even though Apple’s added foundation support gradually over time, it’s still a bit of a mess. Luckily, there’s a library that implements the full stack and it’s called RegexKitLite.

Now, regular expressions are not easy per se, especially if you’re a rookie. Whole books have been written to teach how to construct patterns to match just about any esoteric thing. Optional strings? Repeating patterns? If/else conditions? Non-greedy matches? Ranges? Yeah, there’s a lot there. However, what’s easy to explain is how to perform the match.

Well, at least it should be. BEHOLD! THE REGEXLITE DOCUMENTATION!

What in god’s name is that?! It goes on forever! This is a great example of where RegexLite could have learned from ASIHTTP. You don’t need to teach me how to use regular expressions (there’s a link for that), just teach me how to use your library one use case at a time. Give me a section titled “Check if a string matches a pattern” and then list the lines of code to do it. Instead, RegexLite includes whole paragraphs of text that nobody wants to read and code examples that are dozens of lines long! In addition, the tutorial, API reference, and entire history of the library are all crammed into one document. I don’t care why the library is mysteriously titled -Lite, I just want to use it! It’s nearly impossible to find the information you want.

How could this be improved? Separating the documents and writing concise use cases would improve the documentation immensely! Better still, the API itself needs to be fixed. Methods often have 5 or more arguments. Why?! Perl only ever needed two arguments: the pattern and the string! In RegexKitLite, many of the methods let you supply a range of the text to search. What for? It’s a narrow use case! Almost always you’ll want to search your whole string. Let the users extract the substring themselves if that’s what they want to do. Why complicate your API for a tiny minority of use cases that has such an easy remedy?

To this day, I still use this library when I absolutely need it, but for new projects I routinely find myself finding non-regex solutions because I don’t feel like figuring out how to use this library all over again every time.

Sad.

Tips for writing proper documentation…

If you’ve written a new framework, do yourself a favor and put some thought into the documentation, too. If you do it right, users will not only find your code easy to use, but they’ll also recommend it to their friends. I love to suggest great resources to people and see them get just as excited as me! And which do I love? Here’s what I look for:

  • The project homepage should explain the problem it’s trying to solve while supplying examples if necessary.
  • There should be a big button titled “Get Started Now!” on it.
  • The documentation should include the basics for writing client code. Keep it short.
  • The API reference should explain what the methods do and not just give the names of the arguments.
  • You should use language that’s accessible and has some personality. Writing dry, technical jargon is a classic mistake. (Read the typical IBM document to understand.)
  • Use images, where appropriate, rather than text. If you have iOS and Android versions of your code, use the Apple and Android icons to make the documentation easier to scan and navigate.

Alright, there you go. Get writing!

  • Print
  • Facebook
  • Twitter

My First Android Tablet

Yeah, now I know why they sell these at a $199 price point. Poor gluing and a poorer QA process.

  • Print
  • Facebook
  • Twitter

Previous Posts Next posts