objective-c interface - declaring variable vs just property? - iphone

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.

Related

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.

Private properties and methods in Objective-C

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.

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.

Do I need to declare a private variable for an IBOutlet* property?

Let's say I have a simple view controller with one UITableView property:
#interface MyViewController : UIViewController {
UITableView *tv; // <-- DO I NEED THIS??
}
#property (nonatomic, retain) IBOutlet UITableView *tv;
#end
Do I actually need to declare the UITableView *tv ? I've found that even if I don't declare it (and simply #synthesize the property), everything works fine. Yet, lots of code samples explicitly declare the variable. I'm not sure what the benefit of declaring it (or the harm of not declaring it) is.
In Objective-C 2.0, the compiler will synthesize the storage for you as well as the accessors. That didn't used to be the case, hence all the examples where people explicitly declare the ivar.
No you do not have to declare it, synthesize will take care of dynamically injecting the code at compile time. You will on the other hand not be able to inspect the variable directly in Xcode if you do not declare it, that's the downside.

Help: Instance Variables & Properties [iPhone]

In something like this:
#interface Control_FunViewController : UIViewController {
UITextField *nameField;
UITextField *numberField;
}
#property (nonatomic, retain) IBOutlet UITextField *nameField;
#property (nonatomic, retain) IBOutlet UITextField *numberField;
I understand that "UITextField *nameField;" is an instance variable and "#property ..." is a property. But what do these individual things do?
I guess what I'm really asking is how the property is used for example in the implementation file (.m)
The instance variables are the actual variables, whereas the properties are the equivalent of
- (UITextField *)nameField;
- (void)setNameField:(UITextField *)newTextField;
and completely optional. They are also used by the compiler to understand exactly what you want when you #synthesize a variable. Basically the properties and corresponding #synthesize (or custom implementation) allow OTHER classes access to variables, and are completely optional. It is in fact generally recommended, as per standard object oriented encapsulation principals, not to use properties unless you specifically intend for them to be used by external classes. However, you still need Interface Builder to recognize the UITextFields (presumably) which is why we typically put the IBOutlet decorator before the ivar declaration, not the property.