Rapture in Venice

:: Mobile Design and Development Shop specializing in iPhone, iPad, and Android

wdf-carousel
pholium-carousel-flat
Movementum
finds-carousel
spec-hd-carousel
aa-carousel
passtouch-carousel
tasklist-carousel
ss-carousel
fuzz-carousel
wwp-carousel
kindercards-carousel
hoya-carousel
<<<   |   play   |   >>>

Speeding up Android Studio

I’ve been using Android Studio for about a year now, adopting it early to get a jump on things. And in that time, I’ve certainly had my share of frustrations with it, but it’s going to be a superior tool to ADT when it comes out of beta, so it’s worth it to use it now.

Here’s a few tips I’d like to share with you if you do plan on using it.

The Command/Control-E Menu

I use many IDE’s, from XCode to Sublime Text to Android Studio, and I use each one differently when it comes to file navigation. In XCode, for example, I tend to toggle the “Recent Files” option a lot so that the Project Navigator is only displaying the files I’m mucking with at that moment. In Android Studio, though, I use the Command-E menu.

Open up a bunch of files in Android Studio and then press Command-E (Control-E on inferior OS’s). You’ll see something like this:

You’ll see two columns. On the right are your most recently opened files, in descending order. You instantly have keyboard access so you can arrow up or down and press Enter to open the file you want. This is extremely handy and the optimal way to move between files in Android Studio I think.

As a bonus, on the left you’ll see a list of views you can open. This is also very useful for navigating around the IDE itself, but I encourage learning the individual keyboard shortcuts for them as that’ll be faster. Start with Command-6!

And before we continue on, you might be asking why not just navigate using the tabs? You can do that, yes. However, I find it slower, especially with a mouse. Even with the keyboard, it’s a three-key combo by default. The Command-E popup really is the fastest way to navigate…give it a try!

Avoid the Wizards

Android Studio improves on ADT when it comes to wizards that create activities, resources files, etc. for you. They are more detailed and provide more options. There’s only one problem: you shouldn’t use them.

Well, that’s not totally true. Sometimes I use a couple of them early on in a project, but I still suggest to avoid them after that. Why? Well, several reasons:

  • You should be creating a lot more fragments.
  • You shouldn’t be creating many activities that actually do anything.
  • You can’t avoid creating menu XML for each activity.
  • It’s faster not to.

Do you put all your logic in activities? You really shouldn’t. For the most part, you should be creating “shell” activities that do nothing but host a fragment for your phone-form views (or multiple fragments for your table-form views). This leaves near-empty activities in your code and, rightfully, puts that code in fragment-land!

So, why not use the wizard? Well, the wizard wants to create activities for you, not fragments, and that’s wrong. So what I’ll do when creating a new screen is to clone a previous screen from the bottom-up:

  1. Copy and paste the fragment XML from a similar screen. (Enter new filename.)
  2. Change the XML to match my screen requirements.
  3. Copy and paste the fragment class from that screen. (Enter new filename.)
  4. Change the code and handlers for my screen requirements.
  5. Copy and paste the activity class from that screen. (Enter new filename.)
  6. Direct that class to load your new fragment.
  7. Add the activity to the AndroidManifest.xml. (Or crash!)

A bunch of steps, but it’s many times faster than using an activity creation wizard. Plus, you’ll have to create your fragment yourself and re-jigger everything anyway. If you’re like me, you have a base activity that simply loads a fragment and your fragment logic always looks similar. Same for resource files.

Copy and paste is your friend…well…this time!

Genymotion

There’s no argument. You must be using Genymotion for Android development. Why? Oh, well for one thing you won’t have to wait around for an hour for your simulator to load, and you DO need simulators to test on various devices so don’t tell me to just use a device…plus, it’s nice not having a phone wired to your computer all the time, and Genymotion runs so fast and smooth and, yes, yes, I know there’s that Intel thing to make the real simulator faster and that works (after an hour of trying!) but you still have all the other problems like when you run the app and the simulator comes up and it never runs your app because it’s freakin’ disconnected and it sometimes takes forever for the app to run anyway and WHY THE HELL CAN’T GOOGLE GET THEIR SIMULATOR RIGHT ANYWAY!!!?!?!!

OK, let me breathe.

Alright, so yeah, use Genymotion. It’s not only a way better environment than Google could ever provide, but it’s super simple to install, too! (Which you wouldn’t expect from a “virtual” environment.) All you need to do is install Virtual Box (hell, you don’t even need to run in, just install it) and then install Genymotion. You’ll be shown how to create your virtual device and…oh man, it’s just so easy. Android Studio sees Genymotion as just another device like the simulator or your Nexus. It’s awesome.

And to make launching Genymotion easier right from Android Studio, there’s even a plugin.

This isn’t even a recommendation. Go get it. Stop arguing.

Download Everything

This one doesn’t really just apply to Android Studio, but I’m including it here anyway.

Download everything Google offers you. Every SDK. Every bit of sample code. Everything. Do you only use SDK 10 and the latest stuff? Whatever…just download everything!

There’s a lot of reasons for this. For one, you’ll open existing projects that will fail because they use a different SDK. You will inevitably be testing against different devices in the future. Have you considered Kindle? So, when you install Android Studio and need to download what you need to use it, do yourself a favor and just get it all now. It won’t take that long and it’ll be way better than stopping multiple times later.

DOWNLOAD ALL THE THINGS!!!

  • Print
  • Facebook
  • Twitter
permalink

, , ,

How to Create a Flappy Bird Clone with SpriteKit in 20 Minutes

First, create a project in XCode. We’ll call it “Floaty Avian.” Next, bring in the SpriteKit and…

WHY ARE YOU READING THIS? WHAT IS WRONG WITH YOU?? THERE’S A MILLION GREAT GAMES ON THE APP STORE, AND YOU’RE **STILL** HUNG UP ON THIS ONE? IT’S GONE. YOU’RE AN IPHONE DEVELOPER! I CAN’T BELIEVE YOU CLICKED THIS LINK! YOU REALIZE IRRATIONAL GAMES WENT OUT OF BUSINESS YESTERDAY, RIGHT? GO PORT BIOSHOCK! FLAPPY BIRD? YOU CAME HERE TO REMAKE FLAPPY BIRD?!

WHAT WERE YOU THINKING?!

  • Print
  • Facebook
  • Twitter
permalink

How to Memorize Block Syntax

Since block syntax came out alongside iOS 4, I’ve struggled to memorize it. Sure, blocks without return types or parameters = ^{ return @”super easy to recall”;}, but once you factor in arguments and want to accept a block argument in a method, thingsBecome:(CGFloat (^)(NSInteger way, id more, CGRect complex))dontYaThink?

It’s no wonder that Fucking Block Syntax has become one of my most beloved websites.

But if you’re not the Rain Man and, like me, have trouble remembering the syntax accurately, there’s hope! I have a full-proof way to memorize it.

The Two Basic Forms

There are two basic forms to memorize. The first is when your block has a name, and the second when your block is a value (anonymous):

  1. NSInteger (^myBlockName)(CGFloat param1)
  2. ^NSInteger(CGFloat param1)

Take a minute to look at these two forms. The first form is as normal and expected as could be. REMEMBER, put the block name in parenthesis. If you do that, it’s easy pickings. The ^ is like a * if the function was a pointer. Just remember those parenthesis. Visualize how the parenthesis cuddle the name of the block. Think: Cuddle The Name.

The second form is ridiculous. Backwards almost. Since there is no name associated with the block, the return type flips to the other side of the carat. No cuddling needed, either. Clearly, tho, dropping the name means we can compact the syntax. I like to remember the phrase, Flip No Cuddle. To me, we flip the side of the carat the return type is on and lose the parentheses.

Apply It Everywhere

With these two concepts in mind, the named block and the anonymous block, let’s see them all applied. Read the following sample code and identify each one, repeating the above phrases as you see each one. Recognize if the block is named or not, then say either Cuddle The Name or Flip No Cuddle:

// pass block to method
[self makeNumberFromString:^NSNumber *(NSString *str) { ... }];

// define block locally
NSNumber * (^local)(NSString *str) = nil;

// property
@property (copy, nonatomic) NSNumber * (^myProp)(NSString *str);

// the defined method
- (void)makeNumberFromString:(NSNumber * (^)(NSString *str))named {
    ...
}

How did you do? Your answers should have been Flip No Cuddle, Cuddle The Name, Cuddle The Name, and WHAT THE F*** ARE YOU KIDDING ME? Yep, sorry, method parameters bend the Cuddle The Name mold a bit by flipping the method name to the outside. However, this too is easy to remember because the carat remains and, hey, ALL method parameters put their name on the outside. Right?

- (BOOL)textFieldShouldReturn:(UITextField *)textField { ... }

So, just put the whole expression in parens and the parameter name on the outside like you always do.

Typedefs? Cuddle The Name!

I’m not a huge fan of typedefs for blocks, but you’ll see them used often and you should recognize easily that defining them is Cuddle The Name:

typedef BOOL (^IsItSafeType)(NSInteger);

With it defined, assigning to it is what pattern? RIGHT! It’s Flip No Cuddle because you assign an anonymous value to the variable!

IsItSafeType alwaysSafe = ^BOOL(NSInteger x) { return YES; };

OK, Let’s Summarize!

Alright, so we have our two basic forms:

  • NSInteger (^myBlockName)(CGFloat param1) <-- Cuddle The Name for named blocks
  • ^NSInteger(CGFloat param1) <-- Flip No Cuddle for anonymous blocks

The one exception is with Cuddle The Name for method parameters where we cuddle the whole thing and pull the parameter name outside:

  • ((NSInteger (^)(CGFloat param1))outsideName <-- Cuddle The Name wants to be like other parameters!

But as you can see, since it’s a named block, using Cuddle The Name is perfectly consistent. Then, defining typedefs, we still have a named block and so we use Cuddle The Name there, too! And assigning to the typedef? Yep. Flip No Cuddle.

Simple! Hopefully, this helps us memorize this very strange syntax. :-)

  • Print
  • Facebook
  • Twitter
permalink

, ,

Don’t Write a Class, Write a Category!

As an iPhone freelancer, I develop a lot of iOS apps. A lot. And one of the most important things to my business is that I leverage as much of my past work as possible when it comes to new projects. I have several strategies, but today I wanted to share one of my favorites: categorization.

If you’re an experienced developer who’s worked with various languages and platforms over the years, you’ll know that the classic way to add “core” functionality was to either extend a class or create a new (probably static) class. We’d create classes like BetterString (extends String) or StringUtils as ways to add functionality to the platform we think could be handy later.

Of course, the problem with extending classes is that they’re not always interoperable with library code. Taking the example above, you might have to wrap your String in a BetterString before passing it to your code. It gets ugly. Creating new classes separates the functionality out a bit, but providing a bunch of static methods from StringUtils just feels disconnected and incorrect. (Hint: it is.)

Abuse the $*#@&^ Out of Categories!

Generally, when we think about categories, the first thing that comes to mind is adding useful NSString or UIColor methods. In InnerBand, I provide popular UIColor#-colorWithHex: and NSString#contains: methods that can be re-used all over the place without interfering with the categorized classes.

But what if I told you that using categories for app-specific functionality unlocks their true power?

You see, the best use for categories is dropping ALLLL the reusable bits you need down to the microscopic level. How much do you use categories? Answer yes or no to these questions:

  1. Do you specify fonts or font sizes in place when you need them?
  2. Do you specify colors all over your code?
  3. Do you access NSUserDefaults values by providing keys where you access them?
  4. Do you check for NSNull when you’re parsing JSON?

Did you answer yes to any of these? If so, you need to abuse categories more. You see, as a Clean Coder, it’s your mission to isolate these kinds of choices and checks as much as possible.

If you’re still reading, you want to know more. So let’s inspire you! Here’s how we can put categories to good use!

Pre-Define Your Fonts in a Category

If you’re specifying a font face or size in your view controller, you’re doing it wrong. You should define the fonts you’ll use in one place and reference them elsewhere. And we’ll use a category:

@implementation UIFont (AppFonts)

+ (UIFont *)titleFont {
    return [self bebasFontOfSize:20];
}

+ (UIFont *)subtitleFont {
    return [self bebasFontOfSize:15];
}

+ (UIFont *)bebasFontOfSize:(NSInteger)size {
    return [UIFont fontWithName:@"Bebas Neue" size:size];
}

@end

As a bonus, notice how I even have a convenient private method for creating the Bebas Nueue font in case I ever need to change it.

Create Your Colors in a Category

Colors are tough in XCode. First, I DO NOT LIKE the Apple format of using decimal numbers to define them. Designers don’t use that format, it’s harder to eyeball the distributed syntax, and sooo many apps that can help you with color will output in Hex rather than Apple’s format. (If you insist on using the Apple format, I use and recommend Color Snapper.)

Past that, even if you do use hex colors, you should confine them to a category:

@implementation UIColor (AppColors)

+ (UIColor *)headlineColor {
    return [UIColor colorWithString:@"#ff0000"];
}

+ (UIColor *)standardBackgroundColor {
    return [UIColor colorWithString:@"#111111"];
}

@end

Categorizing your colors in this way makes them easy to change and locates them right on the class you’ll find the most convenient. Look at the client code:

    self.view.backgroundColor = [UIColor standardBackgroundColor];

Contrast that with this macro/function usage:

    self.view.backgroundColor = MA_COLOR_STANDARD_BACKGROUND_COLOR();

The former just feels so natural. Naming is shorter and more readable, and I know where to find it should I need to look at it.

Don’t Re-Use the Key, Re-Use the Access

One of the more prevalent anti-patterns I’ve seen is to create a constant for use as an NSUserDefaults key. I know, my old code does it, too. :-) And yes, constants are good for this sort of thing to avoid typos, but using categories we can make saving and restoring these values even more reusable and easy to do:

// keys
static NSString * const kUserDefaultsDealerId = @"kUserDefaultsDealerId";

@implementation NSUserDefaults (AppDefaults)

- (void)setDealerId:(NSString *)dealerId {
    [self setObject:dealerId forKey:kUserDefaultsDealerId];
}

- (NSString *)dealerId {
    return [self objectForKey:kUserDefaultsDealerId];
}

@end

You can see that I use a constant for the key, but the constant and the accessors are all here on this NSUserDefaults category and, again, all very logically located. (Assuming you don’t have a separate model class.) I can read and write the value, and I do it right on the class:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    [defaults setDealerId:@"ABCDE"];
    [defaults synchronize];

It just feels so natural to perform these operations on the very class we intend to interact with. Notice I don’t do the synchronize in the call because there are cases where doing so would be very ineffecient, such as when you were setting the value within a loop.

Even the Lowest Level Code Can Be Categorized

I love JSON, but it can be a bit annoying to constantly check for NSNull in values you receive. (You are doing that, right?). In the old days, you may have seen a lot of code looking this:

    NSString *firstName = [json valueForKey:@"first_name"];
    self.firstName = (firstName && firstName != (NSString *)[NSNull null]) ? firstName : nil;

Repeated everywhere. Well, let’s categorize!

    self.firstName = [json safeValueForKey:@"first_name"];

We can reuse it everywhere. What’s it look like?

@implementation NSDictionary (Nulls)

- (id)safeValueForKey:(NSString *)key {
    id value = [self valueForKey:key];

    if (value && value != [NSNull null]) {
        return value;
    }

    return nil;
}

@end

Final Thoughts

Categories are a powerful part of the Objective-C language and, for once, one that’s been there quite a while. (*cough* blocks *cough*) They get decent use in every codebase I’ve seen, but I think many stop short of truly abusing them. Hopefully, I’ve turned you into a frequent abuser today!

One last thing, I am a proponent of importing these in the PCH. Every one. Why? Well, if you take the concept of “forgotten code” as code that doesn’t get used by developers who weren’t aware the functionality was there, then the advantage of importing these in the PCH is that a new developer can more easily stumble on these without even being told. They go to define a new font and…hey, what’s that? A -headlineFont method? I think it’s a great way to help developers find their way around the codebase.

Alright, that’s all I got. Code away!

  • Print
  • Facebook
  • Twitter
permalink

, , ,

My Concise Introduction to CocoaPods

CocoaPods is now the industry standard for managing third-party frameworks and dependencies for iOS. There’s such a demand to make libraries work with CocoaPods that, even in its very early days, I actually received 5 requests to add a Podfile and tag before I even knew what CocoaPods was! Nowadays, I love it, and I’d never even consider starting a project without it!

Let’s take a concise look at how CocoaPods works.

The One-Time Installation

CocoaPods is actually implemented as a Ruby gem, so assuming you have Ruby already installed, install the gem with:

gem install cocoapods

If you’re not familiar with Ruby, you might need sudo access to get this command to work.

Setting Up Your Project

Setting up CocoaPods for your project doesn’t get much harder. First, make sure you’ve created your XCode project if you haven’t already. (I’ll wait.) Great! Now, you need to create an initial Podfile. At the top of your project hierarchy, in the same directory as your project’s .xcodeproj file, run:

pod init

This creates the Podfile for you. Now open it and add the following:

pod 'RaptureXML'

Next, install the CocoaPods and framework and your new dependency with:

pod install

Magic be done! Now take another look at your directory contents. CocoaPods has created a complementary .xcworkspace file that you should use from now on to open your project. When you do, you’ll find that your project now shares the workspace with CocoaPods and all your dependencies are managed for you!

Pod Selection and Specification

If you specified the Podfile as listed above, you’ll have the latest version of RaptureXML in your project. It’s very easy to add other libraries and be even more specific as to what version you want. Let’s say you want to add AFNetworking to your project…what do you do? I always start with a search:

pod search AFNetworking

A few items comes up, but it’s quick to see that this is what you’re looking for:

-> AFNetworking (2.0.0)
   A delightful iOS and OS X networking framework.
   pod 'AFNetworking', '~> 2.0.0'
   ...

Even better, the third line there is CocoaPods telling you exactly what you need to add to your Podfile to install AFNetworking! Yet, what’s that syntax? It’s a little weird, so here’s some examples to give you an idea:

pod 'AFNetworking', '~> 2.0.0' <-- Installs latest version up to, but not including, 2.1
pod 'AFNetworking', '~> 2.0' <-- Installs latest version up to, but not including, 2.9
pod 'RaptureXML', '1.0.1' <-- Installs version 1.0.1
pod 'iRate' <-- Installs most recent version
   ...

There’s other options in terms of versioning, but I don’t find anything else very useful. Most of the time, I just grab the latest version. There’s some risk there in case a bug is introduced into a dependency, so if it’s critical for testing that things stay the same, you might opt to lock the versions down in the release branch version of your Podfile. Stick to using the latest versions in your main branch, though, because you don’t want to become dependent on an old version of anything.

Local Pods

This is my favorite feature of CocoaPods. Previously, we’ve been installing pods from CocoaPods’ central repository, but there’s no requirement that you have to. We can alternatively load our pods directly from any Git repository:

pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git'

And, my favorite, you can point directly at a path on your own machine!

pod 'AFNetworking', :path => '~/Rapture/Tilikum'

This is just brilliant because, in both of the above cases, you can manage your own pods privately without exposing them to the central repository that allows anyone access. This is great when you, or your company, have internal libraries that you want to manage with CocoaPods but don’t want anyone else using. I use this endlessly to capture re-usable code that I use repeatedly in many of my own projects.

Creating the Pod

So, how do the pods know how to configure themselves for your app? This takes a little more work, but it’s not too bad. First, you’ll likely need to re-configure your library or framework’s folder hierarchy just a little. Here are a couple tips:

  1. Centralize the re-usable code in your library under one directory hierarchy (i.e., Classes/ or Tilikum/).
  2. Separate app delegates, Info.plist, and any other files which shouldn’t be included in a host app. (So they’re not under Classes/)

Now, in your library, create your podspec at your project’s top level. Let’s pretend we’re creating a library of avatar masks. We run:

cd ~/Projects/AvatarMasker
pod spec create AvatarMasker

This will create an AvatarMasker.podspec in that directory. There’s a lot of comments in that file to help you configure it. My best advice is to browse real-world podspecs to see what they do. Here are the podspecs for RaptureXML, iRate, and ZipZap.

One thing you may notice while you’re browsing around is that some projects don’t appear to have podspecs, but are searchable in CocoaPods. This is because it’s not required that the podspec be in the repository itself. In these cases, the podspec is located only on the CocoaPods central repository. This is, for example, the case for InnerBand. If you want to add your library to the central repository, you’ll just need to upload your podspec to a different place.

Also, note that if the project doesn’t host its own podspec, you can’t load it directly like we just did above. You would have to load it from the central repository.

Conclusion

CocoaPods is clearly the superior option compared to adding each dependency to your project by hand. Every library seems to have unique requirements for how to integrate it and you’ll often include more than you need when you do it this way. You’ve seen that you can integrate a library as large as AFNetworking in a matter of seconds, so why would you want to do it yourself? In addition, you gain the power to specify any version you want without having to reconfigure every time — at will.

Sometimes, developers will use Git submodules to avoid copying library source code into the app. This is fine, but personally I despise submodules. Git just doesn’t implement them very elegantly and, inevitably, you’ll run into errors when a developer doesn’t update the submodule pointer properly or forgets to push or pull submodule commits. On top of all of this, you still have to do the library integration on your own.

If you’ve never used CocoaPods, I hope I’ve inspired you to try out one of the most valuable tools in the iOS toolbox!

  • Print
  • Facebook
  • Twitter
permalink

, ,

Previous Posts