The Cocoa-Carbon Advantage
September 7th, 2006I’ll let you in on a little secret. Well, it shouldn’t be a secret by now, but you’ll know I’m talking about you when I say that not everybody has gotten the memo yet. Don’t be embarrassed – today is the day you come into the light (not the “just died and moving on to a happier place” light, but close to it).
Cocoa is better than Carbon. And Carbon is better than Cocoa.
If you admit to me with a straight face that you know only one and refuse to venture into the other, I will immediately form the opinion that you are a bad programmer. A programmer I’d hate to be stuck in a MacGyver episode with. You couldn’t program your way out of a box. Or an NSRect. Or a RgnHandle. You sad, pathetic sack of unadaptable protoplasm. I loathe you. Actually, I love you. You make it easier for me to shine. If you don’t embrace and use every appropriate tool at your disposal on Mac OS X, well, you deserve to write crappy software! (And yes, in case anybody is wondering, I do think this means sometimes POSIX is better than Carbon, and Python is better than Cocoa, or Ruby is Cocoa — it all depends on what you’re trying to do).
The saddest thing in all of Macdom is the sight of Cocoa and Carbon purists crying in their mailing list beers because a given task is “impossible” in the API of their preference. Often a fearless API-hopper like Jim Correia or John Stiles will pop up and cheerfully announce a one-line solution to their woes. In the opposite API than the original poster had hoped, of course.
“Thanks for the response, but I’d like to keep this as pure as possible.”
Excuse me, I thought you wanted a solution. You idiot! What they really mean to say is “I learned this framework 10 years ago and I’ll be damned if I have to learn anything new now.” Yes, believe it or not, even Cocoa has idiots from 10 years ago who refuse to admit that there is value in Carbon. But by sheer force of numbers, the Carbon idiots are the sadder of the bunch.
Wake up people! It’s 2006. It doesn’t matter what you program in, it’s how you get the job done. Arguing about whether to use Carbon or Cocoa is like arguing about whether to use a net or a hook to catch a fish. You use whatever the circumstances call for. If you don’t, you die. (This, from the vegetarian, city-dwelling Mac programmer).
Why am I rambling on in this unusually caustic mood? Just a good excuse to get this off my chest and toss some code out that I’ve been meaning to share. It’s nothing special, but it will be good to seed google with it, and it is very well suited to the genre of code that can only be accomplished by a Carbon/Cocoa double-play.
Download NSImage+RSCarbonIcon (Free MIT License).
This simple category on NSImage lets you easily produce an NSImage based on a Carbon “Icon Manager” type code. You’ll find a long list of these type codes in Icons.h, beneath the kSystemIconsCreator enumeration. Generic folder? No problem. Computer icon (inaccurate, but hey)? No problem. All of these NSImage at your disposal, which would otherwise “be impossible.”
It’s also useful in that it demonstrates how to properly make use of Carbon IconFamily data in a mixed-endian world. Thanks to a little documented caveat, these structures must always be treated as big-endian. So even if you figured out how to use the Carbon Icon Manager by yourself, maybe you’ll find it useful that this code sample ensures endian-safety across both PowerPC and Intel platforms.
September 7th, 2006 at 5:14 pm
You have to admit though- Carbon windows suck more than Cocoa ones do :)
September 7th, 2006 at 5:58 pm
You have to admit though — Cocoa aliases suck more than Carbon ones do. Oh wait, I guess I can’t say that because Cocoa doesn’t support aliases.
September 7th, 2006 at 6:05 pm
David: a great example of a situation where somebody not afraid of Carbon presented a nearly perfect solution. I have used Chris Hanson’s BDAlias in almost every Cocoa project I’ve worked on.
And … it’s a great example of a stumbling block on which many *Cocoa* developers throw up their arms and say “i’ll just use a path!”
September 7th, 2006 at 6:20 pm
Well thanks for peeing on all us folks who only have a life with spare time enough to focus on the best of the Mac APIs — and may Cocoa continue to absorb the useful features of Carbon over time until all is eventually one. I completely understand the historic — and therefor business – reasons for Carbons existence, but please… You must have had such a bad hair day to write some of the above. My first comment and I’m already a troll – gee…
September 7th, 2006 at 7:17 pm
Daniel,
Thanks for the code snippet. (It is a good example of bridging the two API sets to come up with a generic solution to this problem.)
However, if you just want to retrieve an icon from the kSystemIconsCreator “family”, it is even simpler to get an NSImage representation:
[[NSWorkspace sharedWorkspace] iconForFileType: NSFileTypeForHFSTypeCode(kToolbarDeleteIcon)]
Enjoy,
Jim
September 7th, 2006 at 7:20 pm
Cocoa aliases do suck, and that’s why I use BDAlias as well. PTHotKeys is pretty nice too- but I do go down to the Carbon event handlers when I need too (I’m certainly not afraid of carbon! I use it all over the place!)
September 7th, 2006 at 7:22 pm
Daniel, I agree with the sentiment, but in this case I don’t think you need Carbon (except for the constant):
[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)]
September 7th, 2006 at 8:22 pm
Nice post, Daniel; the Carbon vs. Cocoa flamewars are indeed getting a bit tiring (esp. the FTFF threads that assume Cocoa is the only requirement for a fixed Finder). Incidentally, Amnesty requires the Carbon framework for defining global hot keys via RegisterEventHotKey(). But if anyone knows a Cocoa way of doing it, let me know. ;-)
September 7th, 2006 at 9:42 pm
Gary: sorry if you feel “peed on.” It’s true I wrote this entry with a little venom, because I’m trying to make a point that people on both “sides” don’t seem very receptive to. Take it or leave it, I suppose.
Jim & Michael (and Gus in chat): Whoah! Thanks, that does seem to work, much to my surprise. I wouldn’t have expected it, since I wouldn’t assume “Icon Manager Types” to be the same as “HFS Type Codes.” But I guess somebody was smart and prevented much (if any?) overlap in those namespaces. (Probably thanks to Dave Lyons). I’m curious if anybody can find a type code from Icons.h that returns a different result from my category method than from the NSWorkspace method. In my tests “it just works,” which is probably all that matters for most types you might be interested in.
So damn! There goes my credibility. Trying to demonstrate the importance of Carbon and … I picked the wrong example. Oh well. That’s what blogs are for, right? Now I can rip that useless code out of my private framework.
Danny: as far as I know, you’re still stuck with Carbon for hotkey support :)
September 7th, 2006 at 11:04 pm
Couldn’t agree more. I am a long-time Carbon guy and even though our UI has moved to Cocoa, we have a big C++ codebase underneath, with lots of Carbon goodness where it’s still the best tool for the job. It’s frustrating to listen to Cocoa programmers who don’t have a healthy respect for what came from classic Mac OS. Actually worse than that is that we even call some people “Cocoa programmers” — we all write Mac software here.
September 7th, 2006 at 11:38 pm
Yes, believe it or not, even Cocoa has idiots from 10 years ago who refuse to admit that there is value in Carbon. But by sheer force of numbers, the Carbon idiots are the sadder of the bunch.
In my experience, Cocoa developers are far more likely to complain about having to use Carbon than the other way round.
The imagined lack of “purity” in using Carbon is a regular topic on cocoa-dev – the corresponding discussion on carbon-dev is more likely to be about the wisdom of expressing system APIs in Obj-C… :-)
It doesn”™t matter what you program in, it”™s how you get the job done.
Absolutely. However, we recently released a large application written in Carbon and have had to put up with self-appointed experts complaining about our choice of development framework online (as well as individuals who took the time out of their day to send in abusive emails).
I find it astounding that Cocoa has had this effect on people, given that it’s simply an application framework (IMO, one whose strenths are overrated: it took until 10.3 to be able to programatically hide views, and we’re almost at 10.5 yet you still can’t overlap sibling views?).
Many of the people who dismiss Carbon have never looked seriously at modern Carbon development – it’s considered “too hard”, and their mental picture of Carbon is stuck circa Mac OS 9. Sadly Apple went out of their way, for pretty bogus political reasons, to reinforce this idea early in Mac OS X’s life.
This has produced a culture where it’s cool to diss Carbon (case in point, you write “you’re still stuck with Carbon” as if it’s something to be avoided… ;-), even though some of us actually prefer programming with HIToolbox (gasp!).
September 8th, 2006 at 1:23 am
Thanks for writing this. I completely agree.
I have a personal threshold against including Carbon in every project, but (at least it’s what I tell myself) it’s purely for performance. If I have to use just one Carbon function, I’m going to look thrice if there isn’t a Cocoa way to do it first. After this initial hump, I have no qualms whatsoever.
But mixing Cocoa and Carbon isn’t just okay, it’s what should be done. It gets the job done. We have 17 years of “old Mac OS” that only used what would turn into Carbon and 9 years of NeXT and the precursor to Cocoa. We still have a Cocoa/Carbon split inside Apple, making it fairly impossible for feature parity any year now. If you *have* to include a framework to get the functionality you want, do so. Mixing in dogma isn’t gonna make your app better. (Are you reading, Andrew Stone?)
September 8th, 2006 at 1:32 am
I don’t think the anti-Carbon bias is totally baseless. It’s often a lot harder to program than Cocoa. The CF-style stuff is completely reasonable (which some Apple folks refer to as Carbon), but until QTKit, for example, QuickTime was some pretty rough stuff.
September 8th, 2006 at 2:07 am
Jesper’s comment implying that adding Carbon to a Cocoa project affects performance isn’t quite right. ‘otool -L’ will show you that the AppKit framework directly pulls in HIToolbox, and in fact I think just about everything in the Carbon umbrella framework gets loaded into a simple AppKit app. But that actually doesn’t have any measurable impact on performance anyway, thanks to the system shared region (which makes pulling in standard system frameworks essentially free aside from the rare library initializers and small amount of framework data which gets written on in each process).
In other words, there’s no performance impact to using Carbon code in an otherwise Cocoa application.
September 8th, 2006 at 3:03 am
Don’t stop at learning Carbon, Cocoa, Ruby, Java, C#, et al. There’s LISP, too! http://www.paulgraham.com/avg.html. Why stop learning?
At some point, of course, one needs to just stop, get the current job done and put off learning something new until you have a ‘mo. Maybe this is an opportunity for you (or anyone) to write a book “Carbon for Cocoaheads” and the flip-flop book in the same binding/Website “Cocoa for Carbonjunkies.” Seriously. Unearth those gems the other half has been missing.
September 8th, 2006 at 4:34 am
If you want performance, BDAlias is not the way to go. Creating aliases is slow. It’s far better to use FSRefs everywhere (especially since paths suck) and then just get the alias data when you need to actually store the alias reference somewhere. When working with files, just keep the FSRefs around until you need to be persistent. And since 10.4, FSRefs are valid across processes.
September 8th, 2006 at 5:29 am
A developer: You caught me! I’m definintely biased towards Cocoa. This after using (and developing parts of) Carbon for years. So it’s not a one-sided view, at least. But I can appreciate that the HIToolbox approach is more of a natural fit for some developers. My biggest complaint about “Carbon Only” Apps is that they have a tendency to veer towards an appearance that is no longer “up to date” with Mac OS X. This can all be overcome by a thoughtful developer, but …
Scott: segue from above … I agree that Cocoa makes a lot of things easier. Namely “fitting in with the times.” Adopting anything that Apple has currently blessed as the way to do things is almost always easier on Cocoa than in Carbon. Conversely, filling in the gaps – the finishing “has to do this” details – is often easier in Carbon, because it has historically been more forthcoming of sharing low-level access with the developer.
Eric & Jesper – I just wanted to concur with Eric that there is no performance hit by including Carbon. There can’t be since big chunks of Cocoa these days is implemented in Carbon. So that code is going to not only be mapped, but be initialized, whether you directly link to it or not. That said, I can appreciate the desire to avoid “polluting” your link table with libraries you don’t actually need.
Bob: Would love to learn LISP! Well, I guess I sort of did in school (Scheme). But I was so much older then…
Rosyna: You’re assuming that we would use BDAlias as a wrapper for all files. It’s just a convenient way to get an Alias when it’s appropriate, usually at persistence-time. For fleeting references, I agree that FSRef is the way to go (and BDAlias has an aliasWithFSRef convenience method). The main thing BDAlias lacks is it doesn’t cover the breadth of alias-creation options provided by Carbon, but it’s a good start.
September 8th, 2006 at 5:51 am
Personally, I think all of NSFileManager and NSWorkspace as it exists now should have the hell deprecated out of it. Anything that uses file paths. And a new happy thing that uses FSRefs internally and treats files as objects were created in its stead. File paths are evil and should never, ever be used in any case whatsoever. (Relative paths are ok, in limited amounts, of course).
September 8th, 2006 at 5:53 am
I have to admit that my first reaction to this piece was to wonder what got you so fired up :) Coming to the Mac when OS X was released from around 6 years of enterprise Java I went to Cocoa first. Carbon seemed to be old school and Cocoa the future. Cocoa was also similar enough to the Java APIs that I could usually find what I needed pretty fast and I was regularly amazed that things I would go looking for were there just waiting for me in such a seemingly small API. Over the years though and particularly recently I’ve had to delve into Carbon because Cocoa simply had no avenue for me to achieve my goals. I think it is a much more daunting API, particularly when you find 3 functions with almost the same names and one or two of them are lightly documented. I do sometimes wish that we’d see more in Cocoa but honestly I’d be happy to get access to some of the UI stuff Apple uses regardless of what framework they provide it in. I read a book in 2000 called The Pragmatic Programmer that you might find interesting. I don’t believe it has been revised so I don’t know how relevant it will be now but at the time it helped me to take better advantage of all that was available to me.
September 8th, 2006 at 6:11 am
If you actually think about the example you give, you’ve basically supported the idea that Cocoa is the better API. Just because you use the C calls doesn’t make Carbon particularly attractive; that you CAN and DID wrap them in Cocoa is evidence against your neutrality. After all, if the Carbon API were so great, why wouldn’t you call it directly every time you wanted to use the functionality? As a core C library Carbon does offer a lot, but in use as a high-level API it leaves much to be desired.
September 8th, 2006 at 7:13 am
Ok, what Carbon book would you recommend? Or, unlike Cocoa, is the Apple documentation sufficient?
September 8th, 2006 at 7:29 am
Stephan: regarding the Pragmatic Programmer – have a look at the very first blog posting here. Yes, reading that book motivated me to start this blog! I highly recommend it.
Not Required: the fact that I wrapped them in Objective-C was because doing so was idiomatically appropriate to the project I was working on. If I had been working in C++ then they would have been wrapped in C++. The adaptability of one to the other is not the definition of “betterness.” I agree it’s less common that “bits and pieces” from Cocoa are suitable to wrapping in straight C for a Carbon app, but a good example from the Carbon side is being willing to drop complete pieces of Cocoa-based functionality into an otherwise entirely Carbon app. In this case, it often makese sense to wrap that functionality in a straight C or C++ interface. Again, so that it doesn’t clash idiomatically with the prevailing style of the source base.
sengan: I honestly don’t know how I would commence with learning Carbon from scratch, if I was inspired to do so today. But it’s not as important to “learn Carbon” as it is to be open to learning it on a case-by-case basis. The problem I’m annoyed with is developers drawing an artificial line between the APIs and refusing to cross it. You’ll be 99% of the way there if you just answer “Thanks!” when somebody offers you a Carbon solution, instead of insisting that you “are looking for a native solution.”
September 8th, 2006 at 8:29 am
I’ve updated the entry with some more info about the disparities between NSWorkspace’s icon fetcher and the GetIconRef call that I wrapped in my example category.
September 8th, 2006 at 8:50 am
I think the main point of all this is that there is functionality that’s only accessible from one or the other. While you can moan about this discrepancy (and it can be a pain converting certain data types back and forth), in the end, you should be willing to delve into the other to provide what’s best for your audience.
Lately, I’ve done my share of Carbon for dealing with file stuff. Sure things would have been easier under a more consolidated API but at some point you have to accept the reality of the situation. In the end, the users want a good experience so you have to do what is necessary to provide that (and the choice of when to use Carbon or Cocoa should take that into account).
And btw, my bias is heavily towards Cocoa, being a NeXTSTEP programmer from back in the early 90’s. Just to allay any suspicions that I’m a Carbon schill.
September 8th, 2006 at 9:17 am
>The adaptability of one to the other is not the definition of “betterness.”
Yes, it *precisely* is, and you hint at the fact yourself (though you clearly don’t realize it) when you lament about “unadaptable protoplasm”. It is not unrelated to Turing completeness in that we are discussing the expressive power of a particular API. While there are unquestionably some things that Apple has only provided a Carbon API for, for anything that has a Cocoa bridge you will find (and indeed have demonstrated) it is (or can be made) more expressive to a truly “adaptable” developer. And, yes, while a wrapper makes code fit more easily into a project, the very fact that you would have to do the same wrapping *even in C* to get/resuse the expressive ability points to how inadequate the Carbon API itself is to a developer in *any* language. My point stands.
September 8th, 2006 at 9:42 am
To everyone who thought I didn’t know that Cocoa is largely implemented in or wraps Carbon: yes, I did know that Cocoa is largely implemented in and wraps Carbon. :) It’s the psychological effect of keeping as few frameworks as possible explicitly linked in that’s precious to me in these cases.
September 8th, 2006 at 10:00 am
There is a lot of value in keeping things “pure.” The value is mainly in ease of maintenance. I agree that it’s foolishness for ignoring useful tools to get the job done, but it can be equally foolish to add more complexity to the job of maintaining a codebase just because its easier to accomplish task X in Cocoa versus writing it in Carbon.
What I’ll never understand is why Carbon and Cocoa are so easy to differentiate. I’m referring to products written with Cocoa versus products written with Carbon. To and end-user there should be no difference, yet for years now there has been significant differences between the two. Behavior of buttons, how windows react, interoperability with other services, etc. these all perhaps needlessly harm the user experience.
September 8th, 2006 at 10:14 am
Not Required, all you seem to be saying with all this “expressive” business is that Carbon is generally a more lower-level API. Well, of course it is. But it’s also powerful, and the only point here is that if someone has to dip into Carbon, they should just do it and stop complaining. The fact that it needs to be wrapped in Objective-C or C++ isn’t really relevant. Carbon is not the same kind of application framework that Cocoa is. That’s why the Mac has had a long history of good C++ frameworks, from Think Class Library, MacApp, and PowerPlant to modern ones that wrap up all of HIToolbox and Carbon Events.
No one will argue that Cocoa is the best way to build new apps from a stock Xcode install, but that doesn’t necessarily translate to one framework being overall better than another. As has already been pointed out, Cocoa continues to have a bunch of missing functionality and more than a few poor design choices.
September 8th, 2006 at 10:23 am
It is never a good idea to take tools out of your tool box. Carbon is certainly a valuable tool.
I think some misperception has arisen about comments that programmers make expressing a preference for one API or another. There is a difference between aesthetic judgments such as preference for chocolate or vanilla and a technical judgment. I suspect that many programmers including myself vocalize aesthetic judgments that are misinterpreted by others as technical judgments. For example, I think the procedural QuickTime API is about the ugliest API ever created (an aesthetic judgment), but I use it all the time anyway because it has great technical capability. I have barely used Carbon directly because when I write cross platform code I use other frameworks, and when I write Mac only software I use Cocoa (with the probably fruitless hope that one day Gnustep will make that code substantially cross-platform too) and deliberately stick to the Cocoa plus Posix plus OpenGL world that has a chance of working via Gun step.
September 8th, 2006 at 10:40 am
The whole argument here is OO vs Procedural. That battle was fought way back in 1988. If you are coding a device driver, or something like that, go for it. Anything else, you are a nut, you need to move on and start doing OO (Cocoa/Objective Cee). Ah yes, if you don’t have the “Cocoa” equivalent. Write classes/categories and wrap that arcane API into something that is easy to read, write, and maintain.
BWT a neat observation is that developers that use Cocoa:
1) Are more productive
2) Have more apps
3) Their apps do more
4) The apps integrate better
5) And are written faster
As to should you pollute your code with Carbon APIs. Dude they are APIs. You either need to make the call or not. Now if you have a choice, you better have a really good reason not to use the Foundation/Cocoa version. If the function is not there, you also should probably adding some nice Objective C category or wrapping the code in an Objective Cee wrapper.
September 8th, 2006 at 10:41 am
One of the problem of using Carbon when you don’t know it is you always have that doubt that you might be doing something wrong because you don’t know the whole framework and the concepts.YouI end up copying example codes, scared to modify anything, and looking at it like a black box, hoping it is not filled with dynamite, crossing your fingers when hitting the Run button.
September 8th, 2006 at 12:43 pm
charles: Which is probably exactly how those who primarily use Carbon feel when they have to reach into Cocoa, especially with Objective-C and all.
Beyond learning a handful more basic C programming practices that Cocoa doesn’t require you to know, I have had no trouble calling into Carbon at all to do “menial work” (but I wasn’t juggling Carbon windows next to Cocoa windows, who really are also Carbon windows, but I digress). QuickTime, oh, that monster of an API, is another thing entirely, but it also suffers from horrible documentation.
September 8th, 2006 at 4:08 pm
I think the usual fault of this sort of Cocoa vs. Carbon discussion is that it fails to differentiate between Carbon as an application model and Carbon as a bunch of procedural frameworks.
I’ve written Classic apps since 1984 but I never seriously tried to write a Carbon app in the sense of using the Carbon application model, events and HIViews. Granted I have the advantage of not doing any legacy or crossplatform stuff, but the discussions of the fine points of those things on carbon-dev are daunting. And you still need extra work to use Cocoa UI and methods, I hear.
On the other hand, writing a Cocoa-based app makes the basic stuff extremely easy and you’re free to use any Core Foundation, Carbon manager or BSD API whenever necessary – whatever works best in that case. I tend to avoid NSWorkspace and NSFileManager except for the exact simple tasks they’re used for in the sample code.
Wrapping File Manager calls (for instance) inside ObjC classes may be elegant and good as an exercise perhaps, but unless you’re going to publish that code or reuse it a framework or library, it’s probably overkill; a simple C function may be better.
Daniel, regarding your Carbon icon sample, I coincidentally wrote something similar a few months ago, but also in a more generic way, to get icons for files (instead of calling NSWorkspace’s iconForFile:). Turns out there’s a subtle QuickDraw bug on Intel Macs if you use an IconFamilyHandle for composited icons; see this and this. It’s fixed in Leopard. It probably won’t affect the icons you get from GetIconRef() as there’d be no compositing.
September 8th, 2006 at 4:29 pm
Amen and hallelujah!
The vast majority of Mac Office is still Carbon-based, but many many of our internal tools are Cocoa, and we’re doing more and more shipping bits in Cocoa where it Just Makes Sense(TM) to do so.
September 8th, 2006 at 5:25 pm
I don’t know which group of people original poster is talking about but as a graphic designer myself, one reason why I prefer Cocoa over Carbon is simply because of UI. Cocoa apps almost always come with all goodies by default while Carbon apps will have to add them manually. While that is easily fixable, some of the UI elements’ behavior are not unless you implement ugly code hacks. It’s too much works to get your Carbon apps to feel and look like Cocoa apps.
Personally I don’t care if app is developed in Carbon or Cocoa language as long as UI is Cocoa, I just can’t stand the inconsistencies between Carbon and Cocoa UI. I don’t blame Carbon developers for the ugliness of their Carbon apps, I blame Apple for not paying attention to Carbon UI behavior/look.
September 8th, 2006 at 5:25 pm
100% agreed.
People need to release that the carbonKit framework is already precompiled and doesnt take anylong to link against and run with than AppKit or Cocoa.
Personally, i think Carbon’s File system manager is more reliable and stable than cocoa’s NSFileManager. Not to mention their are many features that Carbon has that cocoa doesn’t, and vise-versa.
September 8th, 2006 at 5:44 pm
I personally try to stick with Cocoa but this is because I don’t know much Carbon and I’m reluctant to learn it until I need to use it. That said there have been times that I have used Carbon simply because it is the better solution. Cocoa is a very nice framework but it doesn’t do everything (the first thing that springs to mind for me is using the keychain) and that’s when Carbon comes in useful.
September 8th, 2006 at 9:37 pm
I am sorry, but in 2006 language, frameworks and others technicals stuff MATTERS
sometimes one tool is better than an other and it’s IMPORTANT you know that if you are professional.
about cocoa vs carbon, on come on people , how many years do you will live in os 7-9 ? you C++ based code if it is efficient and already ready and don’t make huge debate of these.
some people still maintain cobol and fortran code and don’t make a fuss because of Python or ruby or C#.
September 9th, 2006 at 6:37 am
If you are at all interested in your app being cross-platform stick with Cocoa as much as you can.
I think people are allowed to bitch about whether one API is fun to use or not, or is better than another, at the end of the day we are still stuck with a closed one vendor API so we just have to suck up and deal with it. The Cocoa programmer perhaps has more time to complain.
Carbon has that cool retro thing going on, like Win32. RgnHandle? Wow, bad flashbacks, I thought they took QuickDraw out and shot it? Carbon is one thing, but publicly deprecated API’s are another.
September 9th, 2006 at 1:13 pm
I agree that Cocoa makes a lot of things easier. Namely “fitting in with the times.”
I agree, but what I mean is that API and language is designed to be easy and do the right thing by default. The gap is about to widen significantly with Objective-C 2.0.
It’s true some things are only implemented in Carbon, but that’s beside the point of which framework is better. It just means that Carbon is the only key that fits some locks. Design-wise, Cocoa absolutely smashes Carbon to bits. Imagine trying to write Motion or Aperture from scratch in Carbon. Yikes. Though trying to write either without any Carbon would be no picnic either.
September 9th, 2006 at 1:14 pm
cjwl: surely if you are interested in your app being cross-platform you would use Carbon? Last time I checked all the big cross platform applications with shared code bases used main Carbon (granted this is also a side effect of many of these applications dating back to the 80s/early 90s).
September 9th, 2006 at 6:55 pm
For what it’s worth, as a user, I completely believe in the apparent myth that Cocoa is better than Carbon. I simply can’t think of a Carbon app that feels totally smooth and fast and attractive as a good Cocoa one (even Finder has all these antiquated bits in it that make it feel like it’s based on old code.) And then there are things like all the system extensions you can use that only work with Cocoa apps, or the apparent speed it took for Cocoa apps to move to Intel compared to Carbon. Which makes me hesitant to believe they’re no better than each other.
Maybe it’s _possible_ to make an app that feels as good as a nice and clean Cocoa app with Carbon, but people who make small, good little apps (and big good ones, too, like Pages\Keynote!) always pick Cocoa so I never get to see. Carbon just makes me think of ugly stuff like Quicktime 6, Photoshop and BBEdit. Cocoa makes me think “proper modern OS X app” and it seems to be backed up by what I can observe. Just saying.
September 9th, 2006 at 7:51 pm
I think NSWorkspace is looking up the preferred application for that type (probably using Launch Services), then getting the icon from Icon Services for that type and that creator (the one of the preferred application). I suspect that if you did the same thing, you would get the same results from Icon Services as from NSWorkspace, and vice versa.
September 10th, 2006 at 12:22 am
To those people who don’t believe Carbon applications can look and feel like Cocoa applications: Check out the Nano framework, which is “pure” Carbon:
http://www.refnum.com/products/nano/
Take a look at the example applications. I’m sure almost every Mac user would assume they were Cocoa.
September 10th, 2006 at 1:17 am
Scott Stevenson, and notice how slow Aperture is, especially the 1.0?
The NSWorkspace method is getting the icon for the file that has a create code of ‘????’ (ie, any) and the file type you give it. Your GetIconRef is getting the icons with a creator of kSystemIconsCreator (‘macs’), which is a very, very specific domain/application. If you passed ‘????’ to the GetIconRef() function, you’d get the same result. Although you really should use GetIconRefFromTypeInfo(), which is *exactly* what NSWorkspace’s iconForFileType: is doing. However, try drawing the image returned from iconForFileType: in any size than 32×32.
September 10th, 2006 at 9:44 am
[…] When I saw this post, I mentioned to Daniel Jalkut that I had done the same thing that he did (which was to create an NSImage category to access Carbon’s Icon Manager’s icons). After his obligatory insistence that I start a blog, I sent him a little program I had thrown together to preview the icons. […]
September 10th, 2006 at 2:42 pm
In some (non-gui) apps the Carbon framework can come in handy for specific tasks ( cf. How to detect string encoding? on http://www.macosxguru.net/article.php?story=20030808081801868 ).
September 10th, 2006 at 8:09 pm
Daniel: I, too, have Carbon icon code in some of my Cocoa apps. I think there is a point being overlooked in the discussion of NSWorkspace vs GetIconRef. IconServices was designed (partly) to minimize memory usage: for each icon on the system, there should be one and only one instance of pixel data/cache in memory, and all applications should render the icon from that same instance data via PlotIconRef.
So, try this:
Call [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(‘prof’)]; three times in the same function, logging the result with NSLog(“%@”) after each.
Call GetIconRef and printf(“%08lX”) the resulting iconRef three times.
Notice the difference? (Aside from the much richer description returned by NSLog…)
This is a much bigger problem with file-specific icons retrieved through NSWorkspace, where you might invoke iconForFile: way too often if you aren’t aware of the problem. You can cache the generic icon (still once per app rather than once per system, though). File-specific icons, not so much.
Rosyna: What does Cocoa have to do with Aperture’s slowness, especially in the 1.0? Unless they ported it to Carbon in 1.1, I find it unlikely that you can pin that on Cocoa. But if you can really trace Aperture’s performance issues to indiscriminate use of Cocoa rather than Carbon, I and others would certainly like to see the analysis.
September 12th, 2006 at 5:35 am
Cocoa is excellent for interfaces, but sadly it lacks a lot of things that can be found in carbon. I prefer cocoa, but I’m not afraid to use carbon where cocoa falls short.
September 19th, 2006 at 11:12 am
Alas, there are two issues with using Cocoa intermixed with Carbon that have a deleterious effect on performance.
(1) Loading of extra libraries at launch (not a terribly big deal)
(2) You cannot unload Cocoa-based bundles as the Objective-C runtime cannot guarantee that all objects lifetimes are terminated.
That said, the post and the comments are spot on.
September 26th, 2006 at 9:38 pm
Sadly this demonstrates why one must prefer one part of OS X over the other: Carbon is out of sync from Cocoa (and vice versa).
The icon returned should be exactly the same, but NSWorkspace is apparently doing some voo-doo to get the *most current* preferred icons. ThIs implies that NSWorkspace is designed to go and get a different icon than what is actually defined in the bowels of OS X.
This preferential treatment of Cocoa is what really irks (some) old-school Carbon developers. Apple engineers are intentionally making Carbon appear antiquated or “broken” compared to Cocoa, even though Carbon is technically capable of regurgitating the correct, modern, icon.
Another area where Carbon is deliberately hindered vs. Cocoa is in the “grow thumb” in Carbon windows, which appears as a solid-white background square instead of transparent as in Cocoa-derived windows. Carbon can make the grow thumb appear identical to Cocoa windows, it is simply not the default appearance for no technical reason whatsoever (just political ones, methinks, but what do I know).
September 27th, 2006 at 10:30 am
I’d suggest not ascribing to politics what can more easily be explained by there being more important things to fix.
September 27th, 2006 at 10:34 am
Agree with Eric, especially considering that there are behaviors that are better in Carbon than in Cocoa. So it goes both ways. And if Apple didn’t want to support Carbon, they would have made that a lot clearer than just a few UI glitches. Remember Classic?