Objective-C Changing values of instance variables in method - objective-c

I am write a Objective-C Code on XCode 4.4.
I have a NSMutableArray as a instance variable of my class k_info
I have defined and synthesized (nonatomic,retain) property by the name of onesplaces too.
I am unable to add a NSMUtableString object in the NSMutableArray onesplaces.
When I try to add it.The size of onesplaces remains 0 and object at zero index obviously remains null.
I tried doing this with and without using "self" key-word but it didnt worked in either case.
My syntax of adding object and printing it is right because when I create a new NSMutableArray test
and try to do the same thing it works for it but not for the instance variable onesplaces.
I cannot proceed any further in my project without solving this issue.please tell me why is it
happening and how should I solve this problem.
-(void)createinfo:(NSMutableArray )al varsis:(int)vars
{
NSMutableString stes=[[NSMutableString alloc]init];
stes=(NSMutableString*)#"string0";
[ onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[ onesplaces objectAtIndex:0]);
[ self.onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[self.onesplaces objectAtIndex:0]);
NSMutableArray* test=[[NSMutableArray alloc]init];
[ test addObject:stes];
NSLog(#"%u",[test count]);
NSLog(#"value is: %# ",[test objectAtIndex:0]);
}

You probably forgot to create the array. Somewhere in your code, maybe in your init method, you need to create the array before using it.
self.onesplaces = [[NSMutableArray alloc] init];
You get nil instead of error messages because Objective-C allows you to send messages to nil, which always return nil.

Related

componentsJoinedByString causing crash with EXC_BAD_ACCESS

I'm pretty sure this is eactly the same problem as in componentsJoinedByString gives me EXC_BAD_ACCESS
basically, an array is populated using this code, with ARC turned on:
-(NSMutableArray *)getArrayOfCommaSeparatedSelectorStrings{
NSMutableArray *Array = [[NSMutableArray alloc] init];
for(NSMutableArray *e in [self getArrayOfSelectorArrays]) {
[Array addObject:[displayCSSInformation returnArrayAsCommaList:e]];
}
return Array;
}
and then displayCSSInformation tries to return a comma separated list with this method :
+(NSString *)returnArrayAsCommaList:(NSMutableArray *)ToBeConverted{
NSString *test = [ToBeConverted componentsJoinedByString:#", "];
return test;
}
Thanks for your help.
There's usually no need to use a separate method if all that method does is invoke another method. Remove your +returnArrayAsCommaList: method and just use componentsJoinedByString: on the array directly.
- (NSMutableArray *) getArrayOfCommaSeparatedSelectorStrings
{
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSMutableArray *e in [self getArrayOfSelectorArrays])
[array addObject:[e componentsJoinedByString:#", "]];
return array;
}
The above should work (it works in my small test example), if you are still getting errors:
Make sure that getArrayOfSelectorArrays is actually returning an array of array of strings. Log the output to the console or step through with a debugger.
Use the “Build & Analyze” option to have the static analyser check for any issues. This is less of an issue with ARC but it will still pick up things such as using uninitialised values.
Make sure you have properly bridged ownership from any Core Foundation objects.

Trying to add entries in NSArray to NSDictionary, but values in NSDictionary are getting deallocated

I have three Deck Objects which are mostly just wrappers around NSArray objects containing Card objects. Initially, all the Card objects are in deck1, and eventually move through deck2 and deck3.
I also have an NSDictionary object that maps NSString objects to Card objects. I use the cards in deck1 to build this lookup table at the beginning of the game like this...
-(NSDictionary *)buildLookupTable {
NSMutableDictionary *lookup = [[NSMutableDictionary alloc] init];
for (Card *card in self.cards) {
NSString *lookupCode = [self buildCode:card];
[lookup setObject:card forKey:lookupCode];
}
return lookup;
}
I then pass the NSDictionary and the Decks to a layer object, but when I attempt to lookup a given Card based on a NSString, I get "-[CFString hash]: message sent to deallocated instance", but I can easily find the Card I'm looking for, not deallocated, in deck1 or deck2.
The NSString I'm using as a key to retrieve the desired value isn't deallocated, nor is the NSDictionary itself. I have even iterated over the return from the NSDictionary object's allValues method, and none of those are deallocated either.
What other deallocated objects could there be?
Edit-version2:
I've narrowed it down a bit.
In the lookup code this works
NSString *key = #"4-0"; //(NSString *)sprite.userData;
return [self.cardLookup objectForKey:key];
but this doesn't
NSString *key = (NSString *)sprite.userData; // value is #"4-0"
return [self.cardLookup objectForKey:key];
In the debugger sprite.userData looks fine.
sprite.userData is defined in the Card class buildSprite method as...
sprite.userData = [NSString stringWithFormat:#"%i-%i",self.x, self.y];
It looks like calling copyWithZone on key doesn't work (like it would for any other NSString).
Found the issue!
The problem was with the sprite.userData object and how it was created.
sprite.userData = [NSString stringWithFormat:#"%i-%i",self.x, self.y];
Evidently sprite.userData was getting released (thought the Xcode debugger seemed to know what it was, possibly because I had zombie objects enabled). The correct version is...
sprite.userData = [[NSString stringWithFormat:#"%i-%i",self.x, self.y] retain];

NSArray initWithObjects only initializing with some of the objects

I've encountered a weird issue thats causing me quite the headache. I am initializing an NSArray object using initWithObjects. I'm passing in 7 objects but immediately afterwords, if I log the count of the array, I only have a count of 3. Has anyone else seen this? I've used this method countless times with no problem before and I can't see what I'm doing wrong. The code is below:
-(DMORecipe *) saveRecipe:(NSNumber *)recipeID recipeTitle:(NSString *)title recipeDescription:(NSString *)description pictureFile:(NSString *)picFile preparationTime:(NSString *)prepTime cookingTime:(NSString *)cookTime ovenTemperature:(NSString *)ovenTemp {
NSArray *newRow = [[NSArray alloc] initWithObjects:recipeID,title, description, picFile, prepTime, cookTime, ovenTemp, nil];
NSLog(#"Before update, the number of args is %i", [newRow count]);
}
Do I have a type-o somewhere that I'm missing? You can see I'm passing in 7 objects to the array initializer but the NSLog method shows [newRow count] = 3.
If any of the object passed in is nil, the rest of the argument will be ignored.
In this case, it seems that picFile is nil.

NSMutableDictionary error

I want to use NSMutableDictionary to cache some data i will use later. My custom object is following:
#interface MyData : NSObject {
NSRange range;
NSMutableArray *values;
}
#property (nonatomic, retain) NSMutableArray *values;
and implement:
- (id)init {
if (self = [super init]) {
values = [[NSMutableArray alloc] init];
}
return self;
}
and when i wanna cache it, i use it like this:
NSMutableDictionary *cache = [[NSMutableDictionary alloc] init];
NSString *key = #"KEY";
MyData *data = [[MyData alloc] init];
// save some data into data
[data.values addObject:"DATA1"];
[data.values addObject:"DATA2"];
//... ...
[cache setObject:data forKey:key];
My questions is the count of cache.values is zero when i retrieve this object later as follow:
[cache objectForKey:#"KEY"];
i can retrieve "data" and the object's memory address is the same as the address when i put it into cache.
what's wrong? i need some kind guys help, any info is helpful. thanks
As Carl Norum pointed out, you're passing C strings to addObject:. addObject:, as its name suggests, requires a pointer to a Cocoa object; a C string is a pointer to characters. You need to pass NSString objects there; for literal strings, this simply requires prefixing them with #: "Fred" is a constant C string, whereas #"Fred" is a constant NSString object.
Is cache an instance variable? It looks like it's not; it appears to be a local variable, which means you're creating a new dictionary object every time. That's why there's nothing you've added previously (to previous dictionaries) in the new one. It also means you're leaking those previous dictionaries, since you're not releasing them (not in the code you showed, anyway).
Make cache an instance variable and only create the dictionary when you don't already have one (i.e., when cache == nil). Creating the dictionary in your init method is one good way. And make sure you manage its lifetime appropriately, so you don't leak and/or crash.
First of all your objects your adding don't look right it should have an # before the string. Like #"DATA1"
Second when you add an object to a dictionary or an array it does not make an actual copy of it. It just creates a pointer to it so if those objects are destroyed or moved somewhere also they are also gone out of your dictionary. A better way to make a cache of your values would be to copy the objects like so:
MyData* cache = [[MyData alloc] init];
for (int i = 0; i < [data.values count]; i ++){{
[cache.values addObject:[NSString stringWithString:[data.values objectAtIndex:i]]];
}
Don't use a dictionary in this situation.

Objective C /iPhone : Is it possible to re initialize an NSArray?

I read that non mutable data types can't be modified once created.(eg NSString or NSArray).
But can they be re-initialized to point to a different set of objects?
If so, do I use release to free any alloc from first time round in between uses? eg:
myArray declared as NSArray *myArray in interface, and as nonatomic/retain property.myArray set in initialization code to a point to an array of strings as follows.
self.myArray = [myString componentsSeparatedByString:#","];
But later I want to re-initialize myArray to point to a different set of strings
self.myArray = [myOtherString componentsSeparatedByString:#","];
Is it possible? Thanks...
It really depends what you mean with re-initialize. You can assign another immutable object to a pointer, because the pointers aren't constant.
Example:
#interface MyObj : NSObject {
NSString *name; // not needed in 64bit runtime AFAIK
}
#property(retain) NSString *name; // sane people use copy instead of retain
// whenever possible. Using retain can
// lead to some hard to find errors.
#end
/* ... another file ... */
MyObj *theObject = [[[MyObj alloc] init] autorelease];
theObject.name = #"Peter";
NSString *oldName = theObject.name;
NSLog(#"%#", theObject.name); // -> Peter
NSLog(#"%#", oldName); // -> Peter
theObject.name = #"Martin";
NSLog(#"%#", theObject.name) // -> Martin
NSLog(#"%#", oldName) // -> Peter
If the behavior above is what you want, that's fine.
If you want that last line to return Martin you're in trouble. Those are constant strings and are not meant to be modified. You could, if you really want, modify the memory of the object directly, but this is dangerous and not recommended. Use mutable objects if you need such behaviour.
Yes you can reinitialized the NSArray. Here is the sample code that i used to re-initialized the NSArray.
NSString *keywords = #"FirstName|LastName|Address|PhoneNumber";
NSArray *arr = [keywords componentsSeparatedByString:#"|"];
NSLog(#"First Init - %#,%#,%#,%#",[arr objectAtIndex:0],[arr objectAtIndex:1],
[arr objectAtIndex:2],[arr objectAtIndex:3]);
arr = nil;
keywords = #"First_Name|Last_Name|_Address|_PhoneNumber";
arr = [keywords componentsSeparatedByString:#"|"];
NSLog(#"Second Init - %#,%#,%#,%#",[arr objectAtIndex:0],[arr objectAtIndex:1],
[arr objectAtIndex:2],[arr objectAtIndex:3]);
Of course they can. Saying that an NSArray is immutable doesn't mean that an attribute of a class of that type cannot be changed. You can't change the content, but you can assign new content to it.
If you want to make also changing the reference impossible you should use const keyword.