Posts filed under ‘cocoa’

How Tim Burks and Nu Stole the Show at C4[1]

Edit: Fixed some factual inaccuracies about the language itself.

Tim Burks, noted contributor to RubyCocoa and creator of RubyObjC, gave a talk at C4[1] about his experiences with creating a Ruby <-> ObjectiveC bridge, and the problems he overcame in doing so. It was an interesting presentation, and we were all suitably appreciative when he showed his custom visual chip-design software written in Ruby with a Cocoa interface.

And then he dropped a bombshell.

For the past year, Tim’s been working on a new dialect of Lisp – written in Objective-C – called Nu. Here are its features (more precisely, here are the ones that I remember; I was so awestruck that many went over my head):

  • Interpreted, running on top of Objective-C.
  • Scheme-y syntax. Everything is an s-expression (data is code, code is data). Variable assignment was done without let-clauses (which are a pain in the ass) – all one has to do was (set varname value).
  • Variable sigils to indicate variable scope.
  • True object-orientation – everything is an object.
  • True closures with the do-statement – which, incidentally, is how Ruby should have done it.
  • Macros. HOLY CRAP, MACROS! When Tim showed us an example of using define-macro for syntactical abstraction, Wolf Rentzsch and I started spontaneously applauding. His example even contained an example of absolutely beautiful exception handling that should be familiar to anyone with any ObjC or Ruby experience.
  • Symbol generation (__) to make macros hygenic and prevent variable name conflicts.
  • Nu data objects are Cocoa classes – the strings are NSStrings, the arrays NSArrays, etc.
  • Ability to create new Obj-C classes from inside Nu.
  • Interfaces with Cocoa libraries – you can access Core Data stores from within Nu in a much easier fashion than pure ObjC, thanks to Tim’s very clever idea of using a $session global to store the NSManagedObjectModel, NSManagedObjectContext, and NSPersistentStoreCoordinator.
  • Ruby-style string interpolation with #{}.
  • Regular expressions.
  • Positively drool-inducing metaprogramming, including a simulation of Ruby’s method_missing functionality.
  • A web-based templating system similar to ERb in 80 lines of Nu code – compare that with the 422 lines of code in erb.rb.

Tim showed us a MarsEdit-like blog editor written entirely in Nu, using Core Data as its backend – and then showed us the built-in Nu web server inside that program, complete with beautiful CSS/HTML/Ajax.

As F-Script is to Smalltalk, so Nu is to Lisp. Tim said that he hopes someday to open-source Nu; if he does, he will introduce what is quite possibly the most exciting development in the Lisp-related community in a long time. I don’t think I speak for just myself when I say I cannot wait to get my hands on it.

August 12, 2007 at 3:09 pm 4 comments

Map, Filter and Reduce in Cocoa

After working in Scheme, Python or Ruby, all of which (more or less) support function objects and the map(), filter() and reduce() functions, languages that don’t seem to be somewhat cumbersome. Cocoa manages to get these paradigms almost correctly implemented.

map()

One would think that Objective-C’s ability to pass functions around as objects in the form of selectors would make writing a map() method easy. Observe, however, the crucial differences of the NSArray equivalent to map(). (For those unfamilar with it, map(), when given an array and a method/function taking one argument, returns the result of mapping the function onto each item of the array.)

From the NSArray documentation:

makeObjectsPerformSelector:

Sends the aSelector message to each object in the array, starting with the first object and continuing through the array to the last object.

- (void)makeObjectsPerformSelector:(SEL)aSelector
Discussion

The aSelector method must not take any arguments. It shouldn’t have the side effect of modifying the receiving array.

This is different on no fewer than two levels. Firstly, even in the NSMutableArray subclass, this method is not allowed to have side effects. Frankly, I can think of few situations in which I would need to map an idempotent function onto an array; the point of map() is to be able to apply a function quickly to every element of an array and get back the changes! Secondly, an unaware or hurried programmer would think that this function was implemented so that one could write code like this:

- (void)printAnObject:(id)obj
{
NSLog([obj description]);
}

and then do this:
[anArray makeObjectsPerformSelector: @selector(printAnObject:)];

This is not the case – the above code would just make each element call printAnObject:, not call printAnObject with each element. I’m sure that to some it seems obvious, but I, for one, found this to be an insidiously tricky wart.

However, there is a (limited) workaround.

NSArray’s valueForKey: method (somewhat counter-intuitively) returns the result of invoking valueForKey on each of the array’s elements. As such, one can map KVC functions onto arrays. For example:

NSArray *arr = [NSArray arrayWithObjects: @"Get", @"CenterStage", @"0.6.2", @"because", @"it", @"rocks", nil];
[arr objectForKey: @"length"]; // returns [3, 10, 6, 7, 2, 5]

This can be used in many helpful ways; sadly, it only works on KVC-compliant properties/methods.

Anyway, moving on…

filter()

With OS X 10.4, Apple introduced the NSArray filteredArrayUsingPredicate: method, which allows one to filter an array based on criteria established by an NSPredicate. Observe:

NSArray *arr = [NSArray arrayWithObjects: @"This", @"is", @"the", @"first", @"CenterStage", @"release", @"I", @"helped", nil];
arr = [arr filteredArrayWithPredicate: [NSPredicate predicateWithFormat: @"SELF.length > 5"]]; // arr is now [@"CenterStage", "@"release", @"helped"]

Verbose, but useful.

reduce()

Frankly, Apple don’t give us any way to do this in pure Cocoa. The best way I’ve found (if you really need this, which is less often than one needs map() and filter()) is to use the F-Script framework and apply the \ operator to an array. Unfortunately, this takes a bit of overhead.

In conclusion, Cocoa and Objective-C almost bring us the joys of functional programming. We can only hope that Leopard and Obj-C 2.0 improve on these in some way.

List comprehensions, anyone?

June 18, 2007 at 10:42 pm 4 comments

Cocoa Snippet: Detonate your Cursor

- (IBAction)poofCursor:(id)sender
{
NSShowAnimationEffect(NSAnimationEffectPoof, [NSEvent mouseLocation], NSZeroSize, NULL, NULL, NULL);
[NSCursor hide];
}

In case you can’t figure it out, this code shows the *poof* animation one gets when dragging items off the Dock at the current mouse location, then hides the mouse. The overall effect resembles the mouse cursor exploding.

April 18, 2007 at 12:33 pm

Five Things that Suck About Objective-C and Cocoa

Things have been quiet here in this blog. Too quiet. As such, I’m keeping the name-five-things-you-hate-about-a-language-you-like ball rolling, having seen it rolled with zest and vigor by brian d foy, Titus, Jacob Kaplan-Moss and Vincent.

Without further ado:

Five Things that Suck About Objective-C/Cocoa:

  1. Syntax for NSString literals. For the uninitiated, in Objective-C code enclosing "insomnia" in simple double-quotes creates a C-style char[] string; if you wish to use the far more powerful and versatile Objective-C NSString class, you must add an @ (making @"insomnia"). Backwards-compatibility with C is a good and useful thing, but why require more keystrokes to do the most commonly-used thing? I myself last weekend puzzled over a wonderfully non-specific “invalid reciever” error for a long time before realizing that I forgot an @ when sending strings to an arrayWithObjects: method. Aside from that, why use the @-sign as a prefix for NSStrings when it’s used in a plethora of other places, such as @interface, @implementation, @end and @selector? Though 90% of my @-key-presses in Textmate are prefixes to NSStrings, I can’t have a keypress of @ automatically expand to @”” – there are too many other things to do with the poor little @-sign. The oft-neglected | (pipe or vertical bar, I’ve heard both) character is far less disruptive to the flow of typing.
  2. reallyLongAndCamelCasedMethodNamesGetAnnoying. I refer specifically to the lovely NSWorkspace method openURLs: withAppBundleIdentifier: options: additionalEventParamDescriptor: launchIdentifiers:
    And ObjC method names can be concise yet informative – take for example NSString’s compare: options: range: locale:. I must admit, this complaint is not entirely valid, especially considering Textmate/XCode’s fancy code completion.
  3. No operator overloading. Come on, guys – why reject this crucial part of Smalltalk heritage? I, for one, am sick of writing objectAtIndex and objectForKey: as compared to Python’s []. Though Smalltalk allows one to define new operators, I’d be perfectly happy to settle for a few overloadable operators (string concatenation is desperately needed).
  4. Mysterious helper methods. I didn’t know of the existence of NSHomeDirectory(), NSTemporaryDirectory(), or NSClassFromString() until very recently. True, this is my fault, but I think that F-Script’s idea of storing all of these methods in a singleton System object is excellent, and much more in line with Objective-C’s Smalltalk heritage. (Actually, I have a half-finished ObjC class that makes NSBeep() and all those other miscellaneous C functions into class methods; if there’s any interest, I’ll finish and release it. I suppose that makes this complaint invalid. Oh well.)
  5. File management is a mess. Essential code is scattered throughout NSWorkspace (in all its brain-dead glory), NSFileManager, NSFileHandle, NSPipe, NSDirectoryEnumerator, and NSData – few things are as infuriating as hunting down the correct class that does exactly what I want. (Actually, no. Finding a better solution after thirty minutes of hacking around some perceived inadequacy is worse.

So there you have it. To be honest, it took me quite a while to write this, mainly because Objective-C is such a great language and Cocoa is such a great set of libraries. I suppose that the imperfections in a consistently useful and friendly toolkits stand out, and in retrospect I sort of feel guilty for my picky attitude. After all, it could be much, much worse.

April 5, 2007 at 11:59 pm 3 comments

Cocoa Snippet: Finding a File’s ‘Kind’

+ (NSString *)humanReadableFileType:(NSString *)path
{
NSString *kind = nil;
NSURL *url = [NSURL fileURLWithPath:[path stringByExpandingTildeInPath]];
LSCopyKindStringForURL((CFURLRef)url, (CFStringRef *)&kind);
return kind ? [kind autorelease] : @""; // If kind happens to be an empty string, don't autorelease it
}

Thanks very much to Peter Hosey and David Phillip Oster for being unbelievably helpful in clearing up the labyrinth that is CSStringRef to NSString usage.

January 7, 2007 at 5:46 pm 6 comments

Objective-C 2.0

As many of you know, Apple is releasing the new incarnation of Objective-C (creatively dubbed Objective-C 2.0) along with XCode 3.0 and Leopard. Though much of it is hidden under Apple’s elaborate nondisclosure agreements, people like Andy Matushack and Scott Stevenson as well as other sites have uncovered more information from the ObjC mailing lists and repositories than the meager scraps of info that Apple released on their website.

Since I can’t give any new information about this, I’ll just list my opinions, then brace for the reaming I’ll receive in the comments.

Disclaimer: Apple may change all of these things. This post is naught but conjecture heaped upon conjecture.

(more…)

December 27, 2006 at 8:24 pm 3 comments

NSManagedObject: better than sliced bread? (Yes.)

(Update: as usual, Scott Stevenson totally kicked my ass:

+ (EPFoobarMO *)foobarWithDefaultContext
{
return [NSEntityDescription insertNewObjectForEntityForName:@"Foobar" inManagedObjectContext: [[NSApp delegate] managedObjectContext];
}

I often forget that I’m a cretin preaching to a crowd of really smart people.)

I kid you not: NSManagedObject and Core Data are becoming some of my favorite coding structures/paradigms ever. (I suppose I have Wolf Rentzsch to thank; by the way, mogenerator v1.1 is out. Check it out.) It’s just so awesome – so nice not to have to futz around with NSUndoManager, NSCoding, and all the other minutiae that some brave souls worked with in years past.

I got rejected – not just deferred, rejected – from the University of Chicago. :( As such, I don’t really have time to write a very lengthy entry; therefore, I’ll just leave you with this little question/guide.

The official way of instantiating an instance/subclass of NSManagedObject is (I think) to use the NSManagedObject class methodinitWithEntity:insertIntoManagedObjectContext:, like so: (we are assuming that there’s an NSManagedObjectModel and NSManagedObjectContext named model and context, respectively:

NSEntityDescription *e = [[model entitiesByName] objectForKey: @"Foobar"];
EPFoobarMO *foo = [[EPFoobarMO alloc] initWithEntity: e insertIntoManagedObjectContext: context];

Since they’re nice people, Apple gave us a convenience method:

EPFoobarMO *foo = [NSEntityDescription insertNewObjectForEntityForName: @"Foobar" inManagedObjectContext: context];

But if we’re sticking to the MVC paradigm (which we are, aren’t we?), one wants to put the initialization code for the EPFoobarMO object inside the EPFoobarMO .m/.h file.

+ (EPFoobarMO *)foobarWithContext:(NSManagedObjectContext *)context
{
// According to the docs the object returned is autoreleased
return [NSEntityDescription insertNewObjectForEntityForName:@"Foobar"
inManagedObjectContext:context];
}

But it’s ugly to have to pass the NSManagedObjectContext to the initializer every time. We could stick it inside the app’s controller:

- (EPFoobarMO *) foobar
{
return insertNewObjectForEntityForName:@"Foobar"
inManagedObjectContext:[self managedObjectContext]];
}

But that’s a flagrant violation of the MVC rules. (Of course, if you’re ignoring them, then this is an ideal solution. But down that way lies Nyarlathotep.)

Or we could resort to the insanity that is the C preprocessor. (I would give a code sample, but I don’t want to hate myself.)

Anyway, what do you think? Leave comments with your opinions or to alert me of any blatant inaccuracies.

December 27, 2006 at 4:25 am 1 comment

I got you a present!

[Update: Looks like Dave Batton beat me to the punch. *cries*]

Merry Atheist Children Get Presents Day Christmas, everyone!

In celebration of this day, I am giving you a gift – yes, a gift – from me to you. Yes, you. It is my first piece of public code – well, actually, that’s a lie. I posted this some months ago – I consider it my cleverest Java hack EVER. I’m quite proud of it. No! Digression! Must…focus. Wait…my second was this.

Anyway, it’s my third piece of public code, and I hope you like it. In short, it’s called PVCGradientCell, and it’s a subclass of NSTextFieldCell that uses the CTGradient class to mimic the Source List found in iTunes 6. It’s notable for several reasons:

  1. Despite the name of the file (PVCGradientTable) , it is actually not a subclass of NSTableView – all the code is contained in the NSTextFieldCell subclass. This is unlike Matt Gemmell’s iTableView, which requires subclassing of NSTableView. (By the way, props to Matt – his iTableView helped me fix a lot of bugs.)
  2. It uses Chad Weider’s CTGradient code to render the gradient – the majority of implementations use either stretching images or bare CoreImage code.
  3. It allows you to enable centering the text vertically, a lá Daniel Jalkut’s RSVerticallyCenteredTextCell.
  4. It allows one to specify whether the text should be bold when clicked upon.
  5. It freshens your breath.

Here’s a screenshot, with the text bolded and vertically centered:

PVCGradientScreenshot

You can grab it here, or check it out from my Subversion repository (courtesy of Assembla – great job, guys!) here:
http://tools.assembla.com/svn/importantshock

Use the username and password ‘anonymous‘ (without quotes, of course) to access the repository.

Bug reports, accolades, fame, and large sacks of cash are welcome at:

ironswallow at gmail dot etc

By the way, PVC was the initial acronym for the Cocoa application I’m working on.

Anyway, I hope that y’all have a rockin’ Christmas. Oh, and check out Scott Stevenson’s really neat THCalendarInfo present to you; it kinda owns my present in terms of complexity. (It reminds me of the Ruby linguistics module in terms of slickness and usefulness.)

Bye!

December 25, 2006 at 6:11 pm 4 comments

mogenerator, or how I nearly abandoned Core Data

Unfortunately, my Macbook Pro is out of commission due to a broken fan (I’ve sent it in to Apple; they’d better send it back soon! I’m dying here!), so I’m just going to blog about a mini-renaissance I had when working with Core Data last week.

When I first saw Core Data, I couldn’t believe my eyes. Apple’s developer tools now had a simple way to graphically model as many parts of an MVC application as possible – Interface Builder for the view, Cocoa Bindings (and custom logic) for the controller, and now Core Data for the modeling. Add in the fact that I had heard nothing but praise for it, and I was completely sold. I created the model for my application, prototyped a view, and flipped to the documentation on Core Data’s NSManagedObject.

It was, to say the least, an unpleasant surprise. Though I adored the fact that Core Data would take care of undo/redo, saving, archival formats, and saving data, I didn’t want to start using valueForKey:. setValue: forKey, primitiveValueForKey:, and setPrimitiveValue: forKey: instead of the mutator methods that I had grown to love for their combination of ease-of-use and added maintainability. Sure, I could have made a million subclasses of NSManagedObject, but the idea of doing that manually struck me as tedious – and if there’s anything I loathe, it’s tedium. And updating every object every time I made a change to the Core Data model struck me as a maintainability nightmare.

Though it may reflect poorly on me as a programmer, I considered abandoning Core Data. The magic which it brought to undo/redo/saving/archiving could not overcome the reluctance I had to view all my objects as NSManagedObjects – which, frankly, seems like quite a breach of the Model part of the MVC philosophy.

But hope lay in wait. At the bottom of some Google results about subclassing NSManagedObject, I found this page from Jonathan ‘Wolf’ Rentzsch – one of my idols, both for his coding and his vocal pro-Cocoa advocacy – about an unbelievably clever tool named mogenerator.

In short, mogenerator reads the data you have stored in an .xcdatamodel file, extracts the information about each Entity one has created, creates two subclasses of NSManagedObject for each Entity, changes the .xcdatamodel file automatically so that your Entities inherit from their proper classes, and adds code for all necessary accessor and mutator methods – in short, it removes everything I resented about Core Data.

Why two subclasses? Because if I decide to make a change to the data model, I don’t wont to worry about overwriting my own code with the automatically generated code that mogenerator creates for me. To solve this problem, Wolf has his program use one of the two files for automatically generated code, and allows one to use the second – which extends the first file’s class – for one’s own nefarious purposes. If you ever update the .xcdatamodel file, all you need to do is run mogenerator again, and only the file with the automatically generated code will be overwritten; you can be sure that the custom application logic you’ve written will stay intact.

This is a stunningly useful program, and I don’t know why people aren’t proclaiming it’s merits hither and yon. mogenerator allows one to forgo all compromise with Core Data – you get all the advantages of an NSManagedObject without sacrificing the familiar paradigm of creating specific .c/.h files for each object’s code. My thanks go out to Rentzsch for such an amazing tool.

December 19, 2006 at 6:24 pm 4 comments

It’s Hard Out Here for an MVC Advocate

Edit: I finally got the Interface Builder palette mentioned herein working. I’ll post a screenshot sometime later. I also cleared up some language.

In the past, I have alluded to the fact that I am a diehard Model-View-Controller advocate. I stay remarkably lax on other issues – I don’t mind breaking encapsulation, enjoy both static and dynamic typing, and even advocate paradigms other than OOP for certain applications. However, when it comes to GUI or web application development, I will defend Smalltalk’s Model-View-Controller paradigm to the death. In my still-inchoate Cocoa application, I’m using Interface Builder for the view, Core Data for the model, and Cocoa Bindings + my own code for the controller.

The problem emerges when I need to use the smattering of custom widgets that I’ve selected. Since creating Interface Builder palettes is so difficult, it’s hard to get people to make them – but MVC falls apart the moment you have to exit out of Interface Builder to make visual changes to your own instances of custom widgets.

Therefore, I am stuck with a hard decision. Do I break the MVC design pattern and make a zillion little subclasses of NSView, in which I stick a whole bunch of initialization code? It would be a lot easier, especially when one considers how hard it is to create an IBPalette.

But it’s so ugly! I don’t want a custom-made NSView subclass for each color CTGradient that I want! And until Chad Weider releases a CTGradientWell (please, please, please, pretty please?) making a PTGradientView will be quite difficult.

Bah. Any comments/help/IB Palettes will be appreciated.

December 6, 2006 at 5:47 pm 5 comments

Older Posts


About Me



I'm Patrick Thomson. This was a blog about computer programming and computer science that I wrote in high school and college. I have since disavowed many of the views expressed on this site, but I'm keeping it around out of fondness.

If you like this, you might want to check out my Twitter or Tumblr, both of which are occasionally about code.

Blog Stats

  • 535,847 hits

Follow

Get every new post delivered to your Inbox.