I have had the opportunity to do a lot of MacOS X development lately using Xcode and the entire Apple Cocoa framework. On the whole, I am impressed and have a great appreciation with what Apple has been able to achieve.
Objective-C is an excellent extension to C striking a good balance between introducing OO programming concepts without loosing the simplicity of raw C. I've many times criticized C++ for adding too much complexity to the task of programming to be useful in the embedded/real-time disciplines. I won't go into a rant of C++ here but rather direct you to a paper by Felix von Leitner which summarizes many problems with C++. And don't get me started on that cursed STL library!!
I'm still getting into the details of Objective-C so I won't say it has avoided all of the issues I see with C++. Time will tell on that front.
A criticism I do have is not with Objective-C, but with how Apple's Cocoa frameworks are using it. A new curse word for me is "late binding". After banging my head against the debugging brick wall with some MacOS X programs, I can say that I absolutely hate the late binding Apple does with their GUI frameworks. These things make testing near impossible. Late binding adds a dynamic aspect to running Cocoa programs making them operate much like interpreted languages. I cannot use interpreted languages for mission critical programming like network devices. They are way to difficult to QA and qualify. As such, I have concluded I can never use Cocoa frameworks in such projects. Objective-C, yes, that I can use, but Cocoa frameworks, no way.
Message to Apple: introducing even more runtime dynamic behaviours like garbage collection and the new Grand Central Station are going to make program more and more difficult to QA.

