Lee --
You've proven time and again you're damn smarter than I am. And I've seen you give this same advice before -- I've followed it -- but I started Kochan's book the other day and he makes the case AGAINST learning C before Objective-C. C is procedural, he says, which can lead to bad habits when a novice turns to an object-oriented language (I'm paraphrasing and condensing; see the introduction to his book).
Just wanted to throw this out there.
mt
This is simply a matter of perspective, and one's ultimate goal would greatly sway which direction is best. I consider versatility one of the cornerstones of a good programmer. I think starting with a strong foundation in C (and command line tools) allows greater versatility. My concern with someone starting out, is they'll learn Objective-C using XCode, then find themselves in a situation where they have a shell account on a linux or UNIX system, and they then feel that they have to start from scratch as a great deal of their programming knowledge does not transfer. Yes, they may be able to use Objective-C, but they won't have all of the libraries they are used to, the IDE they're used to, they won't know the command line arguments to gcc, or how to invoke gdb from the command line, etc.
If one's goal is to only program for OS X on OS X, and they are confident that they will always be able to do things the Objective-C/Cocoa way (instead of say, using function pointers, or system calls like memcpy, the "C" way) then I'm sure a cursory understanding of C is sufficient to be an effective Objective-C programmer. That's simply not my approach to programming, and I think if one is serious about being a programmer, a working knowledge of C is crucial.
In terms of the "Object-Oriented mindset", i did mention:
... but you will have to wrap your head around objects and the Objective-C object model.
I think moving from procedural programming to object-oriented programming is a bit easier than the other way around. I see object-orientation as an extension of procedural programming, not a totally different paradigm like functional programming. This may be considered faux pas by hardcore academics, but truly in most cases an Object is a bundle of methods and data. You can easily bundle data with structs in C, and you can name methods in a manner that they are bundled in C. When you get to more interesting things like polymorphism, inheritance, etc. OOP really opens up some options that a strictly procedural language is not well suited to.
Obviously Kochan is doing better than I am in terms of educating programmers, being that he is a published author. However, I wouldn't say that his advice is in direct opposition to my own. I think that at the surface I agree that one doesn't need to know C to learn Objective-C. My point is that for some, the ultimate goal isn't to just learn Objective-C, but to become a well-rounded programmer. To me this means having a large toolkit from which to choose from when approaching a problem.
I do understand the idea of learning bad habits from a strictly procedural language, but I don't feel that that's a strong enough argument against having a background in a procedural language before moving to OOP. To me, a higher-level language that supports OOP frees you of some of the more tedious, error-prone tasks such as manual memory management, buffer bounds checking, etc. These are the areas that beginners seem to have the most trouble with, so I think that once a better way is presented in an OOP language most will welcome it rather than clinging to concepts that they weren't 100% comfortable with. By the same token, however, there are some weaknesses of dynamic data structures provided by some languages and libraries. One of these is storage of an arbitrary number of primitives. Maybe you "shouldn't need" to store N ints, but I don't think it would be a "bad habit" if a particular problem, algorithm, etc. needed this. In Objective-C, you have options. You can fall back to the C way, and malloc yourself N*sizeof(int) bytes and assign the pointer to an int*. You can stuff each int into an NSNumber, then you can use NS(Mutable)Array. I'm sure there are other creative ways around this problem, but if this is a performance-critical area of code, having the C way of dealing with this in your back pocket is not a bad thing, in my opinion.
This certainly ended up longer than I had expected, but I think your point deserved a considerate response. I am not trying to defend myself against Kochan's point, as he's obviously more seasoned and has more experience educating new programmers. I'm just trying to provide a counter-point, and some rationale behind my advice.
-Lee