Private properties and methods in Objective-C - iphone

In looking at one of Apple's examples, in the TableViewController.m, they have this:
// Private TableViewController properties and methods.
#interface TableViewController ()
#property (nonatomic, retain) NSMutableArray* sectionInfoArray;
#property (nonatomic, retain) NSIndexPath* pinchedIndexPath;
#property (nonatomic, assign) NSInteger openSectionIndex;
#property (nonatomic, assign) CGFloat initialPinchHeight;
... more properties and methods
#end
#implementation TableViewController
... usual stuff
I'm wondering why they put these properties in the .m file and how this is private. It seems like anyone who imports the TableViewController.m file can use these properties and methods right? Why not use the #private in the .h file?

What they're doing is declaring a category on the class, but since this is done in the .m file, the effect is that those methods are "invisible".
This doesn't mean however that those methods cannot be called from the outside. This is due to the fact that there is no real privacy in objective c, because we're dealing with messages, not method calls. This means you can send an object a message even if you do not know if that object actually implements the method you're trying to call. The receiving object will determine at runtime if it can handle this call, maybe it will even forward it, and it will make no difference whether the method was known to the calling object or not.
This is one of the reasons why it is possible to call private APIs and get rejected for it.

They're not private. They're anonymous properties, since they're part of an anonymous category.
One of the things properties are good for is putting the memory management semantics for an owned object in a single place. Consider this:
#property (nonatomic, assigned) NSString *assigned;
#property (nonatomic, copy) NSString *copied;
#property (nonatomic, retain) NSString *retained;
In all three cases, you can assign to them like this without knowing what their memory semantic is:
self.assigned = stringParameter; // assigns to instance variable
self.copied = stringParameter; // copies, assigns copy to instance variable
self.retained = stringParameter; // retains, assigns to instance variable
And in all three cases, you can free clean up using the same code:
self.assigned = nil; // this just nils the instance variable
self.copied = nil; // releases copy in ivar, nils instance variable
self.retained = nil; // releases ivar (same as original object),
// nils instance variable
This is why you'll often see local properties: It lets the coder skip writing all the memory management logic each time they want to assign to the instance variable. This is a major advantage in that you can change the memory management logic throughout the entire class just by changing the #property.
Another use of anonymous properties is to extend a property declared as readonly to outside code as read/write to the class itself.
In .h:
#property (nonatomic, readonly, retain) NSError *lastError;
In .m, in an anonymous category:
#property (nonatomic, readwrite, retain) NSError *lastError;
Elsewhere in .m code:
self.lastError = error;
Again, this is mostly done for memory management reasons.
An example, that pertains to either use of anonymous properties.
Here's what each assignment to a _lastError instance variable looks like without properties.
Assume we have a NSError called _lastError defined in the .h file.
With retain:
[_lastError release];
_lastError = [error retain];
With copy:
[_lastError release];
_lastError = [error copy];
With assign:
_lastError = error;
In the first two cases, you need this in your dealloc:
[_lastError release];
But in the last case, you must put nothing in the dealloc or you'll get a crash.
So let's add what we need to use a property instead:
Add this in an anonymous category:
#property (nonatomic, readwrite, retain) NSError *lastError;
Add this in the #implementation:
#synthesize lastError = _lastError;
Note, also, that at this point on the "modern" Cocoa runtime (64 bit Mac or iOS), you can remove the NSError *_lastError from your header. The compiler can figure out you want that based on the #synthesize.
Here's how that changes our code:
Each assignment:
self.lastError = error; // works regardless of storage specifier
In daelloc:
self.lastError = nil; // works regardless of storage specifier

AFAIK
a) You can not mark properties as #private in .h - this works only for ivars.
b) You will not be able to reference your class if you just import .m file (without interface definition in .h file). and if you do - you will get duplicate symbols during linking.
c) So yes these properties are private in the sense they are not accessible as regular properties from outside - these properties are accessible only using explicit messages - however you'll get warnings from compiler in this case or you could use KVC

First, you typically cannot import an .m file - not without numerous compiler/linker errors. Second, the properties are private so that Apple is free to change them in subsequent releases.
Yes, you can get to them via reflection. But that's a slippery slope, blah blah proceed at your own risk, will break in later versions blah blah reflection bad unless you know exactly what you're doing.

There are no private methods or variables in objective c, the #private flag is mainly there just so when other developers look at it, they know it's supposed to be private. What your seeing in the apple code is an example of a category, a way to fake private methods and variables in objective c. Because outside classes will import the .h file only, they will never see the added methods and variables in the .m file.

Using an anonymous category black boxes internal properties and methods that other classes should not know about. Although the compiler doesn't know about them when this class is referenced from other classes, you could technically access any of these properties from that other class using key value coding.

you can't import the implementation file TableViewController.m, Only the .h file of TableViewController could be imported,
Although, you could have the reference of these property outside your TableViewController class with a warning that shows the "not respond" note.

Related

objective-c interface - declaring variable vs just property?

In Obj-c when declaring a variable within #interface
#interface: NSObject{
MyObject* myObject}
#property (unsafe, nonatomic) MyObject* myObject;
Vs. Only declare it as a property
#interface: NSObject{}
#property (unsafe, nonatomic) MyObject* myObject;
#end
Not declare any var here?
Regards
Christian
#property defines an interface, not an implementation. In your case, you're defining a readwrite property. This means that you're promising to implement -myObject and -setMyObject:. This has nothing to do with ivars.
Now, the most common way to implement those methods is by having them be backed by an ivar. As a convenience, ObjC lets you automatically generate the required methods with an ivar store using #synthesize myObject=myObject_; This says "create the required methods for the property myObject using an automatically created ivar called myObject_." The ivar myObject_ is a real ivar, and you can access it normally (though you generally shouldn't; you should use accessors).
Instead of using #synthesize, you could just implement -myObject and -setMyObject:. You could even use #dynamic myObject; to tell the compiler "don't worry about the implementations for this property; it'll be handled correctly at runtime."
There are a few differences between #property and just declaring methods, but in principle, this line:
#property (nonatomic, readwrite, strong) MyObject* myObject;
is conceptually the same as this:
- (MyObject *)myObject;
- (void)setMyObject:(MyObject *)anObject;
Declaring the ivar yourself has no real impact here. You still need to implement the methods somehow. If your named ivar is the same as the ivar #synthesize is using, then #synthesize just won't create a new ivar.
As a matter of practice, I discourage people from declaring ivars anymore. I recommend just using public and private properties with #synthesize to create any needed ivars. If you must have a manual ivar for some reason, then I recommend declaring them in the #implementation block rather than the #interface.
Skipping declaring the ivar is perfectly fine--but you will not be able to see the ivar's value in the Xcode IDE. One day Apple may fix this.
You will be able to "po" the ivar to inspect it in GDB or lldb.

Do I still need to declare the instance variable if I am using #property?

In Objective C you can now use #property and #synthesize to auto generate get and set methods. My question is: Do I still need to declare the property in the interface? My program compiles and runs fine without it. But most books and other examples still have it. Why?
#interface Person : NSObject {
// do i need the declaration "NSString name;"? why?
// i have notice that my program works fine without it.
// but many programming examples still incude it.
// NSString name;
}
#property NSString *name;
#end
#implementation Person
#synthesize name;
#end
This depends on runtime. Modern runtime is used in iOS and you don't have to declade ivars. This is not always the case in OS X though. See here - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html
What you're talking about is the ivar. You do not need to declare it as the #synthesize adds it for you. This did not use to be the case on older compilers (and obviously before #propertiy was added to the language), thus a lot of people and books still do.
PS: You also do not need the {...} if you don't have any ivars, e.g.:
#interface Person : NSObject
#property NSString *name;
//...
You do not need to; the ivar will be generated for you. But the debugger won't show you auto-generated ivars, so I like to declare them anyways.
You don't need to declare the ivar. The #synthesize directive does it for you if you omit the ivar.

When do I need to have both iVar and a property?

I see some examples sometimes would declare a property as well as variable other times they do not .e.g. some time I see code like this
#interface Test : NSObject
{
UIProgressView* _progressView;
}
#property (nonatomic,retain)UIProgressView* progressView;
#end
at other times I will come across
#interface Test : NSObject
#property (nonatomic,retain)UIProgressView* progressView;
#end
Why what are the reasons ? I am learning and almost always use property and variable both.
I have used UIProgressView just as example.
Using ivars instead properties is only useful if you want #protected access (access from subclasses only), or support the old runtime (which required both).
It depends whether the property is synthesized against an iVar or derived in some other way (or against another iVar).
IF we have an instance of the class - i.e:
Test *myTest = [[Test alloc] init];
Then basically the property declaration
#property (nonatomic,retain)UIProgressView* progressView;
is telling anyone interested in using the interface that they can access the following two functions on an instance of this class:
[myTest progressBar];
[myTest setProgressBar:aProgressBar];
And objective C also lets you use shorthand notation:
myTest.progressBar =
xxx = myTest.progressBar
which does exactly the same thing.
It is not necessary for these two methods to be implemented via an iVar of the same name as the property, or even via an iVar at all (they could do even do a database fetch or derive the value).
If you #synthesize the property (which means you want the precompiler to generate the above methods for you) and don't explicitly specify an iVar on the #synthesize directive, then the methods described above will automatically be generated (due to the synthesize method) to set or get the value to/from an iVar of the same name as the property (and the implementation will include retain/release logic depending on the property directive.
If you don't #synthesize the property then you provide your own implementation and it can be anything you want. It is also possible to #synthesize the property but include a directive to use a different iVar in the method definition:
#synthesize progressBar=someOtheriVar;
in which case you will not see an iVar of the same name as the property in the header file either.

Instance Variable Syntax Question

When declaring an instance variable, does it make a difference if I declare it under #interface and as a #property? Example:
#interface MyViewController : UIViewController {
NSString *myString;
}
#property (nonatomic, retain) NSString *myString;
Would it matter if I took out the one under #interface? I have been doing that and would like to know if it does anything.
With a modern compiler (recent versions of LLVM), there is no need to declare the instance variables in conjunction with an #property (as tc says; it is the #synthesize that actually tells the compiler to reserve a slot, otherwise, you are on your own for storage) and doing so doesn't change anything.
One suggestion; when you #synthesize, do something like #synthesize myString = myString_; to cause the iVar to have a different name and, thus, make it impossible to accidentally directly access when you meant to go through the property.

Is a private synthesized property an oxymoron?

After going through a beginner's iPhone developer book and reading sample code online, I've noticed that most Objective C programmers synthesize nearly every instance variable. Some variables are convenient to snythesize, but most should not when honoring the object oriented principle of encapsulation. The worst are synthetized properties marked as private. A C++ programmer trying to use someone else's code will read the public fields and methods in the header file. They will skip the private variables. This C++ programmer will not know that you intended the private properties to be used in some meaningful way.
Take a look at this sample template on lazy table image loading provided by Apple:
Header
#interface ParseOperation : NSOperation <NSXMLParserDelegate>
{
#private
id <ParseOperationDelegate> delegate;
NSData *dataToParse;
NSMutableArray *workingArray;
AppRecord *workingEntry;
NSMutableString *workingPropertyString;
NSArray *elementsToParse;
BOOL storingCharacterData;
}
Source
#interface ParseOperation ()
#property (nonatomic, assign) id <ParseOperationDelegate> delegate;
#property (nonatomic, retain) NSData *dataToParse;
#property (nonatomic, retain) NSMutableArray *workingArray;
#property (nonatomic, retain) AppRecord *workingEntry;
#property (nonatomic, retain) NSMutableString *workingPropertyString;
#property (nonatomic, retain) NSArray *elementsToParse;
#property (nonatomic, assign) BOOL storingCharacterData;
#end
#implementation ParseOperation
#synthesize delegate, dataToParse, workingArray, workingEntry, workingPropertyString, elementsToParse, storingCharacterData;
Now I know this is not C++ and we shouldn't assume all C++ practices should be honored in Objective C. But Objective C should have good reasons to stray away from general programming practices.
Why are all the private ivars synthesized? When you look at the project as a whole, only NSMutableArray *workingArray is used by outside classes. So none of the other ivars should have setters and getters.
Why are very sensitive ivars synthesized? For one, now that id delegate has a setter, the user of this object can switch the delegate in middle of the XML parsing, something that doesn't make sense. Also, NSData *dataToParse is raw XML data retrieved from the network. Now that it has a setter, the user of this object can corrupt the data.
What's the point of marking everything private in the header? Since all ivars are are synthesized to have getters/setters, they are effectively public. You can set them to anything you want and you can get their value whenever you want.
I follow the idiom modeled by this example in many of my classes, so I can try to explain my own justification for this practice.
The properties in this example are declared in a class extension in the .m file. This makes them effectively private. Any attempt to access these properties from another class will cause a "Property not found" error upon compilation.
For developers coming from other languages, it may seem strange to synthesize getters and setters for private instance variables. Indeed, there is only one reason why I do this. When used consistently, synthesized properties can simplify memory management and help avoid careless mistakes that can lead to bugs. Here are a couple of examples:
Consider this:
self.workingPropertyString = [NSMutableString string];
versus this:
workingPropertyString = [[NSMutableString string] retain];
Many developers would claim that these two assignments are functionally equivalent, but there's an important difference. The second assignment leaks memory if workingPropertyString was already pointing at a retained object. To write code functionally equivalent to the synthesized setter, you'd have to do something like this:
NSMutableString *newString = [NSMutableString string];
if (workingPropertyString != newString) {
[workingPropertyString release];
workingPropertyString = [newString retain];
}
This code avoids leaking any existing object that the instance variable may be pointing to, and it safely handles the possibility that you may be re-assigning the same object to the instance variable. The synthesized setter does all of this for you.
Of course we can see that (workingPropertyString != newString) will always be true in this case, so we could simplify this particular assignment. In fact in most cases you can probably get away with a simple direct assignment to an instance variable, but of course it's the exceptional cases that tend to create the most bugs. I prefer to play it safe and set all my object instance variables through synthesized setters. All my instance object assignments are simple one-liners that look like this:
self.foo = [Foo fooWithTitle:#"The Foo"];
or this:
self.foo = [[[Foo alloc] initWithTitle:#"The Foo"] autorelease];
This simplicity and consistency gives my feeble brain less stuff to think about. As a result I almost never have bugs related to memory management. (I'm aware that the autorelease idiom could theoretically consume excessive memory in a tight loop, but I have yet to encounter that issue in practice. If I ever do, it's a simple case to optimize.)
One other thing I like about this practice is that my dealloc methods all look like this:
- (void)dealloc {
self.delegate = nil;
self.dataToParse = nil;
self.workingArray = nil;
self.workingEntry = nil;
self.workingPropertyString = nil;
self.elementsToParse = nil;
[super dealloc];
}
EDIT: Daniel Dickison pointed out some
risks to using accessors in dealloc
that I hadn't considered. See the
comments.
where every object property is simply set to nil. This simultaneously releases each retained property while setting it to nil to avoid certain crashes due to EXC_BAD_ACCESS.
Note that I've set self.delegate = nil; even though that property was declared as (nonatomic, assign). This assignment wasn't strictly necessary. In fact, I could do away with properties for my (nonatomic, assign) objects altogether, but again I've found that applying this idiom consistently across all my instance variables gives my brain less to think about, and further reduces the chance that I'll create a bug through some careless mistake. If necessary I can simply flip a property from (nonatomic, assign) to (nonatomic, retain) without having to touch any memory management code. I like that.
One could also use consistency as an argument for synthesizing properties for private scalar variables, as your example has done in the case of BOOL storingCharacterData;. This practice ensures that every instance variable assignment will look like self.foo = bar;. I don't usually bother to create private scalar properties myself, but I can see some justification for this practice.
Why are all the private ivars
synthesized? When you look at the
project as a whole, only
NSMutableArray *workingArray is used
by outside classes. So none of the
other ivars should have setters and
getters.
No real need; if you are going to access all the ivars directly anyway, there is no need for #synthesize.
Why are very sensitive ivars
synthesized? For one, now that id
delegate has a setter, the user of
this object can switch the delegate in
middle of the XML parsing, something
that doesn't make sense. Also, NSData
*dataToParse is raw XML data retrieved from the network. Now that it has a
setter, the user of this object can
corrupt the data.
None of the setter/getters are publicly declared. If a client of the class wanted to corrupt things by switching the delegate in the middle, they'd have to break encapsulation to do so.
So, ultimately, a non-issue.
What's the point of marking everything
private in the header? Since all ivars
are are synthesized to have
getters/setters, they are effectively
public. You can set them to anything
you want and you can get their value
whenever you want.
Note that there is no need to even declare the ivars in that example; the compiler will automatically synthesize them based on the #property declaration.
Traditionally, #private protected against someone diddling the ivar directly from externally to an instance of the class.
Note that anInstance->ivar or self->ivar is almost never used (and, when used, it is almost always for the wrong reason). There are uses for it, but it is rare.