About
This is the M Cubed Software weblog. To find out more about us head to our about page.
Search
Feed
Archives
- September 2010
- June 2010
- April 2010
- March 2010
- February 2010
- January 2010
- November 2009
- August 2009
- July 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
New Objective-C Features [UPDATEDx2]
Posted on 25/06/2010 at 08:54 PM in Coding
Prior to Apple acquiring NeXT, Objective-C had had relatively little added to it since it became a fully fledge language rather than simply a C preprocessor back in the 80s. About the only thing added for many years after Apple acquired NeXT was the @try…@catch…@finally exception syntax.
Then in 2007 Apple released Leopard and with it Objective-C 2.0 and the modern runtime. This added features such as properties, fast enumeration, class extensions and garbage collection and improved areas such as protocols, while making the runtime far more flexible and less fragile to change. Last year with Snow Leopard, Apple added blocks and associative storage to the language in what can sort of be thought of as Objective-C 2.1.
At WWDC Apple announced a few more features, which I personally think of as Objective-C 2.2. These are "@synthesize by default" and "declare ivars in class extensions". These are features that I have wanted for quite a while and I am sure a lot of other Objective-C developers have wanted. So what are they and how do you get them?
Getting the Features
To get them there are two requirements:
- Your app must use the modern runtime (so no 32 bit Mac apps)
- You have to use LLVM 1.5 or higher as your compiler
If you fulfil those requirements then you're almost able to use them. All that is left to do is add these two flags to your "Other C Flags" build setting:
- -Xclang
- -fobjc-nonfragile-abi2
So now we're all set up, what the hell are these features?
@synthesize by Default
With the addition of properties, Apple was able to remove a lot of boilerplate code from our classes. If you are using the legacy runtime then you are able to write code like this:
==========MyClass.h==========
@interface MyClass {
NSString *foo;
}
@property (copy) NSString *foo;
@end
==========MyClass.m==========
@implementation MyClass
@synthesize foo;
@end
It is a lot cleaner than what you had to write pre Obj-C 2.0, but it still has a lot of stuff to write. If you are using the modern runtime (ie are writing an iOS or 64 bit only Mac app) then you can get rid of the instance variable:
==========MyClass.h==========
@interface MyClass {}
@property (copy) NSString *foo;
@end
==========MyClass.m==========
@implementation MyClass
@synthesize foo;
@end
That's a bit cleaner, we're only having to sort out our property in two places rather than three, but it's still one too many. 95% of the time, you just want to synthesise the methods and instance variable and so the vast majority of property code in your implementation is the same. Well as you can probably guess, "@synthesize by default" means that this is done for you by the compiler by default. If you want to override it with an @dynamic statement or link it to a different instance variable you can, but for the rest of the time you can reduce your code to this:
==========MyClass.h==========
@interface MyClass {}
@property (copy) NSString *foo;
@end
==========MyClass.m==========
@implementation MyClass
@end
There is one slight gotcha with this. Due to what seems to be a compiler bug, you will get an error if you try to directly access the synthesised instance variable. Unfortunately the only ways to fix this are to either add @synthesize, add the instance variable or only access it via the property methods.
[Update] It seems that this isn't a bug but is instead expected behaviour. The @synthesize methods are generated at the end of the class if you don't specify them explicitly, as the compiler can't tell if the properties need to be default synthesised until it has got to the end of the implementation.
[Update 2] And now it seems the LLVM/Clang team are going to try and work around this and get it working as you would expect. Three cheers for the LLVM/Clang team!
Declare Instance Variables in Class Extensions
So, we have got rid of the instance variables for our properties, but these are public anyway, it's not that big a deal if developers can see them in the header. However, what is left are the private instance variables, the ones only used internally in a class. We can hide methods we don't want as our public interface in our implementation file, but not our instance variables. Instead we end up with this:
==========MyClass.h==========
@interface MyClass {
id internal1;
id internal2;
}
@end
==========MyClass.m==========
@interface MyClass ()
- (void)internalMethod;
@end
@implementation MyClass
- (void)internalMethod {
NSLog(@"%@ %@", internal1, internal2);
}
@end
Thanks to Objective-C 2.0 and class extensions we can put our internal method declaration into our .m file and also have the compiler check that it is implemented and warn us if it isn't (unlike if we added a simple category). What we haven't been able to do is do the same for our instance variables. Well we can now, so our code can now look like this:
==========MyClass.h==========
@interface MyClass
@end
==========MyClass.m==========
@interface MyClass () {
id internal1;
id internal2;
}
- (void)internalMethod;
@end
@implementation MyClass
- (void)internalMethod {
NSLog(@"%@ %@", internal1, internal2);
}
@end
Our internal instance variables really are internal now, which makes the header effectively become purely our public interface. And if you are feeling really crazy, you can have multiple class extensions:
==========MyClass.h==========
@interface MyClass
@end
==========MyClass.m==========
@interface MyClass () {
id internal1;
}
- (void)internalMethod;
@end
@interface MyClass () {
id internal2;
}
@end
@implementation MyClass
- (void)internalMethod {
NSLog(@"%@ %@", internal1, internal2);
}
@end
These may only seem like small enhancements, but they help you reduce the code you need to write and make that which you do much neater. It is little enhancements like this that keep trickling out that makes the life of an Objective-C developer that much easier.
(10) Comments
Building a Modern Cocoa App
Posted on 04/03/2010 at 06:13 PM in Coding
A while back I wrote a post on how I was pushing towards making my apps much more manageable, by separating my once monolithic app delegates and nibs into various view and window controllers. Yesterday Justin Williams wrote a post on his blog about Getting Started with Core Data, Bindings and NSViewController.
Cocoa has changed a lot over the years. I started programming on 10.3, when Xcode was a version 1.0 and Bindings, KVO and KVC were the new hotness. Over subsequent releases we gained Core Data, Objective-C 2.0, NSViewController, Garbage Collection and much more. I strongly believe that any modern Cocoa app should be using Core Data, Objective-C 2.0, Garbage Collection and NSViewController. Bindings should also be used where appropriate (I'll define where I think this is later).
Justin's post included a project he'd worked on, implementing core data tutorial application from CocoaDevCentral using several window and view controllers rather than one monolithic class and nib. The way he built his version was quite interesting, as it was differently to how I would have approached the task. As it was a relatively simple project, I thought it would be of benefit to some to provide an alternate way of building the same app. I don't think there has been two Cocoa developers giving two different ways of implementing an entire app before.
You can download the source for my version here. I also recommend downloading Justin's version. I'll first outline how Justin's implementation works and then go into how my implementation works and how it differs from Justin's.
The Application
But first it would make sense to outline the application. It is a simple blogging app. It consists of a main window containing a splitview. On the left is a list of posts, with an add button below. On the right are the details of the current post: the title, author, category and body. The author and category are chosen from a list which can be edited by clicking the edit button next to the field. This brings up a panel allowing editing of the author and category lists.
The data model is as shown below:

Justin's Implementation
Justin has structured the application as 3 window controllers, 2 view controllers and the app delegate:
- MDVCAppDelegate contains all the code to initialise the Core Data store and the main window controller. It also inserts the initial authors and categories if the database is empty.
- MDVCMainWindowController is the window controller for the main window. When the window is loaded it initialises the view controllers and adds their views to the splitview, and sets up the frame and autoresizing mask.
Perhaps the most interesting part of the whole implementation is that it uses a single NSArrayController in the main window's NIB, which is then passed to the view controllers when they are initialised. This array controller is in entity mode and bound to the managedObjectContext on the application's delegate. The add button's action is connected to the array controller. - MDVCPostsListViewController is a very light weight class. It just handles initialisation and pushes all the handling into the NIB. The table column is bound to the array controller that was passed in at initialisation
- MDVCPostDetailViewController is almost identical to the posts list view controller, except that it includes methods to show the authors and categories lists. It uses the selection on the passed in array controller to fill in the details. The NIB also contains array controllers for the authors and categories lists, which are bound to the app delegates managed object context.
- MDVCCategoriesWindowController is just a singleton that sets up the main window. Again, most of the logic is pushed to the NIB with an NSArrayController handling everything.
- MDVCAuthorsWindowController is identical to the categories window controllers, except that it handles authors
And that is all there is to Justin's implementation. It is very simple and most of the processing is pushed off to Core Data and NSArrayController.
My Implementation
I built my implementation with the same structure as my 3 existing apps. Rather than relying on core data and bindings completely, I use KVO manually and have a model controller that wraps around core data. I have a similar set up in terms of controllers: 3 window controllers, 2 view controllers and the app delegate. But I also have 9 extra classes, my model controller, 2 classes to simplify core data and 6 model classes generated by MOGenerator.
- M3MasterDetailVC_AppDelegate handles all the window controllers. In this case, all the window controllers are application global. As such I prefer to put the code handling them into the app delegate. You may be wondering how the editAuthors: and editCategories: methods are called, and all will be explained later in the post.
- M3MainWindowController holds and mangages the view controllers. It initialises the view controllers in its init method and adds them to the split view in awakeFromNib. The two subviews of the splitview are connected to IBOutlets. The code for creating a new post is also in here, as I'm no longer relying on bindings for adding and removing objects.
There is also the first bit of KVO usage. The window controller observes the selectedPost property on the posts list controller. When this changes it sets the post of the details controller to the newly selected post. - M3PostsListViewController provides 5 important methods. The first returns an array of posts from the model controller. This is used by the array controller in the NIB as its contentArray. The array controller is this time used in class mode, rather than entity mode, with the contained class set to M3Post. The reload data method tells KVO that the posts array has changed, which causes the array controller to refresh.
The selected post method returns the post object that is currently selected in the array controller, if there is one. Conversely selectPost sets the selected post on the array controller. And finally there is the tableViewSelectionDidChange: delegate method, which informs KVO that the selectedPost changed whenever the table selection changes. - M3PostDetailViewController only contains code for observing and returning the list of authors and categories. Most of the logic is in the nib, where an NSObjectController represents the selected post. Other than this the NIB is almost identical to Justin's version
- M3AuthorsWindowController contains code for listing, adding and deleting authors. The authors are displayed in the UI via an NSArrayController whose content array is set to the authors array. The add and delete actions are connected to the class which calls the model controller and invokes the appropriate KVO methods.
- M3CategoriesWindowController is identical to the authors window controller, except that it deals with categories
- M3ModelController is the main difference in the two implementations. It provides a single focus point through which all data creation, deletion and retrieval flows. While this may seem like overkill for this application, where bindings are pervasive, it is a very useful thing to have when you do a lot of work with data that doesn't involve bindings.
The init methods sets up a core data manger and a simple core data instance. It also checks if the database is empty (there are no authors) and if so inserts the initial content. The rest of the methods just deal with returning, creating or deleting objects.
The following two classes I group together as M3CoreData. They are classes I've built that make CoreData cleaner and simpler to access.
- M3CoreDataManager is where all the CoreData initialisation code that often resides in app delegates is pushed off to. It doesn't do anything special, it just makes life cleaner by pushing all the code you don't care about off into a class and putting the bits you do care about into an initialisation method.
- M3SimpleCoreData is where I encapsulate the code required to add and retrieve objects with core data. This code is very samey and very tedious and there's no good reason to write it every time.
And finally there are the 6 classes generated by MOGenerator. I've learned to swear by MOGenerator for my core data applications, it is removes all the hassle that you would otherwise have if you used Xcode's built in tool for generating model classes for core data entities. The only change from the generated code is an awakeFromInsert method in M3Post that sets the creation date.
Responder Chain Hacking
One thing I like to do is abuse the responder chain (please don't call the police!). In larger applications I make sure every view and window controller on screen is in the responder chain. This has the advantage of being able to put methods where they belong, rather than where you can access them. For example, the newPost: method is in the window controller. In some of my apps I have it in the side bar controller, because that is all that cares about adding a post.
You can then connect you actions to the first responder proxy in the NIB. It will traverse the responder chain and find the appropriate class and then invoke the method. You can then control whether the method can be invoked by overriding respondsToSelector, which will give you menu validation control.
This is how the editAuthors: and editCategories: methods in the app delegate are called. The buttons in the details view are connected to these methods via the first responder proxy. As the app delegate is in the responder chain it will be the one receiving the methods (as nothing else futher up the chain implements them).
Where To Use Bindings
Bindings are a contentious issue. Some people love them, some people hate them. The fact is that they are incredibly useful and can save a LOT of code. To give one example, the new inline inspector in CCP 1.4 was initially all handled in code. Unfortunately this required a lot of logic for handling no selection, multiple selections etc. In the end I just replaced the code with bindings to an NSArrayController and managed to delete around 100-150 lines of code.
But bindings aren't useful in all cases. Over the years I've kept changing how I use bindings. I used to use them everywhere, then went through a phase where I didn't use them at all, but have now settled on a good middle ground, where I use them where they work best. So where is that?
- Preferences - bindings are ideal for handling your preferences. Most preferences are just booleans, strings or integers, handled by checkboxes, text fields and popup lists/radio buttons. These can be bound directly to the shared user defaults controller and remove the vast majority of code from your preferences controller.
- Forms - this is sort of a superset of the preferences use case. Anywhere that you have a form for displaying and/or editing data on an object (or especially in cases of multiple selections), you should use bindings. It saves on a huge amount of code and it handles all the issues of editing multiple items at once, populating pop up lists etc
- Simple Tables - I have found that any sort of simple table should be implemented using bindings. By simple I mean ones that don't require any complicated logic in the data source. If you just have an array of objects and you want to display their properties in a table, use bindings, it is much simpler. However, do NOT use bindings for outline views. NSTreeController is evil and should be avoided like the plague. Consider this a public service warning, just avoid it and save yourself a lot of pain.
Use New Tech, It's There For A Reason
There are a lot of people who avoid some of the new technology in Cocoa. Some don't like Core Data because it seems like voodoo (if you learn a little bit more you'll actually find that it is quite simple, yet incredibly powerful) and some dislike Garbage Collection because of experiences with other garbage collectors (in reality the GC in Obj-C not only saves you the pain of memory management but also of threading, while also potentially being faster than a retain/release system).
You should always be looking at the new technology that comes in each release of Cocoa, most of it can save you 100s, if not 1000s of lines of code if you can adopt it. It can also make the code you do have much easier to manage. It seems odd that most people would agree it is insane to write and use an alternative to something like NSTextView, yet will write and use an alternative to some more modern technology in Cocoa.
(5) Comments
Version Control UI Design
Posted on 12/02/2010 at 12:01 PM in Coding
As with many of my blog posts, it is often a tweet or another blog post that made me want to write my thoughts. In this case it is both:
Just accidentally blew away 16 files' & days' worth of work with hg. Looked up, TIme Machine had just finished. Lost < 1 min. of work.
- @incanus77
That tweet prompted Wolf Rentzsch to write this post about how Time Machine is your version control "safety net". To me both of these are shocking. It seems that the tweeted mishap may have been user error, but it made me look into how the various user interfaces help protect the user.
Your VCS should protect you
For a long while I was opposed to VCSs, mostly due to faffing around with subversion and getting nowhere. With DVCSs I've become an addict. The issue is that DVCSs also try to be clever. Their primary goal is to protect you from yourself, to make sure your code and its history are safe. Essentially your commit history should be like a stack. 99% of the time you push onto the stack, rarely you need to pop off a stack. You can read the contents of the stack as you want. But you shouldn't be able to modify the internals of the stack.
This is why I consider the many rebase plugins/commands in DVCSs to be harmful. I feel that rebase should be viewed as a mixture of goto, premature optimisation and Jeremy Kyle all rolled into one ie don't touch it unless you know what you're doing and are wearing many layers of protection, and even then it probably isn't such a good idea. Some people swear by rebase, but I feel that you shouldn't be messing with what should be treated as sacred.
Your repository is not a toy, so stop playing with it.
Protecting against destructive actions
This is where we get onto UI. I've never really given much thought to command line UIs, but comparing git, Mercurial and Bazaar I've found subtle differences in the UI that make it harder or easier for a user to perform a destructive action. These really fall into 3 categories: confirmations, making it hard to destroy and separating destructive actions.
In the case of the tweet at the start, I looked into the command that was performed: hg update -C . It offers no confirmation dialogue, it just cleans out the items that have changed. It doesn't make it hard to destroy changes and it is a one character option which means it is easy to do. I'm not sure about git but the equivalent in Bazaar would be bzr revert --no-backup. Of course there's no real reason to run --no-backup, it helps save your arse just in case and cleaning it up is just a case of bzr clean-tree --detritus (which lists the files to be deleted and asks for a confirmation).
One of the other examples is from the blog post. git branch -d abranch will delete the branch called abranch. Now to me this seems incredibly dangerous as there isn't any confirmation given. Occasionally I've seen warnings to use the uppercase -D option if changes aren't merged into the parent, but sometimes even those may not appear. If you're doing something like deleting a branch then it should be made harder to do. Really it should be git branch --delete-branch abranch and then ask you to confirm the delete.
Destructive actions should really be moved out into other commands if possible. bzr has 2 such commands: uncommit and clean-tree. Uncommit and clean-tree both list the items that will be removed and ask you to confirm. This makes the user double check what they're doing to confirm what they are doing. Now these commands could be moved into other commands. Uncommit could be made into bzr commit -d, but by separating them out you are making the user think that this is a different thing and making it harder for them.
The hypocrisy of UI design
It does seem very hypocritical, when most of UI design is a push to make life easier for a user, to advocate making it harder. But as odd as it may seem, making something harder may make it more usable. Now by harder I don't mean make a series of convoluted steps that require an animal sacrifice. I mean add an extra step to any potentially dangerous action. Tell the user exactly what the result of the action will be and ask them to confirm it.
Obviously you should provide undo when possible, but sometimes it isn't. Think about where in your UI you place these actions and consider whether you need them there at all. Don't put a 'wipe library' button right next to one of the most commonly used buttons in your UI, and no matter where you put it, if you can't offer an undo then tell the user exactly what you will do and make them confirm. Force them to pay attention to what they are doing. They'll thank you for it, even if it is just by not complaining to you (or worse to the internet) about how your software lost their data without warning.
(3) Comments
The Rules of Communication
Posted on 05/02/2010 at 10:28 PM in Coding
At NSConference Dave Dribin made the following statement in a slide:
Delegates are preferable to Notifications which are preferable to KVO
Now this caused a bit of a murmur on Twitter, as it was taken as "KVO is bad". As this is an important topic and not one that can easily fit into 140 characters I thought I would write a post to outline my rules for when to use each technology and why use them where I do.
Rule #1: Always use delegates for 1 to 1 relationships
One of the main reasons delegates were listed as the most preferable is that they provide the least 'magic' way of communicating between objects while keeping them loosely coupled. It sends the message directly to the object and you can see what method is being run. As such it makes your code more self explanatory. So whenever you have a 1 to 1 relationship between two classes, opt for delegation over notification.
Rule #2: Use notifications for communicating events to many objects
Notifications should really be used wherever you would use a delegate, but need to communicate with any number of objects. They should really be thought of as 1 to many delegates. Quite often in Cocoa you will see a case where there is a notification and a delegate method for the same event (eg change of selection in a table view). These are cases where 80% of the time you just need a 1 to 1 relationship, but occasionally do need a 1 to many relationship. You will rarely encounter this in your own code, unless you are building a class for use in multiple apps.
Rule #3: Use KVO for communicating data model changes
This is where I have found KVO to be the most powerful. You need to keep various UI elements in sync with your data model. Changing the value of the model from one view should also update the value in other views. KVO was built for exactly this situation and as such requires much less code than delegation and notifications.
To achieve the same effect with delegation or notifications you would have to add delegate methods or post a notification in each setter method of each model object. This obviously is a lot of code that needs to be written. Code that could have bugs and code that makes your source more cluttered. KVO of a value in an object requires just one line of code and the implementation of one method. And if you use bindings then it is actually no code at all.
Rule #4: Use blocks instead of callback delegates
I'll start with the exception to this: if you have multiple callback options then use delegates (eg NSURLConnection). But the vast majority of asynchronous operations need just a single callback. In these cases, if you are using Mac OS X 10.6, then you should be using blocks instead of delegates. Blocks reduce the layer of indirection in your source by putting the call back information inline with the invocation of the method.
The next two rules aren't quite rules of communication, but are relevant to the discussion at hand.
Rule #5: Comment anything that isn't clear
This should be pretty obvious. If something in your code isn't explicitly clear from the code itself then comment it. If you are sending off a notification say why you are sending it off, so you can get an idea of what it is doing elsewhere in the application.
Rule #6: If something seems like magic, learn how it works
There is no such thing as magic in programming, simply things we don't fully understand. If notifications, delegation, KVO or anything else seems like magic, then read up the documentation on it or ask a developer experienced in that area to explain how it works. When you find out how they work you realise that what seems like magic is fundamentally a very simple process.
Ultimately, what Dave said was right for some scenarios. Each technology has its use case and you should only use it where it is needed. You should always aim for the smallest amount of indirection in your code while still retaining loose coupling of classes. KVO and notifications are necessary in some occasions (unless you want to go crazy with delegation) but they should only be used when they are needed.