I work on a lot of projects that share significant code between iPhone and Mac versions. This is the beauty of Cocoa. While working on these projects, I’ve bumped into this idiom many times:
#ifdef TARGET_OS_IPHONE
#import <uikit /UIKit.h>
#else
#import <cocoa /Cocoa.h>
#endif
This is almost never correct, and almost always means that someone imported Cocoa.h into a model class. Model classes should never rely on UIKit or Cocoa. They should just import Foundation.h.
There is one interesting exception that we’ve run into: NSImage versus UIImage. These are really model classes, but they’re part of AppKit and UIKit. They have very similar interfaces, so in most code you should be able to interchange them and keep everything portable. What to do?
Read more…
I keep coming across code like this:
newMonster.trueName = [NSString stringWithString:@"New Monster"];
It’s time to say stop it already with the extra +stringWithString:. I haven’t worked out yet where this anti-pattern comes from. Maybe it’s a misunderstanding of some sample code in Kochan? Maybe it’s a Java/.NET thing? I’m not sure. But I see it so often from so many places that it’s clearly something that needs discussing. (The rest of the linked article is good; it just gave me a good example of this issue.)
Read more…
Observing NSNotifications in a view control is a good thing. But remember, just because you’re not onscreen doesn’t mean that you’re not still observing. This is particularly noteworthy on iPhone, where your view can get dropped any time memory is tight and you’re offscreen, but it can bite you anywhere.
ViewControllers, WindowControllers and other UI controllers are often better off registering and uregistering for notifications when they are put on and off the screen rather than when they are allocated and deallocated. This often means that they will need to update their state when put on screen. For example, an icon indicating “connected” might be part of a StatusViewController. When StatusView comes on screen, StatusViewController should update the connected status and then begin observing changes on it. When StatusView goes off screen, StatusViewController should stop observing.
Read more…
Based on a post at StackOverflow. The question was whether Objective-C is only used for development on Mac OS/iPhone and why.
I think ObjC has been isolated to the Apple world through a quirk of history and the nature of proprietary systems.
Read more…
It thought I was going to be quiet for two weeks, now three posts in a day. There was a good question on Stack Overflow about getting system information. The actual question is “what does system_profiler actually do?” But it’s a good way to show how to begin to understand how any program works on the Mac. Here are some of the most basic tools of the trade. This is not a deep tutorial on reverse engineering. It’s a whirlwind tour of how you begin to attack programs using pretty standard tools. I’m not getting into any of the anti-obfuscation tools like Onyx the Black Cat or commercial tools like IDA Pro, or even code injection like SIMBL or F-ScriptAnywhere. When you think you’re going to hide how your program works, make sure you research those first. You’ll learn quickly how hard that really is. Maybe you should read my thoughts about Obfuscating Cocoa.
Read more…
We recently had a discussion on cocoa-students (the excellent list for Big Nerd Ranch alumni; yet another reason to go to BNR classes) about protecting Cocoa programs from reverse engineering, mostly around some anti-copying code. I had some thoughts on the subject since I happen to have a background in anti-counterfeiting.
Cocoa is a reverse-engineer’s dream. Spend some time at culater before dreaming you can really protect a Cocoa program. Objective-C is meant to be highly readable both in source and at run time. Obfuscation is not in its nature. This only points out Objective-C’s particular difficulties in this area; it is not to suggest C or C++ will save you. They’re just not quite as trivial as Objective-C.
That said, the world of obfuscation falls into three big camps: you can try to deal with 70% of your problem, 75% of your problem or 90% of your problem.
Read more…
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…
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…