Think of the Objective-C's ivars like a plain old C-structure. When you instantiate an instance of a class, a block of memory is created large enough to hold that structure.
Let's say you have an NSString
. Lots and lots of existing code is compiled to use NSString
. Lots of this code is built into libraries and frameworks. That compiled code was created knowing that the ivars of NSString
take X number of bytes and are at some given offsets within that memory.
Now in your own little project lets say you create a category on NSString
and want to add an ivar. In theory, any code in your project that includes the header file for the category would know that the size of this "new" NSString
(plus category) takes X + Y bytes. This is much like a subclass. This newly compiled code could properly deal with the additional ivar(s).
But all of the pre-compiled code, the libraries and frameworks, would have no knowledge of the additional ivars. When NSString
instances are created there, the memory is only X bytes, not X + Y bytes. Chaos ensues as your app code gets a reference to that smaller chunk of memory and tries to access the bytes for the category ivar. Things would go boom.
With a plain old subclass, things work because any code that can use the subclass' ivars knows about the subclass's ivars. But with a category, pre-existing code has no knowledge of the additions and won't properly create the space for them.
I suppose I should specify that all of the above is largely an educated guess. I could be totally wrong. It seems reasonable at least. :)