
A Year’s Worth of Opinions about Objective-C - lelf
http://twistedoakstudios.com/blog/Post8237_a-years-worth-of-opinions-about-objective-c
======
berzniz
I actually like the way nil is treated. I'm not a big fan of writing code with
guards all the time like this:

// As in C#/Java if (obj != null) { obj.doSomething(); }

At least in javascript it's easier with the && operator:

str && str.doSomething();

In Obj-C you can just:

[str doSomething]; // If you really care if it happened or not, then introduce
a check for nil

Once you get used to the idea that nil doesn't break your code, you start
writing your methods accordingly.

For me, a lot of the stuff you write about (ARC, Blocks, literals) are the
great improvements to the language.

Before ARC you had C/C++ like control of the memory and you could do some
crazy stuff like an object holding on to itself and then committing suicide
(pretty useful actually). With ARC you _only_ have to care about retain cycles
and declaring weak/strong pointers. It's an awesome feature for a non-GC
environment.

Blocks are truly the biggest change in Obj-C and made the code much easier to
develop. Any async task is now easy to deal with. Alongside GCD, multi-
threading is made simple.

What I'm really trying to say is that from the first iPhone OS to iOS7, we've
seen some major improvements to the language. If it continues at the same
pace, you'll might like it more in your next year's review.

~~~
rbritton
There are some annoying circumstances where you still have to check for nil,
so it's not exactly consistent. For example:

1\. Adding nil to an array triggers an exception.

2\. Trying to set a dictionary key/value pair with nil for either value
triggers and exception. It'd be more consistent with other parts of the code
base if setting a nil value unset that particular key.

3\. Calling a block storage variable that's nil will crash.

It'd be nice if these all were no-ops too.

~~~
jawngee
It is consistent though.

Sending a message to nothing gets your nothing. Adding nothing to something
that expects something causes an exception.

~~~
rbritton
I suppose it depends on what you consider consistent (i.e., all nil operations
should be no-ops or just message-sending operations), but that only covers 1
and 2. Trying to invoke a nil block still crashes.

~~~
paintstripper
That's because blocks aren't completely objective-c objects. They can act like
them in some cases, but underneath they are still C based. That's why you pass
NULL instead of nil to specify an empty block.

~~~
mikeash
All of Objective-C is C based in the end. Blocks are completely Objective-C
objects. Attempting to call a NULL block crashes not because blocks aren't
Objective-C objects, but because block invocation is not a message send.

Note that accessing an instance variable of a nil Objective-C object pointer
will also crash, e.g.:

    
    
        obj->_ivar;
    

That's obviously not because Objective-C objects aren't Objective-C objects.
The crash when calling a nil block is the same thing.

------
norswap
I'm considering writing a similar post. For me the biggest write was how steep
the learning curve for the whole Cocoa (referring mostly to UIKit, but also to
a few other pieces) shebang was. It's not even that the system is badly
designed (arguably it could be a lot better though) but that the documentation
is so so bad. API docs are okay, but don't give you the big picture. Their
reference guide, on the other hand are so abstract and 1000-mile high that you
don't really get practical value out of them.

After that, the system with small inconsistencies, imprecise documentation and
undocumented behaviour. In short, it's not very "systematic". You don't feel
there's a well thought-out system that will allow you to predict what will
happen. This is especially true when talking about layout, but also other
things such how views / controllers interact. There's not a culture of "best
practices", so interfacing with someone else's UI libraries can be hell.

@Author: Any thoughts about this?

~~~
Strilanc
I haven't done enough UIKit stuff to really comment on it, other than to say I
also still find a lot of the conventions confusing or at least weird and also
find that the documentation fails to answer my questions.

I also don't get the distinction between a UIView and a UIControllerView. In
C# land I always associated view=.xaml and controller=.cs. In obj-c land both
views and view controllers have a .xib and .m/.h, so it's not clear to me how
responsibilities are divided.

~~~
mmorey
A view can be a scene in a storyboard file, a xib file, or you can create your
views programmatically (.m and .h).

A view controller is always a .m and .h.

And if you're not following the MVC pattern you can put your view code in your
view controller's loadView/viewDidLoad method.

~~~
Strilanc
Thanks, that's actually a helpful thing to mention and obvious in hindsight. A
view controller can be the _owner_ of a .nib but not the _class_ of a .nib, so
the .nib is never a view controller.

Are there particular divisions of responsibility that come up w.r.t. what you
put in a view's .m/.h vs what you put in the controller's .m/.h? Is the .m/.h
of a view considered to be a controller in the MVC sense but not in the
UIViewController sense?

------
aaronbrethorst
I don't intend to belittle the author's writeup of their experience with
Objective-C. I've been working with the language off and on for over ten
years, now, and have been working almost exclusively in it professionally for
the last 3 or 4, and I have a ton of complaints about it. But...

With one exception, I feel like this entire post could be summed up as 'I
don't like dynamic languages, static typing FTW!' The one exception is with
regard to merging pbxproj files, which, I agree, is a fantastically awful
experience. The only worse experience I have ever had working with this stack
is in trying to merge XIBs (short answer: just don't even bother trying).

~~~
mikeash
Getting off topic, but have you seen the new xib format in Xcode 5? It's
totally different and _way_ better. I haven't actually tried merging one yet,
but I'm highly optimistic for when it comes up.

~~~
aaronbrethorst
No, I haven't. I'm guessing you have to either explicitly upgrade your
existing XIBs to it, or recreate them? Thanks for the head's up, I'll check it
out.

Also, thanks again for the ridiculously awesome blog. It's been one of my
favorite reads for years.

edit: OK, I had a chance to check out the file format. This looks far more
sane and human-readable than it has in the past.

Related: I will happily pay $100 to anyone for a piece of software that has an
auto layout constraint generator that works with XIB files and doesn't suck.

~~~
mikeash
I think you have to manually convert existing ones. I'm fuzzy on the exact
details, but I think there's a popup in the right-side info pane that lets you
choose which Xcode version (and thus which format) you want to use for the
xib.

Glad you like the blog!

------
drewcrawford
In defense of ObjC's type system (which is the author's major gripe).

It is a duck-typed language. This is the philosophy that "if it walks like a
duck... it's a duck." This is the philosophy used by lots of modern languages
like Python, Ruby, and JS.

Meanwhile there is the statically-typed system, which wants you to declare
things to be ducks explicitly (or to pick up a duck declaration through an
inheritance system). This is the philosophy used by Java, C++, etc.

Anyway, the author's gripe isn't with ObjC's types. The author's gripe is with
any duck-typed system. The whole point of these type systems is to avoid
providing any strong guarantees about types. If you want strong typing, use a
strongly-typed language. C++ may align better with this author's programming
ideology.

It's also worth pointing out that runtime type checks are, all else being
equal, slow. ObjC is used primarily in mobile environments where speed is a
concern. As the author discovered, you can opt in to type checking by using
NSAssert. This forces you to think about whether the cost of a dynamic type
check is acceptable. NSAsserts are also disabled by default in release builds,
so this gives you checking when you need them (development) and speed when you
don't (production).

C++'s type system is deliberately constructed in such a way that the compiler
can do the bulk of the type enforcement, which is much faster than runtime
type checking. Alternately stated, this means that the programmer must write
code in such a way that the compiler can infer/enforce type checks, or else
they will get type errors. The author's complaints about not enough compiler
errors seem to suggest to me that he would be more at home in a language like
C++ that is specifically designed for this purpose.

~~~
stevoski
> If you want strong typing, use a strongly-typed language.

Unfortunately in iOS development, we don't have a good alternative to ObjC.

~~~
drewcrawford
Well _good_ is debatable but arguably C++ meets this criteria. I work on many
iOS codebases that have C++ layers.

------
joshuaellinger
As a C# dev without a real project for the iPhone, I couldn't get past how
cluttered the same code looked.

It would be nice to hear how the class library compared to VCL.

~~~
Strilanc
Assuming you mean the BCL (base class library).

In my experience, the BCL is more comprehensive. For example, the iOS
framework lacks a built-in queue or a sorted list (as far as I know).

One thing Obj-C does have, that I miss in C#, is equality methods defined for
collections. You can compare the contents of arrays and sets and dictionaries
without writing any special code or using special methods. (Although you can
break it by creating cyclical structures, since it does naive recursion
instead of unification.)

~~~
jrmg
_the iOS framework lacks a built-in queue_

The convention for this sort of thing is to use an NSArray, inserting at
position 0 to enqueue and removing the last object to dequeue. The NSArray
class _is_ actually written in a way that makes this efficient (for some great
analysis see
[http://ridiculousfish.com/blog/posts/array.html](http://ridiculousfish.com/blog/posts/array.html)).

 _or a sorted list (as far as I know)_

For sorted lists, I think you're right, you'd have to do it yourself.

The question a Cocoa old-hand might ask would be if you _really_ need it to be
always-sorted, or if you can keep your objects in an array, dictionary or set
and sort them before using or iterating - or maybe just iterate the collection
in a specific order instead of sorting it at all.

If you do need to keep it sorted all the time, note that _inserting_ into an
NSArray is also more efficient than you might assume. Keeping a sorted NSArray
up to date yourself might not be expensive (it would be a bit more complicated
than an auto-sorting class though, of course).

~~~
jawngee
You have to sort it yourself, but it's super easy.

For NSArray's:

    
    
        NSArray * sortedArray=[array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            // your code here
        }];
    

For NSMutableArray's:

    
    
        [marray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            // your code here
        }];

------
lupinglade
So Objective C is not what you're used to? Awh... It's no secret that
Objective C software is generally richer and more robust, thanks exactly to
its "strange" differences. Sure it takes effort to learn a new way of doing
things but if you're willing, you'll soon realize it was worth it. Dynamic and
compiled is a great combination.

