I have noticed that with Xcode4 Apple has updated the application templates to include underscores before instance variables.
// Xcode4
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window = _window;
.
// Xcode3
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window;
I know there are differing opinions on the usefulness of this but I was just curious if the updated templates where:
(1) Highlighting a new best practice.
(2) Showing how Apple does things but meaning for you to do it the old way.
(3) Its just personal taste, it does not matter.
It's interesting because in the past (pre-iOS), Apple used to discourage the use of underscore prefixes for ivars:
Avoid the use of the underscore character as a prefix meaning private, especially in methods. Apple reserves the use of this convention. Use by third parties could result in name-space collisions; they might unwittingly override an existing private method with one of their own, with disastrous consequences. See “Private Methods” for suggestions on conventions to follow for private API.
But with a modern Objective-C runtime, I believe ivar naming conflicts in subclasses has been eliminated, so this is not a problem anymore. So I think that's why they're making the templates use an underscore prefix by default, to match what Apple's internal code looks like.
Related
I have dilemma about Memory releasing IBOutlet object.Do anyone please suggest what to do when we create IBOutlet object without property, need to release it?? if need to release... why we are releasing it
The answer is YES.
The runtime connects the objects to IBOutlet using [setValue:ForKey:]. This function will find the private instance variables, retain the target and set it to the instance variable. Please visit here iOS Developer Library to know more.
I highly recommend you to read the article because many iOS framework accesses properties by Key-Value compliance ([setValue:ForKey:] or [valueForKey:]), instead of directly calling getters/setters/instance variables.
IBOutlet does not change the ownership semantics of properties. If you do not use ARC you have to release retained objects as with any other property.
Just Set it to default, which is "Weak". Then you are fine with ARC.
Why not just have a private IBOutlet property, to make things clearer and more explicit. I always do this personally:
MyClassName.m
#interface MyClassName ()
#property (nonatomic, weak) IBOutlet NSObject *myPropertyNameForAnOutlet;
#end
#implementation MyClassName
...
#end
You are not the owner of that object. so no need to release IBOutlet object.If you are using #property (nonatomic, retain) on IBoutlet object then you must release that object in dealloc.
Take a look at Advanced Memory Management Programming Guide
You must not relinquish ownership of an object you do not own
Answer is YES...
i was confused about that too, but try this:
open a xib file
onen assistant editor window and get the .h file code near your XIB IB file
chose an object in IB file (an object with no reference to any var)
ctrl click on it and chose: "new reference outlet" button
drag the line to your .h code file in the #interface{ } section
give a name to your new var ("aaa")
(note that no property "aaa" is created)
now Xcode has done all the magic for you, and...
in .m file you can find, in dealloc method:
- (void) dealloc {
[aaa release];
[super dealloc];
}
so... if apple release it, it seems that the default IBOutlet vars loaded via XIB file are retained...
EDIT:
here's the point in apple doc:
You are not the owner of the object, therefore you do not release it.
You become the owner by retaining, copying or creating (init/alloc) an object. Only then you are you (one of the) owner(s) of the object, and need to release it when you are done with the object. Fore more info check
Cocoa core competencies - Memory Management
I hope this explains why you do not have to release the object.
Even though you didn't set it as property, the property is refer to setter and getter methods. When you use an object you should always remember to release it. The property is unrelated with memory issue.
i have 15 to 20 Variable i wants access it in my whole project. what is the best place for defining it and why?.. Appdelegate File, .Pch file or define these Extern.
really thanks in Advance.
Accessing your app delegate from various points of your app creates a strong coupling between these components of your app.
Basically you are using globals through your app which is usually a good indication for an improvable application design.
Variables usually do not live in thin air. They exist in a context. For example if you are using username and password you should get them from the system's keychain. The whole authentification process should be wrapped in an authentification class in which you would define the properties.
If you need to access information from various places of your app, you have to pass them as arguments of the initializer for example. This btw renders your individual components testable which is a good thing.
My advice is to rethink your app design first to not end in dependency hell later on.
You can define them as properties in your AppDelegate class. For example:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (retain, nonatomic) NSString *publicString;
If you want to make them readonly for external objects then you can define as follows:
1) in AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (retain, readonly, nonatomic) NSString *publicString;
2) in AppDelegate.m
#interface AppDelegate ()
#property (retain, readwrite, nonatomic) NSString *publicString;
#end
#implementation AppDelegate
#synthesize publicString;
// other methods below
#end
Create one header file by name 'defines.h' and implement all defines and constants in it.
import this file in .Pch file
This is the best one, and will be separate from other classes.
I'm an Objective-C newbie and I'm reading "iPhone programming" by Alasdair Allan. While reading, I found this code:
#interface RootController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *tableView;
NSMutableArray *cities;
}
// warning: remember this tableView
#property (nonatomic, retain) IBOutlet UITableView *tableView;
The relative implementation starts this way:
#implementation RootController
#synthesize tableView;
Now: I learnt that #synthesize is a sort of shortcut to avoid boring getters and setters.
But I've some question:
in the code of the implementation tableView is never explicitly called but the dealloc releases it;
if it never gets called explicitly why the #synthesize?
Is it mandatory for IBOutlets to be synthesized?
From Memory Management of Nib Objects,
When a nib file is loaded and outlets established, the nib-loading mechanism always uses accessor methods if they are present (on both Mac OS X and iOS). Therefore, whichever platform you develop for, you should typically declare outlets using the Objective-C declared properties feature.
For iOS, you should use:
#property (nonatomic, retain) IBOutlet UIUserInterfaceElementClass *anOutlet;
You should then either synthesize the corresponding accessor methods, or implement them according to the declaration, and (in iOS) release the corresponding variable in dealloc.
in the code of the implementation tableView is never explicitly called but the dealloc releases it;
That is because when you do assign a value to the tableView, your controller retains it, and it will need to release it when it gets dealloc'd. Don't forget, #properties declared in an interface are publicly accessible. In your case specifically, the tableView you're declaring as IBOutlet is initialized by the view controller loadView method using the connections you define in Interface Builder between the File's Owner and the UITableView.
if it never gets called explicitly why the #synthesize?
You need to provide accessors for all declared #properties. They can be #synthesized, or you could write your own.
Is it mandatory for IBOutlets to be synthesized?
No, but it's way more convenient that way. The rule enforced by the compiler is that #properties must have corresponding accessors (synthesized or not) in the implementation.
For reference: From Xcode 4.4 and LLVM Compiler 4.0 on the #synthesize directive is no longer required as it will be provided by default for #properties defined in the interface.
If you type
#property (nonatomic, retain) IBOutlet UITableView *tableView;
you tell the compiler: "Listen, there will be a getter and a setter. If appropriate, use them!" And it will use them when loading the nib.
Therefore you have to implement the getter and the setter otherwise the compiler will complain.
The IBoutlet pseudo-type is just a marker so that the InterfaceBuilder "knows" that the mentioned class-file has a handle/outlet to the UITableView instance.
When compiling IBOutlet is being removed by the preprocessor (InterfaceBuilder parses (looks at) the source files). It's similar with IBAction: it is being replaced with void by the preprocessor.
That said, you could use the reference to said instance to do stuff programmatically (Like adding/changing values of the UITableView)
While coding always the same questions concerning retain counts of IBOutlets came along: Retain count after unarchiving an object from NIB? When to use #property's for an IBOutlet? Retain or assign while setting? Differences between Mac and iPhone?
So I read The Nib Object Life Cycle from Apple's documentation. Some test apps on Mac and iPhone gave me some strange results. Nevertheless I wrote down a few rules how to handle this issue to stay happy while coding but now wanted to verify with the community and listen to your opinions and experiences:
Always create an IBOutlet for top-level objects. For non-top-level objects if necessary (access needed).
Always provide a property as follows for IBOutlets (and release them where necessary!):
Top-level objects on Mac:
#property (nonatomic, assign) IBOutlet SomeObject *someObject;
#synthesize someObject;
[self.someObject release];
Non-top-level objects on Mac (no release):
#property (nonatomic, assign) IBOutlet NSWindow *window;
#synthesize someObject;
Top-level objects on iPhone (must retain):
#property (nonatomic, retain) IBOutlet SomeObject *someObject;
#synthesize someObject;
[self.someObject release];
Non-top-level objects on iPhone (should retain):
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window;
[self.window release];
Side notes:
On Mac and iPhone outlet connections are made with a setter if available.
Top-level objects: "have [...] no owning object"
Non-top-level objects: "any objects that have a parent or owning object, such as views nested inside view hierarchies."
So the question would be: is this correct and good practice?
I hope you can approve or correct it.
Always have your nibs' File's Owner be a subclass of NSWindowController or NSViewController (on Mac OS X) or UIViewController (on iPhone), and use #property (retain) IBOutlet for all of its outlets, doing appropriate releases in your controller subclass -dealloc method.
This pattern will work fine on both Mac OS X and iPhone OS, because NSWindowController and NSViewController on Mac OS X take implicit ownership of top-level objects for you (and relinquish that in their own -dealloc methods), and iPhone OS doesn't take any implicit ownership of top-level objects for you during nib loading.
Top-level objects: "have [...] no owning object"
Nix. Top-level objects are owned by the File's Owner, which is the File's Owner because it owns all the top-level objects in the file.
Windows have that option to release themselves as a convenience, but I find my design cleaner (even if it's a little more work) when I either turn it off and manage its lifetime myself, just like any other object I own, or use a window controller.
If you think this conflicts with the documentation you were quoting, let's go through the entire paragraph:
Objects in the nib file are initially created with a retain count of 1. As it rebuilds the object hierarchy, however, AppKit autoreleases any objects that have a parent or owning object, such as views nested inside view hierarchies.
Thus killing off its own ownerships. The nib loader doesn't want to own your objects.
By the time the nib-loading code is done, only the top-level objects in the nib file have a positive retain count and no owning object. Your code is responsible for releasing these top-level objects.
In other words, it's handing the ownership over to you.
The curious artifact of that is that you'll actually leak the object if your property to it has retain semantics. The documentation says you should retain it:
For both Mac OS X and UIKit, the recommended way to manage the top-level objects in a nib file is to create outlets for them in the File’s Owner object and then define setter methods to retain and release those objects as needed.
But if you do this, the object will remain alive even after you release your ownership of it.
I think I'll go file a bug about this. (Edit: Done. x-radar://problem/7559755) At the very least, the nib loader shouldn't be handing off two retentions, which it does in my test app (on 10.5.8 and 10.6.1).
From apple's doc mentioned above:
For both Mac OS X and UIKit, the recommended way to manage the top-level objects in a nib file is to create outlets for them in the File’s Owner object and then define setter methods to retain and release those objects as needed. Setter methods give you an appropriate place to include your memory-management code, even in situations where your application uses garbage collection. One easy way to implement your setter methods is to create a declared property (using the #property syntax) and let the compiler create them for you. For more information on how to define properties, see The Objective-C Programming Language.
Otherwise use #property(nonatomic, retain) IBOutlet * outletName;
I can write my opinion about iPhone NIB development:
If you use IB then use as many IBOutlets as possible (sometimes you don't know the views hierarchy when you build a NIB - it may be dynamic) or don't use them at all - otherwise there will be a mess
Use properties only if you want to access the views from outside the View Controller (if they should be public)
AFAIK there's no need to manage memory for IBOutlets
Hope it helps...
You should follow standard memory management guidelines. If your outlet is connected to a retained property, then you must release it in the -dealloc message.
And yes, you any top level objects not retained by any other objects usually need to be retained by yourself.
1) In general, why would you have a top-level object with no IBOutlet to point to it anyway? That requirement has never seemed very restrictive.
2) I think you got the settings about right for the iPhone. You can also use an assign property on the iPhone as well, which does what you would expect... but in general after a lot of use I prefer to use retain properties so I am 100% clear on when I consider the object released (especially with the viewDidUnload method to implement).
Also, just as a side note it's not good form to call [self.property release]. That leaves the reference intact but potentially invalid, if something else ever also releases the object... either say self.property = nil, or (better) set the underlying class variable to nil directly without using properties in dealloc statements (to avoid any possible side effects in dealloc).
As I mentioned in response to another poster, you can keep things clean by using IBOutlet properties declared in private class-local category extensions so they are not public properties. That looks like:
// in .m file
#interface MyClass ()
#property (nonatomic, retain) IBOutlet UIView *myPrivateView;
#end
#implementation MyClass
#synthesize myPrivateView;
.....
In most examples I see the following setup of IBOutlets:
(Example A)
FooController.h:
#interface FooController : UIViewController {
UILabel *fooLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *fooLabel;
#end
FooController.m:
#implementation FooController
#synthesize fooLabel;
#end
But this works also fine (notice: no property and no synthesize):
(Example B)
FooController.h:
#interface FooController : UIViewController {
IBOutlet UILabel *fooLabel;
}
#end
FooController.m:
#implementation FooController
#end
Are there any downsides of defining IBOutlets as in Example B? Like memory leaks? Seems to work fine and I prefer to not expose the IBOutlets as public properties as they are not used as such, they are only used in the controller implementation. Defining it in three places without a real need does not strike me as very DRY (Don't Repeat Yourself).
On Mac OS X, IBOutlets are connected like this:
Look for a method called set<OutletName>:. If it exists call it.
If no method exists, look for an instance variable named <OutletName>, set it without retaining.
On iPhone OS, IBOutlets are connected like this:
call [object setValue:outletValue forKey:#"<OutletName>"]
The behavior of set value for key is to do something like this:
Look for a method called set<OutletName>:. If it exists call it.
If no method exists, look for an instance variable named <OutletName>, set it and retain it.
If you use a property, you'll fall into the "Look for a method called set<OutletName>:..." case on both platforms. If you just use an instance variable, then you'll have different retain/release behavior on Mac OS X VS iPhone OS. There's nothing wrong with using an instance variable, you just need to deal with this difference in behavior as you switch between platforms.
Here's a link to full documentation on just this topic.
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6
On Mac OS X, IBOutlets are not retained by defaults. This is the opposite of the behavior on iPhone OS: on iPhone OS, if you don't declare a property it is retained and you must release this property in the dealloc method. Additionally, the 64-bit runtime can synthesize instance variables using property declarations. That means that someday the instance variables (with the IBOutlet) may be omitted.
For these reasons it is more homogeneous and compatible to create always a property and use the IBOutlet only in the property. Unfortunately, it is also more verbose.
In your first example you always have to release the outlet in the dealloc method. In your second example you must release the outlet only with iPhone OS.
The end result is exactly the same, but you have to keep a few things in mind:
When using instance fields as outlets, you should NOT release them in dealloc.
When using properties that have the (retain) attribute, you have to release the property in dealloc (using self.property=nil or by releasing the backing variable). This makes it a lot more transparent as to what's going on.
Actually it all comes down to the same old rule: "thou shalt release what you alloc/retain". So in case you use an instance field as outlet, you didn't alloc/retain it, so you shouldn't release it.
Its possible that those examples use the retain because the sample code is programmatically allocating and initializing a UILabel and then adding it to the UIView. That's the case for many examples, since learning how to use Interface Builder is often not their point.
The second example (no property and no synthesize) with the IBOutlet is used when the developer 'assigns' the UILabel (Button, View, etc) within the Interface Builder -- by dragging the IBOulet to the Label or other View component. In my opinion, the preceding drag and drop action (Label onto View) also add the subview, the Label to a View -- and so on. Label is retained by a View; a View is retained by Window; Window is retained by File's Owner. File's Owner is usually your Document that is booted up in main.
You will note that when you step through your program (by adding an awakeFromNib
- (void)awakeFromNib
{
[fooLabel blahblah];
}
that fooLabel already has a memory address.
Thats because the Label was initialized from a file bundle (the nib file) using not init but initWithCoder. Which essentially deserializes the filestream to an object - and then sets the IBOutlet variable. (We're still talking about the IBOutlet method).
Also note that the aforementioned iOS method uses the Key Value method
call [object setValue:outletValue forKey:#"<OutletName>"]
which is the Observer/Observable pattern. That pattern require the Observable object reference each Observer in a Set/Array. A change in value will iterate the Set/Array and equally update all Observers. That Set WILL already retain each Observer thus the lack of retain in iOS.
Further and the rest is speculation.
It seems that cases when you do use Interface Builder then
#property (nonatomic, retain) IBOutlet UILabel *fooLabel;
should possibly be changed to
#property (nonatomic, weak) IBOutlet UILabel *fooLabel;
or
#property (nonatomic, assign) IBOutlet UILabel *fooLabel;
And then it needn't be released in a dealloc method. Plus it will satisfy the OSX and iOS requirements.
That's based on logic and I could be missing some pieces here.
Nevertheless, it may not matter if the view is persistent through the life of your program. Whereas a label in a modal dialog box (open, close, open, close) may in fact have over-retained and leak per cycle. And that's because (speculation again) each closed dialog box is serialized into a file system and thus persists x,y position and size, along with its subviews, etc. And subsequently deserialized ... on the next session open (Opposed to say minimiz or hidden.)