
A better introduction to Objective-C - js2
http://cocoadevcentral.com/d/learn_objectivec/
======
hiraki9
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];
      }

~~~
pashields
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.

~~~
alextgordon
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.

~~~
mikeash
Is there any situation where you would legitimately still have an observer for
an object which is being deallocated?

~~~
adamjernst
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.

~~~
mikeash
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!

------
natesm
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.

~~~
Zev
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.

~~~
zoul
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.

~~~
bmelton
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.

~~~
nolanw
> 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.

------
flyosity
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>

------
geuis
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.

------
Luyt

        [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 ;-)

~~~
sthulbourn
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...

~~~
nomurrcy
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.

~~~
sthulbourn
All 3 of your examples are viable; and you're right, Obj-C isn't that hard to
read once you understand the syntax.

------
acavailhez
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.

------
jollojou
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/...](http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/Introduction/introObjectiveC.html).

~~~
5hoom
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.

~~~
hboon
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.

~~~
DrJokepu
(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.

------
hexagonc
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.

------
jayfuerstenberg
GC and Arc will obsolete the memory management part of this tutorial but
otherwise a great resource!

------
tedkalaw
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.

------
robjohnson
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.

------
rapidos
Finally someone did it! I didn't read through it yet but I definitely love the
start. Thanks!

~~~
zoul
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.

~~~
Zev
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.

~~~
mcobrien
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.

~~~
jbjohns
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.

~~~
mikeash
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.

~~~
jbjohns
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.

~~~
mikeash
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+.

~~~
Zev
_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.

~~~
mikeash
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.

------
nhoss2
Is there something like this for java (for andrioid)

