how to preserve array outside of method in objective c - iphone

After a ASIFormDataRequest , i create a temporary NSMutableArray *resultArray from the JSON then add it to a defined NSMutablearray *myData
-(void)viewDidLoad{
myData = [[NSMutableArray alloc] init];
//request that calls gotInfo method
}
-(void)gotInfo:(ASIFormDataRequest *)request{
NSString *responseString = [request responseString];
NSMutableArray *resultArray = [responseString yajl_JSON];
[myData addObject:resultArray];
}
-(IBAction)doSomethingWithData:(id)sender{
//something with myData
}
but when i try to call myData from outside of the gotInfo: method, i get bad access errors and when i inspect myData outside of the method, it shows a kern_protection_failure. So i'm guessing that outside of the method, the resultArray is obviously released, but it's also released from myData since the object inside myData is sharing the same memory location?
I also tried
-(void)gotInfo:(ASIFormDataRequest *)request{
NSString *responseString = [request responseString];
[myData addObject:[responseString yajl_JSON]];
}
How do I preserve myData??
in my header file:
#import <UIKit/UIKit.h>
#class ASIFormDataRequest;
#interface EventsTableController : UITableViewController <UITableViewDataSource>{
NSMutableArray *myData;
}
-(void)gotInfo:(ASIFormDataRequest *)request;
UPDATE:
so in the gbd, the myData is allocated as 0x5e96560 so i did
po 0x5e96560
and then i get the EXC_BAD_ACCESS with the reason being KERN_PROTECTION_FAILURE at address: 0x00000009
but if i do
po [[0x5e96560 objectAtIndex:0] objectForKey:#"key"]
then i get the value! whyyyyyy?

#property(nonatomic,retain) NSMutableArray *myData
and create the object
self.myData = [[NSMutableArray alloc] init];
and
// and i assume your resultArray is a mature NSMutableArray object
[self.myData addObject:resultArray];
The best way of using copy I can think of, is to always set NSString properties to "copy" instead of retain. That way you get more accurate readings from the Leaks instrument if you mess up and forget to release a string an object is holding onto. Other uses of copy need to be more carefully thought out.
NOTE : You are responsible to release myData after no use of that variable.

You dont really have any way to correctly access myData as you declare it as a member inside of EventsTableController, but you dont set the #property for it, and do not synthesize it either. By synthesizing it in your EventsTableController.m file you are telling xcode to generate the getter/setters you need to correctly touch myData, which is where your program seems to be failing. If you do this, this should solve your problem.
-Karoly

Except for the different name of your ivar (mienVar vs. myVar), I don't see a problem. Some other code must be releasing your ivar, or you are accessing it before viewDidLoad has the opportunity to actually create the array (I bet it is the latter).
I think you should put the code in viewDidLoad in your initialization method instead. Don't forget to release the array in dealloc.
You could, of course, also write your own myData getter method, doing lazy initialization, instead of creating it in the init method:
- (NSMutableArray *) myData
{
if (!myData)
myData = [[NSMutableArray alloc] init];
return myData;
}
Note that now, you should access self.myData if you want to use it.

I think the NSString yajl_JSON category can return an array or a dictionary - you might need to inspect the type of the result array on the line below as it may be an NSDictionary:
NSMutableArray *resultArray = [responseString yajl_JSON];
IF you are treating it as an array when its a dictionary that might be causing your problems.
(relevant code from the NSObject+YAJL category below)
YAJLDocument *document = [[YAJLDocument alloc] initWithData:data parserOptions:options error:error];
id root = [document.root retain];
[document release];
return [root autorelease];
(and in YAJLDocument object)
#interface YAJLDocument : NSObject <YAJLParserDelegate> {
(id root_; // NSArray or NSDictionary

Related

Self with an array and addObject

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.

iphone: unable to copy instance of an array to other array

Dont why this is happening I have a method getOutage which returns an array of managed objects
NSArray *fetchedOutages = [context executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Error in Core Data: %#", [error description]);
}
return fetchedOutages;
when I try to copy this array to listOutage (this is a property)
#property (nonatomic, retain) NSArray *listOutage
I tried to copy this array like this in didRowSelectMethod like this
if (listOutage) {
NSLog(#"Its there");
[listOutage release];
}
listOutage=[[NSArray alloc] initWithArray:[self getOutage]];
I tried various other methods but all of then are failing.
This getoutage method returns 5 objects five objects got copied in listOutage but when I try to access the listOutage elements they are displayed as 'out of scope'
Please help me to overcome this I have to pass this to next ViewController.
Thanks in advance
when there is a property, use 'self.property' instead of 'property' that way, when somebody else reads your code it is more obvious if you mean an ivar or a property.
if you use self.property, you do not need to write
if (listOutage) {
NSLog(#"Its there");
[listOutage release];
}
listOutage=[[NSArray alloc] initWithArray:[self getOutage]];
instead, just write
NSArray newListOutage=[[NSArray alloc] initWithArray:[self getOutage]];
self.listOutage = newListOutage;
[newListOutage release];
the release and retain will be handled by the get/set method generated by the #synthesize property.

iPhone memory management (with specific examples/questions)

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

Can't Figure Out How To Fix Memory Leaks on iPhone

I was running Leaks tool and discovered a massive leak in my Dictionary mutableDeepCopy but I can't figure out what's wrong with the code. Any suggestions?
#interface RootViewController : UIViewController{
NSDictionary *immutableDictionary;
NSMutableDictionary *mutableDictionary;
}
Here is the line of code that's highlighted in Instruments
self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];
Here is the method for creating a mutable copy of a Dictionary
#interface NSDictionary(MutableDeepCopy)
-(NSMutableDictionary *)mutableDeepCopy;
#end
Here is method implementation, I've highlighted the code that Leaks saids is leaking 100%
- (NSMutableDictionary *) mutableDeepCopy {
NSMutableDictionary *dictionaryToReturn = [NSMutableDictionary dictionaryWithCapacity:[self count]];
NSArray *keys = [self allKeys];
for(id key in keys) {
id value = [self valueForKey:key];
id copy = nil;
if ([value respondsToSelector:#selector(mutableDeepCopy)]) {
copy = [value mutableDeepCopy];
} else if ([value respondsToSelector:#selector(mutableCopy)]) {
copy = [value mutableCopy]; //This is the Leak
}
if (copy == nil) {
copy = [value copy];
}
[dictionaryToReturn setValue:copy forKey:key];
}
return dictionaryToReturn;
}
You need to analyse this in light of Apple's Memory Management Rules.
Starting with this line:
self.mutableDictionary = [self.immutableDictionary mutableDeepCopy];
I would expect mutableDeepCopy to return an object I own, so at some point I need to release or autorelease it. e.g.
NSMutableDeepCopy* temp = [self.immutableDictionary mutableDeepCopy];
self.mutableDictionary = temp;
[temp release];
or
self.mutableDictionary = [[self.immutableDictionary mutableDeepCopy] autorelease];
So now we need to look at mutableDeepCopy. Because it has 'copy' in the name it needs to returned an "owned" object which, in practice means "forgetting" to release the returned object. You have already failed to do that when you create the returned object in the first line, since dictionaryWithCapacity: gives you an object you do not own. Replace it with
NSMutableDictionary *dictionaryToReturn = [[NSMutableDictionary alloc] initWithCapacity:[self count]];
Now you own it.
It is important that you make your mutableDeepCopy obey the rules because it means you can treat the objects returned from mutableDeepCopy, mutableCopy and copy in exactly the same way. In all three cases you own the object copy that you insert into the array. Because you own it, you must release it or it'll leak as you found out. So, at the end of the loop, you need
[copy release];
That'll stop the leak.
How is your property declared? If is is retain or copy, then this doesn't leak.
Your problem is that the name mutableDeepCopy suggests that it returns a retained object, and not an autoreleased one as it actually does.
Edit:
And at the mutableDeepCopy itself, you need to release the copy variable after adding to the dictionary.
mutableCopy increments the retain count of the object, as does setValue:forKey:. This means that when dictionaryToReturn is dealloc'ed, the object that had mutableCopy called still has a retain count of one.
Try doing this instead:
copy = [[value mutableCopy] autorelease];

Correct way to instantiate NSDictionary/NSArray in init without extra retains

I have numerous classes that use the various NSDictionary/NSArray collection classes as ivars but often I run into the problem of my collection class getting released before the containing class is released.
This seems to happen mostly with the collections classes and not with another model class (ie classes that I either created separately or other NS* non-collection classes).
Here are the two variations I've done and seen other people do:
#implementation ClassX
// myDictionary declared as a property in the .h file as this:
// #property (nonatomic, retain) NSMutableDictionary *myDictionary;
#synthesize myDictionary;
- (id)int
{
if (self = [super init])
{
// Option 1:
// If I don't instantiate and assign with 'self',
// myDictionary ivar will not be available
// at times in doSomething.
myDictionary = [NSMutableDictionary dictionary];
// Option 2:
// Doing this, however will keep the dictionary around.
// because I have invoked an extra retain on the dictionary
self.myDictionary = [NSMutableDictionary dictionary];
// Which one is more correct?
}
return self;
}
- (void)doSomething
{
// this will give the error about trying to invoke
// a method on an already released instance
[myDictionary objectForKey:#"myKey"];
}
- (void)dealloc
{
// If I did self.myDictionary in 'init', I then
// need to do this:
[myDictionary release];
[super dealloc];
}
#end
So which approach is the more correct way to hold an instance of NSDictionary within a class?
Option 2 is correct; Option 1 is wrong.
But you left out the best option: myDictionary = [[NSMutableDictionary alloc] init].
I recommend using
myDictionary = [[NSMutableDictionary alloc] init];
The memory is only within the scope of the method you're in if you call [NSMutableDictionary dictionary]. Once you leave the method, that memory goes with it which is why you need to alloc/init if you want to retain the values.
That's why you don't have to release if you don't encounter an alloc.
So for instance:
- (void) doSomething {
// Do not need to release this string
NSString *someText = #"Hello world!";
// You need to release this string:
NSString *otherText = [[NSString alloc] initWithString:#"Hello world!"];
[otherText release];
}
Edited: Removed self after #mipadi #st3fan and caught my mistake. Forgot to post the change. Thanks for keeping me accountable.