Object-oriented – Ongoing confusion about ivars and properties in objective C

object-orientedobjective cpropertiesvariables

After almost 8 months being in ios programming, I am again confused about the right approach. Maybe it is not the language but some OOP principle I am confused about. I don't know..

I was trying C# a few years back. There were fields (private variables, private data in an object), there were getters and setters (methods which exposed something to the world), and properties which was THE exposed thing. I liked the elegance of the solution, for example
there could be a class that would have a property called DailyRevenue…a float…but there was no private variable called dailyRevenue, there was only a field – an array of single transaction revenues… and the getter for DailyRevenue property calculated the revenue transparently.
If somehow the internals of daily revenue calculation would change, it would not affect somebody who consumed my DailyRevenue property in any way, since he would be shielded from getter implementation.

I understood that sometimes there was, and sometimes there wasn't a 1-1 relationship between fields and properties. Depending on the requirements. It seemed ok in my opinion. And that properties are THE way to access the data in object.

I know the difference betweeen private, protected, and public keyword.

Now lets get to Objective-C.

On what factor should I base my decision about making something only an ivar or making it as a property? Is the mental model the same as I describe above? I know that ivars are "protected" by default, not "private" as in C#.. But thats ok I think, no big deal for my present level of understanding the whole iOS development. The point is ivars are not accessible from outside (given I don't make them public.. but I won't).

The thing that clouds my clear understanding is that I can have IBOutlets from ivars. Why am I seeing internal object data in the UI? *Why is it ok?* On the other hand, if I make an IBOutlet from property, and I do not make it readonly, anybody can change it. Is this ok too?

Let's say I have a ParseManager object. This object would use a built in Foundation framework class called NSXMLParser. Obviously my ParseManager will utilize this NSXMLParser's capabilities but will also do some additional work. Now my question is, who should initialize this NSXMLParser object and in which way should I make a reference to it from the ParseManager object, when there is a need to parse something.

A) the ParseManager

1) in its default init method (possible here ivar – or – ivar+ppty)

2) with lazyloading in getter (required a ppty here)

B) Some other object – who will pass a reference to NSXMLParser object to the ParseManager object.

1) in some custom initializer (initWithParser:(NSXMLPArser *)parser) when creating the ParseManager object..

A1 – the problem is, we create a parser and waste memory while it is not yet needed. However, we can be sure that all methods that are part of ParserManager object, can use the ivar safely, since it exists.
A2 – the problem is, the NSXMLParser is exposed to outside world, although it could be read-only. Would we want a parser to be exposed in some scenario?
B1 – this could maybe be useful when we would want to use more types of parsers.. I don't know…

I understand that architectural requirements and language is not the same. But clearly the two are in relation.

How to get out of that mess of my?

Please bear with me, I wasn't able to come up with a single ultimate question. And secondly, it's better to not scare me with some superadvanced newspeak that talks about some crazy internals (what the compiler does) and edge cases.

Best Answer

First, I think you're asking many questions, not one.

And half of the answers of these questions is the ever correct "It depends".

In general, exposing object ivars directly is discouraged if you're aiming for looser coupling (obviously). Although I think when it comes to IBOutlets it is an acceptable practice, since after all the Interface Builder is tasked with the creation of the object.

On the other hand, a readwrite property for an NSInteger makes little sense, unless you're doing something very funky, and you can easily use an ivar instead.

Once upon a time, in pre-ARC ages, there were some people, who advocated always using properties for objects, since then you don't need to care about retain/release. However now that ARC is widely used, this makes almost no difference and it is mostly a cosmetical thing.

A final piece of advice: aim for consistency project-wide.

EDIT: I'm not the greatest fan imaginable of Design Patterns, but it seems that most of your questions would find the best answer in this book.

Related Topic