I can’t take credit for finding this myself. Gilad Gurantz forwarded it to me. From the Quartz Event Services documentation:
CGEventTimestamp
Defines the elapsed time in nanoseconds since startup that a Quartz event occurred.
typedef uint64_t CGEventTimestamp;
Discussion
An event timestamp is a big, unsigned, 64-bit number. That’s big, really big. You just won’t believe how vastly, hugely, mind-bogglingly big it is. You may think your application has been running for a long time, but that’s just peanuts to an event timestamp.
So if my math is right, “a long time” translates into over 2850 years. And it’s counted since the last reboot. I think we’ll avoid the Y2K problem on this one.
Answering a question on Stack Overflow, asking for an explanation of the Application Delegate, how it is accessed and created.
In Cocoa, a delegate is an object that another object defers to on questions of behavior and informs about changes in its state. For instance, a UITableViewDelegate is responsible for answering questions about how the UITableView should behave when selections are made or rows are reordered. It is the object that the UITableView asks when it wants to know how high a particular row should be. In the Model-View-Controller paradigm, delegates are Controllers, and many delegates’ names end in “Controller.”
Read more…
Say you want to talk to another app through Applescript. With 10.5, you can much more easily get there from Cocoa without complex forays into CoreServices, Carbon and AppleEvents. The docs on how to do it are a little thin at times (as all Applescript docs are), so let’s walk through it. The relevant docs you’ll want to read are these:
Learning Applescript
Scripting Bridge Framework Reference
Scripting Bridge Sample Code
And most importantly (and most hidden):
SBSystemPref’s Magical README
And now for a step-by-step example. We’re going to send some mail with an attachment through Mail.app.
Read more…
See Take 2 for an updated approach to this problem.
When faced with mixing C++ and ObjC code, there are two main approaches. One is to just work in Objective-C++ through the entire project. I don’t like this approach. I find the mixing of ObjC and C++ classes very confusing, since they cannot be used interchangeably and require completely different memory management. The mix of class hierarchies and naming conventions lead to a lot of confusion when we introduce people to code that does this kind of mixing.
My opinion is that ObjC and C++ have very different patterns, so it is important to pick one to be in charge and wrap the other. So if you basically have an C++ program than needs a little ObjC to talk to the UI, then wrap the ObjC in C++ objects. If you basically have an ObjC program that needs a C++ middleware, then wrap the C++ objects. Read more…
Apple finally updated the Memory Management Guide to deal with IBOutlets.
They came to the same recommendation that many of us have. Treat them exactly like other properties. Mark them as retain properties, release them in -dealloc, and overload -setView to clear them in low-memory situations. This last recommendation was one that many of us used, but was based on undocumented behaviors. Apple finally documented the behavior because there’s no other good way to do it given their internal implementation.
Unfortunately they haven’t updated the “Using View Controllers” documentation to include this stuff, and the section on how -loadView works is still a bit vague. I’ve sent them feedback on those pages.
For those of you familiar with SQL and coming to Core Data, you probably want to separate the concept of “database” into the two kinds we’re discussing here. There are relational databases, which is what you’re probably used to, and object databases, which is what Core Data provides. Core Data happens to implement its object database on top of a relational database (SQLite), but that is a opaque implementation detail.
In a relational database, the key actions are the select and the transaction. In the select, you ask the database to form itself into a collection of columns (joins are just a fancy way of doing that), filter and sort itself according to some set of rules, and then return you a linear collection of rows. In the transaction, you inform the system that you are beginning a transaction, instruct the database to perform a series of transformations, and then commit or roll-back the transaction. It’s a great model, but Core Data doesn’t look much like it. Read more…
Here are the three magic words: +alloc, -copy and +new. If you commit these magic words to memory, and devote yourself to a life of accessors, then Cocoa memory management should cause you no fear.
For those interested in the path to memory management enlightenment, you should first deeply understand every word of the Memory Management Rules. Don’t be afraid, it is very short, and if you will commit it to heart, you will avoid much suffering in the future. Read more…
Unregistering
Because these bugs are very hard to track down and very easy to avoid, I’d like to direct everyone’s attention to how to properly unregister for notifications.
If your object uses NSNotificationCenter ever, you must add the following to -dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self];
This removes you from all notifications. If you fail to do this, and you are dealloc’ed, and a notification you were observing is later posted, the application will crash with a bizarre access violation deep in NSNotificationCenter when it tries to post to an object (you) which no longer exists. It is tricky to figure out even what notification is being passed in these cases.
If you are not observing anything, then -removeObserver: does nothing, so it is not dangerous to call. There is a slight performance cost, especially for objects that are alloc’ed and dealloc’ed a lot, so there’s no reason to add it to objects that do nothing with notifications, but I recommend better safe than sorry in most cases.
This advice does not apply to KVO observations, which are a completely different animal. Read more…
When faced with the need to return “not found” for something that normally returns an index or other value that would normally be unsigned (whether this is an error condition or a normal event), Cocoa offers the NSNotFound constant as an alternative to returning an illegal index like -1 (which forces you to change the index to an NSInteger, raising the likelihood of sign-based errors if there’s ever a long promotion).
NSNotFound is 0x7fffffff, which is not -1 (0xffffffff), but is still very large (~2 billion) and so should never be a real index for any sanely-sized spaces, and is more readable than -1. NSNotFound is a good constant to remember when these issues come up. Look at NSString -rangeOfString: for an example of its usage.
I move between VS and XCode a bit without shuddering or fussing, which seems to make me a strange creature. In general, shocking as it is to say on a Cocoa list, VS is actually a much more powerful environment. Most who love XCode have little used VS (at least VS2005 or later, VS.NET is clunky IMO). But learning what actually is better about VS requires using XCode for quite some time. Most of the initial complaints are simply small differences between the two; many of which I prefer the XCode way. But then, XCode is a Mac app, and I generally prefer Mac UI.
Read more…