Major pieces of the Cocoa frameworks are difficult (not impossible, of course) in less dynamic languages. Key-value coding (which makes use of dynamic dispatch and runtime class and hierarchy modification) are very hard to do in compile-time bound (method-calling) languages. Core Data's synthesis of attribute getters/setters is a similar example of Objective-C's dynamic messaging (and dynamic runtime) making things much easier.
As an example, Apple's Cocoa-Java bridge (which was written by some very smart folks) was deprecated right about the time Key-Value coding and observing were introduced as major patterns in the Cocoa MVC stack. Making the Java runtime play nicely with those new features was deemed too difficult to pull off in a reasonable effort.
Finally, Objective-C's dynamic messaging was designed specifically to solve the dependency problem in large projects. Whereas a compile-time bound language like C++ requires that dependent modules be recompiled together, Objective-C's runtime-bound messaging means that you don't always have to re-compile everything. At the time of NeXT's decision to use Objective-C over (the, at the time, immature C++), that was a major factor in developer sanity. It still makes large systems easier to manage (though, again, it's certainly not impossible in C++ or Java or ..., just much harder).