I am developing a iPhone app using core data that has a to-many relationship and in one of my classes i have a NSSet property. I am creating an NSSet, assigning to this property and then releasing the object, the problem is a i am getting an EXC_BAD_ACCESS.
NSSet *feedSet = [[NSSet alloc] initWithSet:mutableFeedSet];
Signature *signature = (Signature *) [NSEntityDescription insertNewObjectForEntityForName:#"Signature" inManagedObjectContext:context];
signature.site = [feed objectForKey:#"site"];
signature.url = [feed objectForKey:#"url"];
signature.feedList = feedSet;
NSLog(#"%d", [feedSet retainCount]);
[context save:&error];
[feedArray release];
[mutableFeedSet release];
[formatter release];
[feedSet release];
when i printed the feedSet retain count i realized that the signature.feedList = feedSet; wasn't retaining the object, so i removed the [feedSet release]; and the i got the problem solved... The question is. Why when a assign the feedSet to the feedList property it didn't retained the object?
Thanks!
Probably Signature is your class, and you have property feedList. If you want to retain the object you have to declare it like this
#property(nonatomic, retain) NSSet* feedList;
If signature.feedList = feedSet; isn't retaining it, it is because the property is defined as assign (not copy or retain). Or, if not synthesized, your setter implementation is hosed.
If that isn't the case, you have a stray autorelease or release somewhere.
Note that retainCount is not a very good indicator here; autorelease will not cause the retain count to decrement immediately.
Aha! You said #dynamic feedList; Is this a managed object subclass?
#dynamic does not provide method implementations. So, either you have implemented setFeedList: or you are subclassing NSManagedObject (or their is a superclass involved).
Which is it?
And post the crash backtrace, too, please.
Related
This is a general question about memory leaks. Let's say you have the following code:
NSObject *object = [[NSObject alloc] init];
NSArray *array = [[NSArray arrayWithObjects:object] retain];
[object release];
[array release];
Is that a memory leak? Like, would I have to enumerate through all the objects in the array and release them one by one before releasing the entire array? Or does NSArray's dealloc method release all of the objects within it as well as releasing the array itself?
Thanks for any help! Memory management can be quite tricky.
Here are some rules:
whenever you call alloc, you must eventually call release
for every retain, you should have a release
When you add an object to an array, it calls retain on that object. If you don't release your pointer to that object, it will be a leak. When you release the array, it will call release on all of the objects that it holds, since it called retain previously.
NSObject *object = [[NSObject alloc] init];
// object has retain count 1
NSArray *array = [[NSArray arrayWithObjects:object] retain];
// array is autoreleased but has a retain, so has retain count 1
// object now has retain count 2
[object release];
// object now has retain count 1
[array release];
// array is now set to autorelease,
// once that happens, array will be sent dealloc and object will be released
Hence no memory leaks.
When inserting an object into an array with a property is there any reason to invoke the getter/setter with self? i.e.
[self.myArray insertObject: myObject];
Or can I just use:
[myArray insertObject: myObject];
the gist would be:
.h
#interface ArrayViewController : UIViewController <UITextFieldDelegate>
{
NSMutableArray *myArray;
int itemNumber;
}
#property (nonatomic, retain) NSMutableArray *myArray;
#end
.m
- (IBAction)createMyArray
{
self.myArray = [[NSMutableArray alloc] initWithObjects: nil];
}
-(IBAction) addItemToMyArray
{
NSString *myString = [[NSString alloc] initWithFormat:#"item %d",itemNumber];
[myArray addObject: myString];
//[self.myArray addObject: myString]; //Or should I use self?
[myString release];
NSLog(#"myArray = %#", myArray);
itemNumber++;
}
//- (void)dealloc etc. not shown
Conceptually, it doesn't matter, so long as your getter method only returns the existing field value and doesn't, eg, do some "just in time" allocation or some such.
However, it's good practice to come up with a policy (personal or group) that you stick with, so that the caveats of that policy become second nature. Constantly switching styles results in sloppy, buggy code.
I tend to always use the self. for properties, just to remind myself that they are, in fact, properties, and to make it less likely that I'll accidentally set the value without using the property notation.
Either will work but you need to be aware of what you are doing. Using self. will invoke the setter/getter methods while the other will just access the variable directly. Using the variable directly, while perfectly valid, is discouraged outside of the initializer and dealloc method. The reason is you are losing out on the benefits of the property, especially setting using self. because it will properly assign/copy/retain the value for you correctly. Another reason not use property variables directly is because of atomicity but in your case you declared it as nonatomic.
Both of those are fine. It's mostly a stylistic choice. Using self.myArray will result in a call to the getter [self myArray].
When using alloc/init you should not set the returned value to a property, as these will retain twice:
self.myArray = [[NSMutableArray alloc] initWithObjects: nil];
use
myArray = [[NSMutableArray alloc] initWithObjects: nil];
or
self.myArray = [NSMutableArray array];
for the initialization.
The insert operations are equivalent though.
I typically skip the getter because I rarely find it valuable and it clutters up the readability of the code a bit. However, I tend to use the setter because I find it easier to allow the auto-generated setter methods to handle the retain/release semantics
In your case it's not an obligation to use self.myArray but for this case belloaw it will be an obligation:
-(void) addItemToMyArray:(NSAarray *)myArray
{
NSString *myString = [[NSString alloc] initWithFormat:#"item %d",itemNumber];
[self.myArray addObject: myString];
[myString release];
NSLog(#"myArray = %#", self.myArray);
itemNumber++;
}
to difference between the class attribut and the function argument.
In my app I want to copy a custom class from one array to another array. So I implemented copyWithZone for this class. Xcode analyze warning me that every line with [alloc] or [copy] are leaking memory. How can I tell if it's really leaking or it's the copied instance that I need?
#implementation MyClass
- (id)copyWithZone:(NSZone *)zone {
MyClass *copy = [[MyClass allocWithZone:zone] init];
if (copy){
copy.uniqueId = [uniqueId copy];
}
return copy;
}
Is your uniqueId property declared as a retain property? If so, this line is leaking:
copy.uniqueId = [uniqueId copy];
Change it to:
copy.uniqueId = [[uniqueId copy] autorelease];
It's not quite right.
The line
copy.uniqueId = [uniqueId copy];
should probably be
copy.uniqueId = self.uniqueId;
That way you'll get correct semantics for the property no matter if it is declared as copy, retain or assign.
Also, I wouldn't bother with the test for copy != nil. Sending setUniqueId: to nil is a no op.
Edit
By the way
copy.uniqueId = [uniqueId copy];
leaks if the property is retain or copy since [uniqueId copy] gives you an object you own and you don't release or autorelease it before the end of the scope.
I am implementing a copyWithZone method for a custom A class, in which a NSNumber pointer was declared as (retain) property
#class A <NSCopying>
{
NSNumber *num;
}
#property (nonatomic, retain) NSNumber *num; // synthesized in .m file
-(id) copyWithZone:(NSZone*) zone {
A *new = [[A alloc] init];
new.num = [num copy];
return new;
}
When I debug, I always find new.num is the same address as the self.num.
Even if I use
new.num = [NSNumber numberWithFloat: [num floatValue]];
I still get the same address. In the end, I have to use
new.num = [[[NSNumber alloc] initWithFloat:[num floatValue]] autorelease]
to achieve the result I want. I am just wondering why NSNumber complies to but does not return a new memory address when copied?
Thanks
Leo
NSNumber is immutable. Making a copy is pointless and, thus, the frameworks just return self when copy is invoked.
If a class implements NSCopying, you should mark the property as copy (not retain). -copy on immutable classes (NSString) will simply return a reference to the object (w/a bumped retain count). If passed a mutable instance, it'll be copied to an immutable instance. This prevents an external party from changing the state behind your object's back.
Not only is NSNumber immutable - for low values it as also a Flyweight.
NSNumber isn't mutable, so there is no need to force physical copying.
You should be using [[A alloc] initWithZone:zone] when implementing the NSCopying protocol.
As others have stated though, NSNumber is immutable and so returns the same object.
Hey all. I know this question's been asked but I still don't have a clear picture of memory management in Objective-C. I feel like I have a pretty good grasp of it, but I'd still like some correct answers for the following code. I have a series of examples that I'd love for someone(s) to clarify.
Setting a value for an instance variable:
Say I have an NSMutableArray variable. In my class, when I initialize it, do I need to call a retain on it?
Do I do
fooArray = [[[NSMutableArray alloc] init] retain];
or
fooArray = [[NSMutableArray alloc] init];
Does doing [[NSMutableArray alloc] init] already set the retain count to 1, so I wouldn't need to call retain on it? On the other hand, if I called a method that I know returns an autoreleased object, I would for sure have to call retain on it, right? Like so:
fooString = [[NSString stringWithFormat:#"%d items", someInt] retain];
Properties:
I ask about the retain because I'm a bit confused about how #property's automatic setter works.
If I had set fooArray to be a #property with retain set, Objective-C will automatically create the following setter, right?
- (void)setFooArray:(NSMutableArray *)anArray {
[fooArray release];
fooArray = [anArray retain];
}
So, if I had code like this: self.fooArray = [[NSMutableArray alloc] init]; (which I believe is valid code), Objective-C creates a setter method that calls retain on the value assigned to fooArray. In this case, will the retain count actually be 2?
Correct way of setting a value of a property:
I know there are questions on this and (possibly) debates, but which is the right way to set a #property?
This?
self.fooArray = [[NSMutableArray alloc] init];
Or this?
NSMutableArray *anArray = [[NSMutableArray alloc] init];
self.fooArray = anArray;
[anArray release];
I'd love to get some clarification on these examples. Thanks!
According to Apple's Object Ownership Policy, any method that begins with the words alloc or new, or contains copy is owned by the caller.
To obtain ownership of an object, you must retain it.
So, in your first example, the retain is unnecessary because you already own the object.
The correct way to do this:
fooArray = [[NSMutableArray alloc] init];
Since autoreleased objects are owned by the current autorelease pool, you must call retain on them to gain ownership of them, so this example is correct:
fooString = [[NSString stringWithFormat:#"%d items", someInt] retain];
This would work fine as well:
self.fooString = [NSString stringWithFormat:#"%d items", someInt]; //retained by property setter
And for your last example using the property setter, this would be the correct way to do it:
NSMutableArray *anArray = [[NSMutableArray alloc] init];
self.fooArray = anArray;
[anArray release];
Instead of having to do the above, I'd suggest the following solution:
self.fooArray = [NSMutableArray arrayWithCapacity:10];
arrayWithCapacity: will return an autoreleased NSMutableArray, which is the retain-ed by the property setter method. :)
Ideally you would want to use the accessors whenever possible, especially when dealing with objects as they help avoid many memory issues. So even for instance variables, you should do:
self.fooArray = ...;
instead of
fooArray = ...;
The reason why you should declare properties for object instance variables is because the memory management is slightly more complicated, and recreating it by hand each time is tricky. The correct setter for a nonatomic, retained property would look like:
- (void)setFoo:(NSArray *)aFoo {
if (foo == aFoo) {
return;
}
NSArray *oldFoo = foo;
foo = [aFoo retain];
[oldFoo release];
}
You are right about the instance variable having a retain count of 2 when you do something like this (assuming foo is retained):
self.foo = [[NSMutableArray alloc] init];
The first retain count is coming from alloc, and the second one from your synthesized setter. Any of these should work:
// longer, explicit version, releases immediately (more efficient)
NSMutableArray *aFoo = [[NSMutableArray alloc] init];
self.foo = aFoo;
[aFoo release];
// autoreleased, not so bad unless you're a memory management freak
self.foo = [[[NSMutableArray alloc] init] autorelease];
// an even shorter version of the above
self.foo = [NSMutableArray array];
To create private properties, you can declare them as a class extension in the .m implementation file. To give an example, consider a simple Person object, which has a name, and a boolean property didSave which simply indicates whether the object has been saved to some database or not. Since we don't want to expose this to the outside world, but still keep the benefits of properties inside the implementation file, we can create the header file will all instance variables (public, private, protected) and only public properties:
// Person.h
#interface Person {
NSString *name;
#private
BOOL didSave;
}
#property (nonatomic, retain) NSString *name;
#end
But declare private properties inside the implementation:
// Person.m
// property is declared as a class extension, making it
// invisible to the outside world.
#interface Person ()
#property BOOL didSave;
#end
#implementation
// synthesize as normal
#synthesize name, didSave;
#end
First of all, with this line:
fooArray = [[NSMutableArray alloc] init];
fooArray will automatically have a retain count of 1.
Second, yes, it's 2. And your guess on the setter implementation is correct.
Third, the latter one is right