Retain on NSManagedObject crashes - objective-c

I'm experiencing a weird problem when trying to use an NSManagedObject subclass. I've got code that looks something like this:
[self.navigationController popViewControllerAnimated:NO];
MyController *myController = [[MyController alloc] init];
myController.managedObject = managedObject;
Pretty simple right? But for some reason it crashes in the synthesized function for setting "managedObject". I tried replacing the function with something like this:
- (void) SetManagedObject:(NSManagedObjectSubClass*) obj
{
if ( managedObject )
[managedObject release];
managedObject = obj;
--> [managedObject retain];
}
And that crashes on the retain call... I'm stumped and don't know where to start debugging this.

There are several problems with your code:
If you provide a custom setter, your property is not a synthesized property (remove SetManagedObject: and use the #synthesized directive instead)
Your custom setter is releasing the object before it retains it. So managedObject might have been freed when you send the retain message (That's the crasher)
SetManagedObject: has the wrong case. Use setManagedObject: if you decide to provide a custom setter.
Don't use NS as prefix for your custom subclasses (NS is used by Apple).
I'd use a synthesized property. Remove your setter code, declare #property(retain) XYManagedObjectSubClass managedObject; in your .h file and use #synthesize in the implementation.

Related

Does Objective-C auto generate setter and getter?

I am calling a method from other class, as below
#property (nonatomic,strong) CalculatorModel *calculatorModel;
double result = [self.calculatorModel result:operator];
however this method doesn't received the message from the caller. Until I wrote the getter my self
- (CalculatorModel*)calculatorModel {
if (!_calculatorModel) _calculatorModel = [[CalculatorModel alloc]init ];
return _calculatorModel;
}
and it works. why, I remember once you did #property, the Objective-C will generate setter and getter automatically. Am I wrong?
Thanks
updated:
Does Objective-C auto generate setter and getter?
Well, rather the compiler, but yes, recent versions of Clang have this feature. You don't need to manually synthesize properties anymore.
You are right. However you still have to initialize the property by using [[Class alloc] init]. Like we set the property for NSMutableArray, #property (nonatomic, strong) NSMutableArray *anArray; and before you are using anArray you have to init it as _anArray = [[NSMutableArray alloc] initWithCapacity:10];
the - (CalculatorModel*)calculatorModel method is called Lazy instantiation, which will take over the [[Class alloc] init] job before calling, this will give help on both performance and memory control.
Seems like You don't need to manually synthesize properties anymore from xCode4.5.The IDE will help you do it.But terrible thing is if you open your project on xCode4.3 or xCode4.4, it will not work,lots of warning will appear,then you should add the code by yourself .

Message sent to deallocated instance using ARC

I wouldn't normally ask questions like this, but I really cant get my head around it. I have a class 'GetTableInfoFromDatabase', which connects to my database and downloads some JSON. This works great from the first screen of my tab-bar application. I can call the getNewData method as much as I want to effectively refresh the data.
My problem arises when I try and create an instance of the 'GetTableInfoFromDatabase' class and call the very same method from another tab. I get the following error:
*** -[GetTableInfoFromDatabase respondsToSelector:]: message sent to deallocated instance 0x1d89e830
The funny thing is, i'm using ARC. The culprit (in my opinion) is ASIHTTPRequest. I have had to enable -fno-objc-arc to get the project to compile. This library is used in the GetTableInfoFromDatabase class.
Here is the class:
- (void) getEventDataWithSender:(id)sender{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:#"-------.com/getdata.php"]];
[request setDelegate:self];
NSLog(#"Running!");
[request startAsynchronous];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = appDelegate.managedObjectContext;
}
And this is how i'm calling it:
GetTableInfoFromDatabase *getInfo = [[GetTableInfoFromDatabase alloc]init];
[getInfo getEventDataWithSender:self];
I've even changed the order of the tabs around, so the first tab to be displayed purely just calls this method, nothing else. Not even before the 'GetTableInfoFromDatabase' has been previously initialised by the class that initialised it first last time. Still crashes.
Has anyone got any ideas? This is so frustrating!
You need to assign that variable to a property if you plan on exposing it to other view controllers. ARC will, and should, immediately deallocate getInfo after this code executes:
GetTableInfoFromDatabase *getInfo = [[GetTableInfoFromDatabase alloc]init];
[getInfo getEventDataWithSender:self];
So if this line is included in say viewDidLoad: and nothing else refers to getInfo in that method, it will be immediately released. Why, because you haven't told the compiler that it should retain it.
So in the view controller that's exposing this class, on whatever tab it might be a child of... you would do something like this:
ViewController.h
#class GetTableInfoFromDatabase; // forward declaration
#interface ViewController : UIViewController
#property (strong, nonatomic) GetTableInfoFromDatabase *getInfo;
ViewController.m
#implementation ViewController
#synthesize getInfo = _getInfo;
- (void) viewDidLoad {
[super viewDidLoad];
self.getInfo = [[GetTableInfoFromDatabase alloc]init]; // assign your value to a property
[self.getInfo getEventDataWithSender:self];
}
So when you declare your property as Strong in your header, it will maintain a strong reference to it. #Synthesize getInfo = _getInfo means that it will create a getter and setter for self.getInfo around an instance variable named _getInfo. If you didn't want to expose it as a property, just an instance variable... you could do this:
ViewController.h
#class GetTableInfoFromDatabase; // forward declaration
#interface ViewController : UIViewController {
GetTableInfoFromDatabase _getInfo;
}
ViewController.m
#implementation ViewController
- (void) viewDidLoad {
[super viewDidLoad];
_getInfo = [[GetTableInfoFromDatabase alloc]init]; // assign your value to a property
[_getInfo getEventDataWithSender:self];
}
By default, the compiler will maintain a strong reference to that instance variable unless otherwise specified. You can have weak references as well, and all of those options are pretty well documented. So with ARC, or plain old memory management in general, you need to make an instance variable or property if you want it to hang around for a while.
Honestly... all ARC is doing for you is keeping you from having to call retain and release. Before ARC, setting that property would look like this:
GetTableInfoFromDatabase getInfo = [[GetTableInfoFromDatabase alloc]init];
self.getInfo = getInfo;
[getInfo release];
Now with ARC, the compiler just writes that code for you ;) Hope this helps!
[self.getInfo getEventDataWithSender:self];
Your GetTableInfoFromDatabase object is being deallocated, almost certainly because nothing is holding a strong reference to it. In your code above, getInfo is a local variable, so I would expect it to be released very shortly after this code, unless you are storing it somewhere.
Almost certainly, your dealloc in GetTableInfoFromDatabase does not clear the request's delegate. You should be holding the request in an ivar of GetTableInfoFromDatabase so that it can remove itself as delegate when it is deallocated.
As a side note, avoid prefacing ObjC methods with get. That has a special meaning in KVC (it means that the first parameter is supposed to be updated by reference). Typically the kind of method you have here would be prefaced with "fetch."

Strange memory only when using copy

I have a class named SomeClass. in its init I have a lot of lines like:
SomeProperty_ = [[SomeObject alloc] initWithSomething];
While the properties are declared as
#property(retain) SomeObject *SomeProperty;
and defined as
#synthesize SomeProperty = SomeProperty_;
When I allocate objects of SomeClass and later release them, everything works fine and there are no memory leaks. However, when I copy an object of SomeClass and later release it, all the lines like
SomeProperty_ = [[SomeObject alloc] initWithSomething];
are marked as a memory leak in Instruments. this is also correct as I get memory warning and later crash if I use this a lot.
However if I make a method named dealloc like:
-(void) dealloc
{
self.SomeProperty = nil;
[super dealloc];
}
Everything is fine with copies as well and no memory warning or leaks.
I think this is because of my copy implementation:
-(id)copy
{
SomeClass *copy = [[SomeClass alloc] init];
copy.SomeProperty.somePOD = self.SomeProperty.somePOD;
return copy;
}
Where is the problem? what can I do to resolve it without the custom dealloc?
The first things I can think of is:
How your somePOD is set as far as #property(???)
And when you say :
"However, when I copy an object of SomeClass and later release it, all the lines like
SomeProperty_ = [[SomeObject alloc] initWithSomething];
are marked as a memory leak in Instruments. this is also correct as I get memory warning and later crash if I use this a lot."
You are referring to call made in your init method?
Because if your not, you are bypassing a setter and the object that was in that variable before this assignment will leak.
You must either use a custom dealloc method or start using Automatic Reference Counting (ARC).
When you call [[SomeObject alloc] init...], you get ownership of the new object, so you must release the object when you are done with it. Setting self.SomeProperty to nil does the release because you declare the property with the retain attribute.
You do this in your dealloc method if you want to own the SomeObject object until your SomeClass object dies. If you use ARC, it will generate the dealloc method for you.

property and synthesize : in this code, without "self"?

i have a simple question :
if we don't use here the dataController property in another class in the project, we don't really need to use the "#property" and synthesize and we could have just done a simple "=" operation with dataController = controller, like in the second chunk of code? :
DataController *controller = [[DataController alloc] init];
self.dataController = controller;
[controller release];
rootViewController.dataController = dataController;
Second one :
DataController *controller = [[DataController alloc] init];
dataController = controller;
So if we don't need a property outside the class, we could just do it this way?
Thanks
You are correct, if dataController is a retaining property.
If you are just using it once, there is not much to gain with a property. If you change its value often (i.e. assign a different DataController) then even a private property can make sense just to make the memory management easier.
If dataController is not gonna be used in any other class then you don't need to synthesize it. Then Yes, you could just create it inside that class.
(Of course, if your dataController in your rootViewController also need a reference to it, then you need to handle that as well)
Yes, the second example works fine, provided dataController is declared as an iVar and not just a local variable to the method where it is used - but you probably are aware of that.
In both examples you of course need to release the stored value in the dealloc method.

Objective-C 2.0; Assigning a Property; Leaking Memory?

I'm still learning about Objective-C memory management. I'm trying to implement several simple classes in an example program that I'm building.
As an example, say I have the following class definition:
#import <UIKit/UIKit.h>
#interface customViewController : UIViewController
{
customObject *myCustomObject;
}
#property (retain) customObject *myCustomObject;
- (void)replaceCustomObject:(customObject *)newObject;
#end
For the property, I use the standard synthesize keyword...
#synthesize myCustomObject;
Then please assume that in the instance of customViewController the myCustomObject is already set with a valid value and is in use. Then the method replaceCustomObject is defined as:
- (void)replaceCustomObject:(customObject *)newObject
{
//Does this cause a memory leak because I just assign over
//the existing property?
self.myCustomObject = newObject;
}
As the comment asks, does this leak memory? Or is this the valid way to replace a previous object with a new object?
Thank you,
Frank
As others have mentioned, your code is perfectly valid and won't leak memory when assigning to the property.
If you have forgotten to implement a proper dealloc method, the last object assigned will be leaked when your customViewController is destroyed. A proper dealloc implementation would look like so:
- (void)dealloc
{
self.myCustomObject = nil;
[super dealloc];
}
That's perfectly valid, and does not leak memory. The synthesized accessors manage retain counts correctly.
(As an aside, you don't need that replaceCustomObject: method; since your property is readwrite by default, you have an auto-generated setCustomObject: method that clients of your class can use, and which follows the normal Cocoa naming conventions.)
According to this, if you use (retain) in your declaration, the synthesized method will release the old value first, then retain the new one:
if (property != newValue) {
[property release];
property = [newValue retain];
}
the property accessor syntax
self.x = y;
has the same effect as calling the setter method explicitly:
[self setX:y];
The accessor method will do whatever it has been written to do. In your case, for a #property(retain) property that has been #synthesized, the accessor will release the old object and retain the new one.
So, calling the setter, whether explicitly or through the '.' syntax, will do the right thing - including the right memory management.
So in short: no, this will not leak memory.