Class method to return autoreleased object - iphone

I have been following the iPhone development videos on iTunes U and so far so good. I think I understood things well enough.
The thing is that on the examples they provide they never create custom class methods just like those that you use on some Foundation classes (like [NSString string]) so I'm not sure as to how I should go about creating my own class method to return an autoreleased instance of my class.
I do know how to create a retained object using an instance method but I'd rather use a class method because I prefer it, I'm just not sure if this implementation would be the most appropriate to return an autoreleased object:
+ (PhotoViewController*)initWithImageView:(UIImageView*)imageView
{
PhotoViewController *toreturn = [[PhotoViewController alloc] init];
toreturn.imageview = imageView;
[toreturn autorelease];
return toreturn;
}
Thanks a lot for any help you may provide.

A class method can return either a retained or autoreleased object as you wish, and your code returns an autoreleased object perfectly appropriately.
However you should probably name your method differently. Since your method begins with init, that implies it is initialising an alloced object (and should therefore be an instance method rather than a class method). I'd suggest naming the method photoViewControllerWithImageView: if it's going to return an autoreleased object.
Also, I'd probably write it as return [toreturn autorelease]; but I guess that's a style preference of mine.

I think it's a good practice to check whether toreturn is nil or not before accessing imageview property.

Related

property assign

If I have one property like this, what is the diference of assign the value of the property of the first mode and the second mode?
#interface Prueba : NSObject{
CustomeClass *_cclass;
}
#property(nonatomic, retain)CustomeClass *cclass;
#end
#implementation Prueba
#synthesize cclass = _cclass
- (void)config{
// 1 This
self.cclass = [[CustomeClass alloc] init];
// 2 This or
CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
}
#end
:/
Your first example gives you an object with a retain count of two (wrong), whereas your second example gives you an object with retain count of one (right). The second method is preferred in non-ARC projects. Alternatively, you could also do either set the ivar yourself (which I don't like because you're not using the setter):
_cclass = [[CustomeClass alloc] init];
or use the setter as your examples do, but do an autorelease (which I don't like because you shouldn't defer your releases unless you have to):
self.cclass = [[[CustomeClass alloc] init] autorelease];
In your non-ARC project, your original second example is best (using a pointer, using your property's setter, then releasing your pointer), because for KVO you want to get in the habit of using the setter:
CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
There is no difference in the result except that in the second method you create an additional pointer. In both versions self.cclass will hold your object just fine.
The problem is that when you only release the object in your second mode, in the first mode you'll have a memory leak. Since the retainCount of an object is +1 when you allocate it, you assign a +1 object through your setter. This means, that you actually bump up the retainCount again. Now if you don't release the object after assigning it to your property, once it gets released from there the retainCount will only be reduced by 1. Thus letting an object with a retainCount of +1 float around in the memory, lost forever.
But because you are already asking about a better version, I want to introduce lazy instantiation to you. What you can do, is that you overwrite the getter method of the property in question and check if it has been allocated yet. If not, you allocate it inside your getter method and then return it. It would look something like this:
- (CustomeClass*) cclass
{
if(!_cclass)
{
_cclass = [[CustomeClass alloc] init];
}
return _cclass;
}
With this method you assign a +1 retained object to an internal variable, thus bypassing the setter and not increasing the retainCount. Also it's memory friendly, because you object only gets instantiated when you really need it. Now when you set your property to nil or some new object, the old object will be properly deallocated.
EDIT:
In response to Robert Ryan's comment I want to add the following:
This does not break KVO, or interfere with the assigned qualifies for your properties. If your property is marked as assign or weak, then lazy instantiation doesn't really make sense. If it's marked as retain or strong this way of instantiating an object is perfectly fine, especially when it is a property which you would assign anyway inside a config method.
Regarding KVO: the value which is assigned inside the getter can be seen as the initial/default value, so KVO still works. It will trigger when you use the setter to assign something else to the property. You wouldn't want KVO to trigger because of a default value, would you?

Objective-C method to nullify object

i have some trouble writing a method in Objective-C to make an object nil. Here is some example :
#interface testA : NSObject
{
NSString *a;
}
#property (nonatomic, retain) NSString *a;
+(testA*)initWithA:(NSString *)aString;
-(void)displayA;
-(void)nillify;
#end
#implementation testA
#synthesize a;
+(testA*)initWithA:(NSString *)aString{
testA *tst=[[testA alloc] init];
tst.a=aString;
return [tst autorelease];
}
-(void)displayA{
NSLog(#"%#",self.a);
}
-(void)nillify{
self=nil;
}
- (void)dealloc {
[a release];
[super dealloc];
}
#end
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
testA *test=[testA initWithA:#"some test"];
[test displayA];
test=nil;
//[test nillify];
NSLog(#"after setting to nil");
[test displayA];
[pool release];
return 0;
}
Apparently , when I set test object to nil and then call some method on it nothing happens , but if i call nillify instead of directly setting it to nil , displayA method works normally like test object is still there. Is there a workaround for nillify method to function properly ?
Your help is much appreciated !
You can't actually do something like this, because setting 'self' to nil only has any effect within the scope of that method (in your case, 'nilify'). You don't have any actual way to effect the values of pointers located on other parts of the stack or in random places in the heap, for example.
Basically any code that holds a reference to some object is responsible for maintaining and clearing those references itself. If you have some use case where random sections of code may need references to "live" objects of some kind, but where you'd want those object references to go away in response to some external event (maybe a user tracking system or something), you could do something with notifications, but the various modules tracking those "live" objects would still be responsible for listening for notifications and cleaning up references when they received them.
The 'nilify' thing, however, can't possibly work.
You cannot do what you're trying to do. self is just a local reference to an object that actually exists elsewhere. Setting it to nil doesn't mean anything. An object doesn't, in general, own itself, and it certainly doesn't control other objects' references to it. It's up to the owning objects to manage its lifetime.
There are a few things wrong with your code.
First, by convention, class names start with an uppercase letter. Please stick to these naming conventions as it will make it harder for other developers to work with your code (and even confuse you).
Next, your initWithName:... According to the naming conventions, a method with init in its name should be an instance method, not a class method. So either name it newWithName: or turn it into an instance method like this:
-(testA*)initWithA:(NSString *)aString{
self = [super init];
if (!self) return nil;
tst.a=aString;
return self;
}
If you keep it as class method (and name it newWithName:) you should not return a autoreleased object since according to the naming conventions method that start with init... or new... return a retained object. If you do not follow these conventions, the static analyzer will give you "false" warnings and it will become useless for you.
Now for the reason your nillify doesn't work: the self is in fact an argument to a method. Under the hood, your nillify method actually has two arguments that you do not see: the self pointer and the selector pointer. This means, self is actually a variable on the stack. And if you overwrite it, you only overwrite that stack variable but that doesn't influence your test variable which is somewhere else.
As an example, consider a method - (void)foo:(NSString *)bar;. The compiler turns it into the equivalent of the C function (void) foo(id self, SEL _cmd, NSString *bar).

#property retain - iPhone

I am newbie to iPhone programming. I have the following doubt which is stopping me to go ahead. Please consider the following code:
---------.h------
#interface myClass: UIViewController
{
UIImage *temp;
}
#property (nonatomic, retain) UIImage *temp;
---------.m------
#interface myClass
#synthesize temp;
-(void) dealloc
{
[temp release];
[super dealloc];
}
The above is the only program code. Thats it ... nothing else. Do I need to declare [temp release] in dealloc method even though I am not using the property accessor method in my program at all. What if I don't declare [temp release] in dealloc. Will that create memory leak as I am releasing something which I haven't retained as I am not calling property accessor method.
Also when i print retain count for temp why does it show 0 even though it is getting retained in #property.
Thanks in advance
If no value has ever been assigned to (an instance of) myClass.temp, then there won't be a leak. But you should release it in your dealloc.
#property is only a declaration that instance of myClass will have this property. You need to assign it a value before that value gets retained.
myClass *instance = [[myClass alloc] init];
// instance will now retain the value passed in
// and is therefore responsible for releasing it
instance.temp = [UIImage imageNamed:#"whatever"];
// if instance is not retained anywhere else,
// its dealloc will be called
[instance release];
On a sidenote, you should give your classes names that start with an uppercase
letter, i.e. MyClass. Not required, but makes things clearer.
You can also use self.temp = nil; in your dealloc You're sorta not supposed but it kinda works better and looks cleaner. It's a bit of an iffy subject...
What you are doing is correct. Scroll to the "dealloc" section of this Apple Doc: Declared Properties
Soon, however, these properties will be cleaned up automatically when you synthesize them (in the next Cocoa update) -- that being said, a convention I have personally began to follow so that my code works in the future is setting self.temp = nil; in dealloc instead of sending a release message (read the apple doc i posted, it explains this). The accessor method created at runtime releases the object first, so for me and quite a few other devs, this is a better/safer way of cleaning up declared properties in our dealloc.
Your code is correct.
The general rule is that, for all variables you declare in #interface, you must clean them up in -dealloc. Some variables will need to be released, others just need to be nil'd out, depending on how you've declared the #property.
In your example above, temp may never have been given a value explicitly by you, but the ObjC runtime will have initialized the value of temp to nil when an instance of your class gets allocated.
Sending a -release to a nil object is generally not a problem, so the [temp release] is fine. It's a no-op. When temp has a non-nil value in -dealloc, the [temp release] gets to do its job of freeing up the memory.
If you need temp to have a non-nil value on creation, you'll need to implement the -init method and make sure it gets some value. While your class is legitimate & functional without an -init method, you really should get in the habit including one in every custom class you design.
You'll need the default initializer at a minimum: -init. You may also want to design a more detailed initializer that could be used to give your temp ivar an a value, like -initWithImage:
Here's what you should also be including in your class:
#implementation MyClass
...
- (id) init {
self = [super init];
if (self != nil) {
// The minimal default initializer.
// temp will already have a value of nil, so you don't need necessarily
// need to do anything more, unless temp needs a real value on initialization.
}
return self;
}
- (void) dealloc {
...
}
#end
To implement a more detailed initializer, which would be known as the designated initializer, you would to something like this:
#implementation MyClass
...
- (id) initWithImage:(UIImage *)newImage {
self = [super init];
if (self != nil) {
temp = [newImage retain];
}
return self;
}
// Implement the default initializer using your more detailed initializer.
- (id) init {
// In this default initializer, every new instance comes with a temp image!
return [self initWithImage:[UIImage imageNamed:#"foobar"]];
}
- (void) dealloc {
...
}
#end
Here, the designated initializer -initWithImage: is the authoritative initializer. All other initializers, including -init, get implemented using -initWithImage:.
You get to exercise a lot of discretion over whether to implement any initializers beyond the minimal default initializer. Maybe -init is good enough for your purposes. That's fine. Sometimes more detailed initializers make using the class more convenient. Experience (and the Force) will be your guide.
Note that I didn't use the generated property accessor in either initializer method. If you aren't required by circumstances, you should generally avoid using property accessors in -init methods and -dealloc, primarily because of potential pain-in-the-ass issues with side effects of automatic key-value coding notifications.
The initializer and dealloc methods play a special role in a class. As the class designer, it is your responsibility to set and clean up instance variables in these methods. A good rule of thumb is to leave the use of synthesized property accessors for the callers of your class, and the implementation of other methods in the class.
When doing initialization of an instance, or deallocation, you can and should touch the ivars directly. They're yours. You declared them, so you can handle them directly. When implementing other methods in your class, you generally should use the property accessors.
JeremyP's link to the Cocoa Conceptual documentation on objects is a good one. You should definitely read the sections on Objects, and periodically re-read it as you gain more experience writing custom classes of your own. Eventually, it will all start making sense.

IPhone memory management

I am a bit lost with the memory management. I've read that you should release whenever you alloc. But when you get an instance without the alloc, you shouldnt release.
What about this situation, just need to know If I was coding correctly. I'm still new on iphone dev.
I have a class CustomerRepository it has a method
- (MSMutableArray *) GetAllCustomers() {
MSMutableArray *customers = [[MSMutableArray alloc] init];
Customer *cust1 = [[Customer alloc] init];
cust1.name = #"John";
Customer *cust2 = [[Customer alloc] init];
cust2.name = #"Tony";
[customers addOjbect:cust1];
[customers addOjbect:cust2];
[cust1 release];
[cust2 release];
return customers;
}
Then I have a UIViewController
- (void) LoadCustomers() {
CustomerRepository *repo = [[CustomerRepository alloc] init];
MSMutableArray *customers = [repo GetAllCustomers];
// Iterate through all customers and do something
[repo release];
}
So in this scenario ... the MSMutableArray will never be release? Where should it be release?
If you alloc an object in a function that you need to return from the function then you can't release it inside the function. The correct way to do this is to autorelease the object.
MSMutableArray *customers = [[MSMutableArray alloc] init];
// ..... do work
return [customers autorelease];
This is the approach taken by the connivence constructors like
[NSString stringWithString:#"test"];
This method will return you an autoreleased string so that you don't need to release it.
And if you don't do this then you should name your function accordingly that the caller knows that it owns the returned object and thus needed to be released. These are conventions, not a rule imposed by the compiler or run-time environment but following convention is extremely important, specially when multiple people are involved in the project.
Whenever you create and return an object from a method or function, that object should be autoreleased. The exceptions are when the method starts with Create or New (or Alloc, obviously), or when the object is being cached within the method.
The other answers which suggest releasing it in LoadCustomers are incorrect, because GetAllCustomers does not imply a transfer of ownership like CreateCustomersArray or NewCustomersArray would. However, you can't release the object in GetAllCustomers either because then the object would be deallocated before returning it. The solution is autorelease.
The customers array should be released after you are done iterating it. You delegated the creation of the array to your repo object but your LoadCustomers method owns the array.
Another approach would be to have your CustomerRepository expose an allCustomers property. You could lazily initialize the array in your getter and then release the array when the CustomerRepository is released. That would keep your calls to alloc and release in the same object.
it should be released in your view controller, LoadCustomers() since you are allocing it in the method you are calling, it is still owned by YOU.

Initialize a class only once

I have a class that contains a few instance methods which need to be called from another class. I know how to do that -
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
[myTimeFormatter formatTime:time];
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I tried putting
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
"by itself", or not in any blocks, but when I compile, I get an "initializer element is not constant" error.
Any input is greatly appreciated!
You can use the singleton pattern. You can read more about it here.
Specifically, you'd do something like:
static TimeFormatter* gSharedTimeFormatter = nil;
#implementation TimeFormatter
+ (TimeFormatter*)sharedTimeFormatter {
if (!gSharedTimeFormatter) {
#synchronized(self) {
if (!gSharedTimeFormatter) {
gSharedTimeFormatter = [[TimeFormatter alloc] init];
}
}
}
return gSharedTimeFormatter;
}
...
#end
Notice that we check if the variable is null, and if it is, we take a lock, and check again. This way, we incur the locking cost only on the allocation path, which happens only once in the program. This pattern is known as double-checked locking.
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I think it's worth clarifying some OOP terminology here.
The reason you need to alloc and init TimeFormatter is because your methods are instance methods. Because they're instance methods, you need an instance, and that's what alloc and init provide. Then you call your methods on (send messages to) the instance ([myTimeFormatter formatTimeString:…]).
The advantage of allowing instances is that you can keep state and settings in each instance, in instance variables, and make the latter into publicly-visible properties. Then you can deliberately have multiple instances, each having its own settings configured by whatever's using that instance.
If you don't need that functionality, you don't need to make these instance methods. You can make them class methods or even C functions, and then you don't need a TimeFormatter instance. With class methods, you send messages directly to the class ([TimeFormatter formatTimeString:…]).
And if you do want settings shared among all instances (and you don't have any state to keep), then you're right that you can just have one instance—a singleton.
The reason for that parenthesis is that shared state is bad, especially if two threads may use the time formatter concurrently. (For that matter, you could say that about settings, too. What if one thread wants seconds and the other doesn't? What if one wants 24-hour and the other wants 12-hour?) Better to have each thread use its own time formatter, so that they don't get tripped up by each other's state.
(BTW, if TimeFormatter is the actual name of your class: You are aware of NSDateFormatter, right? It does let you only format/parse the time.)
Here's a detail example of a sharedMethod. Credit goes here
#implementation SearchData
#synthesize searchDict;
#synthesize searchArray;
- (id)init {
if (self = [super init]) {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"searches.plist"];
searchDict = [[NSDictionary alloc] initWithContentsOfFile:finalPath];
searchArray = [[searchDict allKeys] retain];
}
return self;
}
- (void)dealloc {
[searchDict release];
[searchArray release];
[super dealloc];
}
static SearchData *sharedSingleton = NULL;
+ (SearchData *)sharedSearchData {
#synchronized(self) {
if (sharedSingleton == NULL)
sharedSingleton = [[self alloc] init];
}
return(sharedSingleton);
}
#end
A very nice, and easy, way to setup a Singleton is to use Matt Gallager's SYNTHESIZE_SINGLETON_FOR_CLASS.
It sounds like you want to make TimeFormatter a singleton, where only one instance can be created. Objective-C doesn't make this super easy, but basically you can expose a static method that returns a pointer to TimeFormatter. This pointer will be allocated and initialized the first time in, and every time after that same pointer can be used. This question has some examples of creating a singleton in Objective-C.
You are trying to declare your variable outside the class? If to do it the way you want to do it you gotta declare it as static so
static TimeFormatter *myFormatter=...
From the name of the class though i dont see why you would wnat to keep one instance of your class... you can also do this with a singleton as described above, that is if you want to keep one instance of your class for the app as a whole.