See the problem? NSPoint is actually a struct (as is its identical cousin CGPoint). It’s not an object. You shouldn’t pass a struct where Cocoa is expecting an object because weird things can happen (usually crashes, or inexplicable numerical values). The solution is to break the point apart into _position.x and _position.y, or use NSStringFromPoint (on the desktop) or NSStringFromCGPoint (on iOS) to make a string description of the object.

That got me thinking about Cocoa, objects, and structs. It’s not just the points that are structs. NSRect is a struct. NSRange. NSSize.

Why do the Cocoa platforms have all these structs? Wouldn’t it be nicer and more object-oriented if they were full-fledged objects? That’s a pretty common question asked by newcomers to the platform. It would certainly make things a lot more consistent API-wise, instead of remembering that this NS-thing over here is a struct and that NS-thing over there is an object. It’d be cool to be able to add categories onto NSRect to simplify some app-specific coordinate transforms.

That’s sixteen megabytes, not gigabytes. I have a sixteen megabyte mp3 of Rhapsody in Blue that would occupy all of the RAM of a stock NeXT machine. That’s 1/32nd of the RAM inside an iPhone4S. So, not a lot of memory in those days.

It’s kind of hard to compare performance of the processors, but by looking at FLOPs (floating point operations per second), the 68040 can do 3.5, and the iPad 2 gets 160. So by crude guesstimation, floating-point power is a factor of 45 times faster today.

The original NeXT cube was, by today’s standards, extremely resource constrained. But it did an incredible amount of work. It ran a full-blown Unix operating system. It had a monstrously huge display for its time. It had Display Postscript for drawing on that screen - essentially the computational guts of a laser printer. It also had the earliest form of the toolkit we now call Cocoa. That’s a lot of work that the machine was doing.

Nowadays, we create and destroy objects with reckless abandon. They appear to us to be as lightweight as structures. I think (mostly) nothing of creating an NSArray to hold a single NSNumber wrapping a float so that I can pass it to a method. Back in the mists of time, though, objects were proportionally much heavier weight.

Every Objective-C object contains a pointer, called isa, that points to its class. There’s four bytes of overhead. A NSPoint holds two floats, for a total of 8 bytes, so you’ve got a 50% overhead just for the isa pointer - you’d need 12 bytes now to store the point.

Objective-C objects are dynamically allocated, ultimately boiling down to a call like malloc or something similar. There is computational overhead with each allocated block, with malloc juggling free lists and data structures, plus it needs some place to store the size of the block. Frequently there’s padding on one or both ends of the allocated memory. That can be overhead consuming the same amount of memory (or more!) than the data being stored. If you browse through Cocoa, you’ll see that most of the objects are pretty heavy-weight, making the overhead of the isa pointer and malloc bookkeeping proportionally much much smaller.

Dynamic memory allocation can also be very slow. You call into a library. There’s locks involved. You might need to dip into the kernel to get a couple more pages of memory. Maybe memory has to be paged back in. You make a similar round-trip when destroying the object. Whereas a simple struct on the stack is “created” by adjusting the value of the stack pointer. That is a very fast operation.

The NS-structs you encounter tend to be ephemeral. You use an NSSize or an NSRect for a couple of calculations, and then you’re done. Same with NSRanges - get the coordinates of a substring match, use it to index something else, and then you’re done. If ranges were objects, this very lightweight operation would suddenly turn very heavy-weight, involving trips through lock-land. On the original NeXT cube, this could have easily dogged performance.

Nowadays, machines are so fast (even the portable ones) that a couple dozen extra memory allocations here and here is not a big deal, so having things like points and sizes being first-class objects wouldn’t be a Big Deal. But it’s very difficult to change a legacy code base, especially one as big and as old as Cocoa and its ecosystem, so we’re stuck with the NS-structures. And like a computational Stockholm Syndrome, I kind of like knowing that rects, sizes, and whatnot are stack-based structures and extremely lightweight. I have no qualms about using as many of them as I need, while I still feel a little twinge of guilt when I have to allocate something.