48 comments

[ 9.1 ms ] story [ 771 ms ] thread
Is there something like this for java (for andrioid)
A concise presentation of most of the core features of Objective-C. It lacks protocols, however.

Apple has a bunch of good tutorials, for example this one: http://developer.apple.com/library/mac/#documentation/cocoa/....

Coming from C++, protocols vs categories still mystify me a bit.

They appear to be methods for doing multiple inheritance type stuff without the multiple inheritance problems. From what I understand protocols set a list of methods that a class implementing that protocol must provide, whereas categories let you 'tack-on' methods to existing classes.

They seem like powerful features & I'm sure there is more to them than I've described, but I sometimes have problems re-wiring my brain to 'think in objective-c'.

Seeing more tutorials that show how to use these interesting language concepts in real projects would be very educational.

Protocols are "interfaces" (in the general sense of the word in programming). So they are useful when you want to write a delegate (or callbacks in the general sense of the word) class. Many classes have a delegate property that is of type id<SomeProtocol>. Equivalent to Java's interfaces, but Cocoa use protocols heavily for delegates only.

Categories are useful not for sharing code, but for expanding a class's functionality. This is especially useful when you write a class X that works with an existing class Y, but some of X's code should be an instance method of Y, or X introduces additional capability for Y to support X. UITableView adding functionality to NSIndexPath to support referencing table sections and rows is a good example. All those Java classes that add static methods to support existing Java classes, or if you used Smalltalk and added methods to existing classes, this is the equivalent.

(I agree with you, this is just nitpicking)

>Equivalent to Java's interfaces, but Cocoa use protocols heavily for delegates only.

Uh, NSCoding, NSCopying and the million other non-delegate protocols? Cocoa uses protocols heavily for a lot of things, not just delegates. The average Cocoa/Cocoa Touch developer, however, uses protocols mostly for delegates.

Close.

A protocol says that an object can (and in some (but not all) cases, is required to) implement a given list of methods, leaving the implementation/the "how" up to the programmer. Think of protocols as being similar to interfaces in Java.

OTOH, A category says "in addition to the existing methods, this class will also, for sure, implement these additional methods — and here's how."

A protocol is an interface (a type contract), a category is a mixin (class extension)
This is an excellent tutorial, especially compared to the other one. The only thing I took issue with was this:

    if ( [self hasPrefix:@"http://"] )
        return YES;
    else
        return NO;
The other thing that puzzled me a little was the K&R interfaces and Allman everything else, but I guess it's a consistent style. I do use K&R exclusively for blocks, so I suppose I am just as guilty.
What was your issue with that? It not being written as below?

  return [self hasPrefix:@"http://"];
If so, I disagree. The way it was written in the tutorial is easier to read when going into a new language — and teaches you that Objective-C uses YES and NO, rather than true and false.
I think people should not use awkward code in tutorials and then say it was for the sake of illustrating a point. Otherwise the readers can pick up bad idioms just as in a natural language. In this case I doubt the author wanted to showcase YES/NO. And if that really was the intention, you can easily add one sentence after the code example, explaining the potentially strange BOOL type and its values.
The code is very easy read. And, when you're getting started, being easy to read is very important. Besides, it is still semantically correct. (Also FWIW, I didn't find it very awkward, personally.)

I might even be convinced to go a step further and say that early on, it is far more important to actually get started and avoid hitting roadblocks, then it is to write nice and pretty code. You can figure that out later on, once you're comfortable with everything.

I think his point is that the code is written differently than it would be written in practice solely to make a pedagogical point. Tutorial code should exemplify well-written practical code in addition to whatever concept is being demonstrated.

This particular construct is debatable - I personally think it can read better to explicitly break out a boolean statement like that in some cases, especially in a simple method like in this example. I certainly wouldn't take a hostage over that opinion, though.

Anybody who can pick up Objective-C from a single HTML page is unlikely to be such a beginner that they are flummoxed, confused or unduly influenced by this code.
Don't confuse awkward with clever. The code that illustrates the IF conditional is far more readable than the self-returning YES or NO, where you don't even know that YES and NO are the return values.

Arguably, an ObjC programmer should know that booleans are YES and NO and not true or false, but so what? Code that can't be maintained isn't good code. Code that is developed within a team should be readable before it should be clever. if it is clever, or if it needs to be clever, then it should be commented to the degree that it is more easily understood.

I personally would rather write readable code than more comments.

Actually, YES == TRUE == 1 and NO == FALSE == 0.
> Arguably, an ObjC programmer should know that booleans are YES and NO and not true or false

It's just C. 0 is false, anything else is true.

I think that it teaches that conditionals (or boolean constants) are "special". When I first learned to program I did similar things, and I think it held the "everything clicks" moment back.
Why do you have a problem with that when they said, "Keep in mind this is not a good implementation of URL detection. We're just trying to get the concept of categories across:..."
Finally someone did it! I didn't read through it yet but I definitely love the start. Thanks!
Please note that the tutorial was written some three years ago. It starts to show on some parts, for example people starting to learn Objective-C today can spare themselves the trouble of manual memory management and use Automatic Reference Counting supported by the upcoming Xcode release.
Please note that you still can't ship an app that uses Automatic Reference Counting on iOS, and we don't have any real idea of when we will be able to. Last time I had a discussion about this on HN, the other person was convinced it would have come out early September.
(comment deleted)
We have a pretty good idea. As soon as iOS 5 goes GM, we'll be able to use Xcode 4.2 (and ARC) to submit apps. With the rumoured announcement next week, iOS 5 should be GM in the next week or two.

In any case, if you're reading an introduction to Objective-C today, you're probably not going to be submitting anything to the App Store in the next fortnight.

But will apps made with Xcode 4.2 and ARC run on older iOS versions? I mean, my understanding was that ARC was a compile time thing, so there should be no difference in an ARC app and a non-ARC app (except the ARC one probably has less bugs) but I've heard others talk about needed runtime support.
ARC includes zeroing weak references, which need runtime support. These are only available on iOS 5.

The rest of ARC still needs a bit of runtime support, but the functions it needs are basically just wrappers around the standard Objective-C memory management messages. They exist because they enable various optimizations. Apple provides a shim library for these which allow ARC apps to run on iOS 4.3. I'd guess they could run on even earlier OSes, but I believe that's not officially supported.

Thanks for your answers. Does this mean we have to maintain different versions of each app or is it reasonable to say nothing earlier than 4.3 is supported [1]?

[1] Full disclosure: I haven't released my first app yet so I'm wondering if I should only develop with the new IOS 5 tools or if I'm going to have to write my app with Xcode 4.1 anyway.

This is just my opinion, so don't take my word for it.

There is no reason to support anything earlier than iOS 4.3 for an app being released today. 4.3 works on all devices except the original iPhone, the 3G, and the equivalent iPod Touch models. It's also a free upgrade for (nearly?) everybody. The fraction of your audience still using something prior to 4.3 will be very small.

If you're not releasing very soon, it will probably be worthwhile to simply require iOS 5. New OS version uptake tends to be fast, and it seems likely that those who don't update their OS are also less likely to buy apps. iOS 5 is a pretty big deal with a lot of new features, so I think it will probably see pretty swift uptake. iOS 5 also provides a lot of nice features for a developer (like those zeroing weak references, which I believe are pretty important for ARC programming), so there's a good incentive on your end to require 5+.

There is no reason to support anything earlier than iOS 4.3 for an app being released today.

There's only one reason that I can think of: Verizon/CDMA iPhones only run iOS 4.2.x, and won't be on parity with GSM iPhones until iOS 5 comes out.

Good point, I forgot about that. I would argue that, with the small number of CDMA iPhones sold so far, and with iOS 5 just around the corner (maybe as early as next week), they can be ignored for this purpose.
There is no reason to support anything earlier than iOS 4.3 for an app being released today.

For whatever reasons, some users still stick with older firmware versions. 100% of our userbase is iOS 4+, but about 10% of it is below 4.3.

This introduction is excellent, it's aimed at programmers who wants to get a first and painless overview on how Objective-C is coded and how to read Objective-C code. It gives you all the subtleties of the language, compared to the other (the unusual method calling syntax being the first). It's kind of a starting blocks for learning a new language, exactly what I look for when I learn a new langage.
Thank you. Really, thank you. I'm not sure why the world works as it does, but so often when I am attempting to learn or accomplish something, within a day or so something comes along that exactly matches what I need.

In this case, I had a desire to dig into an Obj-C project yesterday to try yet again to really learn it. The Apple tutorial is extensive, if verbose. This introduction is exactly what I need at this moment to get me through the knowledge gap.

(comment deleted)

    [NSString stringWithFormat:[prefs format]];
"Avoid nested nesting more than two message calls on a single line, as it easily gets unreadable."

Oh, the joy of function call chaining in languages like JavaScript:

    rs = db.find({"name": "Joe"}).limit(10).lower().sort();
I don't dare to imagine how that'd look in ObjectiveC ;-)
Something like:

  NSArray *records = [db find:[NSDictionary dictionaryWithObject@"Joe" forKey:@"name"] limit:10];

  [records sortedArrayUsingComparator:^(id a, id b) {
    // logic for sorting
  }];
...and then you'd do the lower method on usage...
Or even (granted that I'm assuming the whole db api here is fake, and you'd actually probably be using core data here)

  NSArray *records = [[db find:[NSDictionary dictionaryWithObject:@"Joe" forKey:@"name"] limit:10]
                       sortedArrayUsingComparitor:^(id a, id b) {
                         // sort logic
                       }];
I typically add a category to NSArray for mapping a selector or block. The signatures are - (NSArray )mapBlock:(id (^)(id object))block; - (NSArray )mapSel:(SEL)selector;

Which would enable you to do it all in one statament:

  NSArray *records = [[[db find:[NSDictionary dictionaryWithObject:@"Joe" forKey:@"name"] 
                       limit:10]
                       sortedArrayUsingComparitor:^(id a, id b) {
                         // sort logic
                       }]
                       mapSel:@selector(lowercaseString)];
Also for mapping over an array you can usually use NSArrays valueForKey: which returns a new array which contains the result of calling valueForKey: on each member of the target array. As your sorting logic would typically exist in the db layer whether you were using CoreData or something else, it would be easy to write a wrapper such that you could write something like:

  [[[[MyFetchRequest forEntityNamed:@"foo"
          orderedBy:@"SomeKey"
          limit:10] fetch]
    valueForKey@"nameField.lowerCaseString"]
    enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
       // do stuff here
    }];
Again this is all 'fake' code as this is just a readability discussion.

I don't really agree with the article that nesting message-sends leads to unreadable code. I think reading obj-c is a lot like reading lisp s-expressions and your eye / brain quickly learns to read nested constructs. I generally try not to save anything to an explicit var that I don't intend to use somehow. (of course there are limits to this) I don't find nested code above difficult to read, YMMV.

All 3 of your examples are viable; and you're right, Obj-C isn't that hard to read once you understand the syntax.
GC and Arc will obsolete the memory management part of this tutorial but otherwise a great resource!
This tutorial was how I learned Objective-C and Cocoa. Scott Stevenson's got a great and flowing writing style that's easy to follow.

Don't miss all of the other more advanced tutorials similar to this one at the full site, http://CocoaDevCentral.com

This is incorrect:

  - (void) dealloc
  {
    self.caption = nil;
    self.photographer = nil;
    [super dealloc];
  }
Using the dot syntax will invoke a setter whose implementation might change if the class is subclassed, which can be the cause of subtle errors. Also, if you're using KVO (Key-Value Observing), invoking the setter might notify observers who then try to work with a (partially) deallocated object.

This is standard:

  - (void) dealloc
  {
    [caption release];
    [photographer release];
    [super dealloc];
  }
Can you expand on this, as the resistance to this style has always confused me. The concern you are presenting is that a subclass could implement the setFoo method, and do so in a way that: 1) does not call [super setFoo:], and 2) does not follow the convention of handling memory management appropriately?

My problem with this argument is that the user could botch release just as well. Maybe they are slightly more likely to botch the setter, but either way they are botching it.

If you have an observer listening for changes on the "photographer" key, then `self.photographer = nil;` will send off a KVO event. [photographer release]; will not.

Since your object is likely to be dealloced at an odd time (for instance when an autorelease pool is drained), and in an inconsistent state (half its fields missing), it's much better to do a release.

Is there any situation where you would legitimately still have an observer for an object which is being deallocated?
I can contrive one. Class A holds a strong (i.e., retain) reference to an instance of class B in a property "myB". A also has a property "myC" which B observes.

  - (void)dealloc {
    self.someOtherVariable = nil;
    self.myC = nil; // Sends KVO on myC. B sees half-deconstructed A.
    self.myB = nil; // myB now is dealloc'd and stops observing A.
    [super dealloc];
  }
Admittedly this is a real edge case and probably bad design, but it's not overtly terrible. I have a couple cases where objects observe their owners.

BTW thanks for the blog, Mike! I love it.

I'd argue that this would be a bug. B has a weak reference to A here (whether explicitly or just implicitly through KVO) and that weak reference should be cleared out first thing before tearing down the rest of the object. The method should start with a [myB setA: nil], then go on with the rest. Setting that to nil would then remove the observation, solving the problem.

There may well be similar setups which aren't broken which still exhibit the problem, though.

Glad you enjoy the blog!

This was a good resource when I was learning objective c. The Apress objective c book, as well as the apple documentation are also good resources.
This is a great introduction, but to this day I find the sheer size of Cocoa the largest barrier to entry for Mac and iPhone development.

Just have to get used to it, I suppose.

Not bad but I would have liked to have seen a formal grammar for the syntax structure, especially since it is so different from Java, C# and C++ which most developers are familiar with. It was especially difficult to understand the syntax around keyword-based input arguments for methods. I only understood it on my second reading and only then because I was already familiar with the concept from LISP. There were also no examples or even mention of flow control statements. That seems like a glaring omission.

Perhaps most importantly, the tutorial should have mentioned that objective-c is a superset of c. That alone would have answered most of the questions around flow control statements since those, presumably, use the same syntax as c. As it stands, there's barely enough in this tutorial to do basic scripting with objective-c.