How do you read Objective-C if you only know Swift, and what looks different but means the same?
Predict first
What does this print? (CountOf is Objective-C and calls [items count] on a possibly nil pointer.)
print(CountOf(nil))
- 0
- Crash
- nil
Predict first
In Objective-C, what does if (obj) test?
// A: that the object is valid and non-empty
// B: that the pointer is not nil
// C: that the object responds to isEqual:
- A
- B
- C
Mental model. It is a dialect of the same language, with different punctuation. The grammar is familiar; the pitfalls are in the idioms.
The shapes map one to one. A method call [obj doThing:x with:y] is obj.doThing(x, with: y). @interface declares the public API (in the .h), @implementation holds the code (in the .m). A leading - is an instance method, + a class method. @property declares a property with attributes (strong, weak, copy, nonatomic, readonly) and, by default, a backing instance variable named _name. Objects are created with [[Foo alloc] init], and an initialiser typically reads if ((self = [super init])) { … } return self;. id is “any object”, NSInteger and BOOL (with YES and NO) are plain C values, and literals are @"text", @42, @[…] and @{…}.
The differences that bite: sending a message to nil returns zero instead of failing, so a missing object often produces silent no-ops; == compares pointers, while equality is isEqual:; if (obj) tests for non-nil; any pointer may be nil unless annotated; arrays hold objects only, so numbers are boxed in NSNumber; and a missing return or a stray ; may compile with only a warning. Read the property attributes first, because they tell you who owns what.
Messaging nil returns zero, so the count of “no array” is 0, with no crash.
It is only a pointer check. An empty string or array is still a non-nil pointer, so the test is true.
Common traps
- Comparing strings with
==. It tests identity, so it works by accident for literals and fails for dynamic strings. - Treating
nilmessaging as a bug. It is defined behaviour, which is why bugs from missing objects hide so well.
They might follow up with
- What does
@synthesizedo? It names the backing instance variable; modern compilers do it automatically. - Where is the “private” API? In a class extension (
@interface Foo ()) at the top of the.m.
Related questions
- 4.1.1 What happens when you send a message in Objective-C, and what if nothing responds?
- 4.5.1 How do nullability annotations change what Swift sees, and what happens when they lie?
How do Objective-C blocks differ from Swift closures, especially for… →