It was written by Dr. Chris Hanson, a Chris Hanson who's evidently still in the mid-South. Maybe the next time I get a chance to visit
This talk is a combination of an introduction to Cocoa, as well as a series of advanced tips and tricks that even relatively experienced Mac programmers may not know about.Joel Norvell will also be presenting on how to edit PDF forms using Cocoa — he's done a lot of work with PDFKit and Cocoa, and I'm looking forward to learning from him.
The idea here is that we want to give all of the people who are new to Mac and iPhone development a chance to get started, but we also want to do something special for our advanced programmers. So rather than choosing one, we're just going to go ahead and do both.
clang very easily and in five to ten minutes.[~]% cd /Projects
[/Projects]% mkdir LLVM
[/Projects]% cd LLVM
[/Projects/LLVM]%
Then check out LLVM itself and clang from the LLVM Subversion repository. [/Projects/LLVM]% svn checkout http://llvm.org/svn/llvm-project/llvm/trunk llvm
[/Projects/LLVM]% cd llvm/tools
[/Projects/LLVM/llvm/tools]% svn checkout http://llvm.org/svn/llvm-project/cfe/trunk clang
[/Projects/LLVM/llvm/tools]% cd ../..
[/Projects/LLVM]%
Then edit the PARALLEL_DIRS definition in llvm/tools/Makefile to tell it about clang. Just add clang onto the end, like this: PARALLEL_DIRS := llvm-config \
opt llvm-as llvm-dis \
llc llvm-ranlib llvm-ar llvm-nm \
llvm-ld llvm-prof llvm-link \
lli gccas gccld llvm-extract llvm-db \
bugpoint llvm-bcanalyzer llvm-stub llvmc2 \
clang Now create a directory to build into, next to your llvm directory, and change into it. [/Projects/LLVM]% mkdir build
[/Projects/LLVM]% cd build
[/Projects/LLVM/build]%
This is where you'll actually run configure. This will ensure your source tree isn't polluted with build products, and that everything stays self-contained while you hack. [/Projects/LLVM/build]% ../llvm/configure --enable-targets=host-only
# lots of logging
[/Projects/LLVM/build]%
You'll note that above I passed an argument to configure. This ensures that LLVM is only built to target the architecture I'm running on, to speed up the build process; this is generally fine for simple front-end development.clang all I have to do is invoke make. LLVM is set up to correctly do parallel builds, so I'll pass the number of CPUs I have in my machine via make -j 4. [/Projects/LLVM/build]% make -j 4
# lots of logging
[/Projects/LLVM/build]%
That's it! LLVM is now (hopefully) successfully built. All of the pieces are in the build directory under Debug/bin and Debug/lib and so on; see the LLVM web site for details about what the various components are.NSHumanReadableCopyright of its Info.plist file. This should generally be of the form Copyright © «YEARS» «HOLDERS». All rights reserved.where «YEARS» represents the individual year, set of years, or range of years during which the application was authored and «HOLDERS» represent the authors of the application.
Copyright © 2007–2008 Chris Hanson. All rights reserved.in the
NSHumanReadableCopyright key of its Info.plist file. (Yes, that's an en-dash between the years, option-hyphen gets you one.) It wouldn't have the year at the end, or random commas after things, or random abbreviations. Just one simple statement.Copyright © 2002–2008 Chris Hanson. All rights reserved.to the bottom of my weblog, too. Hopefully in such a way that I can actually update it easily when the year rolls over…
launchd was pretty cool. But what’s so great about it?launchd is what makes it easy to get tasks launched on-demand on Mac OS X 10.4 and later. It obviates lots of different archaic Unix infrastructure — init.d, cron, inetd — in favor of a single self-consistent and easy to use mechanism. Dave Zarzycki’s post Where to begin? describes the launchd design philosophy in some depth.launchd. There’s no careful balancing of init.d or SystemStarter scripts on modern releases of the operating system. Instead, launchd jobs have property list entries in the LaunchAgents and LaunchDaemons directories in the system and local domains. Some specify that launchd should keep them alive indefinitely, others simply provide conditions under which they should be launched.finger service; it doesn’t run all the time, nor does it rely upon a separate “network service daemon” to launch. Similarly, the Bluetooth daemon is only run only when a particular Mach port is connected to; it doesn’t need to be running all the time, and a framework interacting with it can easily just connect to it and start using it, without worrying about the mechanics of launching it, ensuring only one instance is running, and so on.launchd really shines is in the level of integration it lets developers offer between frameworks and daemons or agents when it comes to managing shared state./Library/Frameworks. Then you can install a property list describing when launchd should launch the daemon, and in what type of environment to launch it. Since everything is going to be local to a single machine, you can use a Unix-domain socket — which, if you don’t already know, is represented via a path in the filesystem — by describing it in the Sockets key in the property list. That way, any time the framework wants to communicate with the daemon, it can just connect to the socket at that path and it will have a channel.SecureSocketWithKey option to have launchd generate the path for you, and pass it to all processes via the specified environment variable. See the ssh-agent property list for an example; it's how ssh-agent is launched on-demand in Leopard.)oneway, bycopy, byref and so on as appropriate to keep communication efficient. The daemon can even distinguish between clients by keeping track of which socket it’s accepted their connection on.launchd is what’s actually listening on it? There’s a process that the daemon needs to go through when it first starts up called launchd check-in. This process lets launchd pass the daemon information from the property list that was used to start the daemon. You just have to use the launch_msg() API described in <launch.h> to send a LAUNCH_KEY_CHECKIN string: - (void)checkInWithLaunchd {
launch_data_t checkinRequest = launch_data_new_string(LAUNCH_KEY_CHECKIN);
launch_data_t checkinResponse = launch_msg(checkinRequest);
switch (launch_data_get_type(checkinResponse)) {
// launchd will return an errno if an error occurs
case LAUNCH_DATA_ERRNO: {
int error = launch_data_get_errno(checkinResponse);
// handle it
}
break;
// launchd will return your job's dictionary for successful checkin
case LAUNCH_DATA_DICTIONARY: {
// The dictionary isn't an exact copy of your plist.
// It has file descriptors substituted for socket descriptions,
// Mach ports substituted for Mach port descriptions, and so on.
}
break;
// launchd returned some other bad response
default: {
// handle it
}
break;
}
launch_data_free(checkinRequest);
launch_data_free(checkinResponse);
} The trick is that the dictionary given back by launchd upon check-in is not simply a literal copy of what’s specified in the job’s property list! Instead, where you had specified in the property list how you wanted launchd to listen on a socket, upon check-in launchd will actually pass the socket itself as a file descriptor. You can retrieve it easily using the launch_data_get_fd() function, accept the connection (on another socket), and continue listening.launchd in your own designs, see the launchd(8) and launchd.plist(5) manual pages, as well as Tech Note TN2083: Daemons and Agents and the System Startup Programming Topics guide. There’s an example daemon called SampleD which illustrates how launchd check-in works, and of course you can browse the source code to launchd — it’s under the Apache License, Version 2.0 — at the launchd site on Mac OS forge. Here is a complete 104-line native code compiler for a tiny subset of OCaml that is expressive enough to compile an external Fibonacci program: [...] The compiler is itself written in OCaml, of course; for those who don't know, OCaml or Objective Caml is an object-oriented dialect of Standard ML, a #nscodernight on FreeNode.#nscodernight on FreeNode.#nscodernight on FreeNode.#nscodernight on FreeNode. (And also consider joining some of the other channels there, such as #macdev and #macsb, where you can meet other fellow Mac developers!)