Blog Archives

Lessons from AngularJS

AngularJS

AngularJS

The past two weeks I’ve been working on a web project using AngularJS.  Angular is a Javascript MVC framework with the backing of Google.  I always enjoy taking some time to learn a new language or tool from time to time.  As iOS developers I think there’s a couple of concepts we could learn from Angular.

Bindings – Bindings everywhere.

One of the first thing you learn in Angular development is its two way binding system.  Placing a binding in your HTML template is dead simple; simply enclose the variable in the handlebars: {{myvar}} or link it via the ng-model attribute on an input tag.  The binding is two way such that changing the value of a text field will update that in your model.

Unfortunately iOS is often much more difficult and manual when it comes to keeping your model and UI in sync.  MacOS provides bindings to developers but there’s no once and done solution for iOS.  However binding is not difficult to implement using KVO.  KVO has its downside when it comes to performance, but it may be worth it for the simplicity.  I haven’t tried to implement it myself to be able to tell.

Thin models; thin controllers

Angular makes very few assumptions about what your model in the MVC way of thinking is.  In fact, the model for any controller is expected to be a special variable called the $scope.  The $scope object is provided by the controller, whose entire job is to do nothing but populate the scope.  Compared to iOS view controllers, Angular controllers are extremely light.

iOS view controllers have a bad habit of being very involved in both in view-ish things and model-ish things, as well as its dictated function of handing controller-ish things.  How many times have you managed a view directly in your view controller as well as managed changes back to the model?  Probably a lot.  One of the downsides of UIViewController is that they often wind up being behemoth and barely manageable monster objects. Angular’s documentation strongly advises that you don’t make changes to the DOM (the literal view of a web application) from within the controller, delegating those tasks elsewhere.  The result is a very simple controller that does its job of exposing the model to the view well and without needless other operations.

Greater separation of the view and the controller

Web applications have an inherently strong presentation layer: the HTML and CSS that handles display in the browser.  In Angular style, the HTML provides structure of a view, CSS provides the presentation of the view, and Angular does the job of providing data to the view.  As mentioned above it’s all too common in an iOS application to jam all this functionality into a single view controller.

It’s not a stretch to say that UIViewControllers are often required to do far too much for any non-trivial application.  A view controller might be responsible for loading data from somewhere, maybe through an NSURLConnection, doing any formatting or transformation of the data, creating a view in loadView: and laying all the pieces out.  It may also be the datasource and delegate for a table view providing cells and handling cell selection.  After all of that it might also be accepting event callbacks from UI controls and altering the model appropriately.  That’s a huge set of tasks and I’m as guilty as anyone of writing multi-thousand line view controllers.

Applying the lessons

So how should we break up a UIViewController subclass into more manageable chunks?  I think Angular presents a couple of ideas.

  1. The most simple task is to separate the model related concerns of a UIViewController from its view related concerns.  In iOS development you need to have view controllers, but there’s no rule that you can have other controllers to handle other tasks.  NSFetchedResultsController provides a great example of a way to separate the needs of dealing with CoreData from the other responsibilities of the view controller.
  2. Relegate the UIViewController subclass to what its name implies:  management of the view.  Offload data related concerns to a custom defined model controller.
  3. Make views a little smarter.  HTML and CSS provide a natural separation between controllers and views.  Interface builder is one of the best tools and iOS developer has but there’s no reason we can’t make smarter views that know more about it’s layout and the properties of it’s subviews.  If reuse is concern there’s nothing wrong with the root view of a view controller being a custom subclass that arranges other pre-made components.
  4. Attempt bindings using KVO.  You could easily inject a transformer into the mix for formatting.

Fully realizing these are all a little abstract right now I’m planning to take a concrete stab at these in some future posts.  For now the takeaway is that learning a different way of doing things can always open your eyes to some better ideas in your current workflow.

Advertisements

How much for that iPhone App?

I don’t know how it is I haven’t come across this stackoverflow discussion about iPhone app costs before.

Like most developers, I’m asked frequently to run levels of estimate for software projects at work and in the freelance arena. Consistently, I feel like there’s pressure to give the client a number that they can swallow, which is ordinarily way under what the work is at a quality level I’m comfortable with. It’s a constant battle for me to be honest with myself about the time required to actually complete the work. After all, everyone loves to get the contract.

Of course, the downside is, and everyone knows it, that a gross under-bid is bad for everyone. As the developer, you feel overly constrained to meet unrealistic deadlines, you wind up putting in hours for free or feel like you’re not serving your clients as well as you can by delivering a sub-par product.

The discussion is an excellent read for folks who always find themselves having to place numbers on iOS projects. It’s refreshing to get a peek into the scales of production from the developers of some the most revered apps out there.

10 iOS Libraries + 2

AppDevMag posted a list of 10 libraries to make iOS development easier. We’ve used Three20 and a few of the others here at Mindgrub, and wound up writing our own library similar to ASIHTTPRequest back in the iOS 2 days, though it was built around NSHTTPURLRequest rather than CFNetwork.

Two great libraries they left out however:

  • ShareKit – Post to many social network sites out of the box. This library is light and fast, and easily extendable to add other services.
  • XMLRPC in WordPress for iOS – Writing XML-RPC from scratch is a pain, but this library will get a lot of the boiler plate code out of the way. The app is open source.

A roundup of my favorite iOS and Cocoa blogs

These are some of the better blogs and authors in my Google Reader related to iOS, Cocoa, and Objective-c:

“iPhone Development” – Jeff LaMarche : Always well written and in depth articles. Virtually every article gets starred in Google Reader.
“Cocoa with Love” – Matt Gallagher : If you’re looking for how to use an obscure part of the apple frameworks, this would be the first place to look. Usually Matt’s posts come with accompanying sample code.
“Able Pear Software” : A lot of good beginner articles. Not updated as frequently as it used to be, but their twitter feed has been very active with links to resources.
“Dr. Touch” : Another resource for finding information on lower level or more obscure cocoa tips.
Cocoa Is My Girlfriend” : Real world coding examples
“iCodeBlog” : Tips and help from a variety of authors

CABasicAnimation Interpolation

In my previous post, I detailed how you have to specify to and from values for a basic animation on a property. Using those two values, the animation should be able to interpolate the actual values of a property at any point.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation.delegate = self;
animation.fromValue = [NSValue valueWithCGPoint:layer.position];
// move the x position by delta
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(layer.position.x + delta, layer.position.y)];

// later during the animation
NSValue *currentValue = [(CABasicAnimation *)[aLayer animationForKey:@"position"] byValue];

For some reason, this doesn’t work, and you have to grab the value from the presentation layer instead.