What is error in this code? - iphone

for(NSDictionary *feed in Feeds)
{
NSString *feedName=[feed objectForKey:#"name"];
if(listofBusiness==nil)
{
listofBusiness=[[NSMutableArray alloc]init];
}
if([listofBusiness indexOfObject:feedName] !=NSNotFound)
{
[listofBusiness addObject:feedName];
[feedName release];
feedName=nil;
}
}
in this code when compiler comes on this statement
if([listofBusiness indexOfObject:feedName] !=NSNotFound)
then not go into codition and go to increment in for loop so that any element is not added in array.what is error in this code?

The logic appears to be inverted - you probably want it to add the elemement when
[listofBusiness indexOfObject:feedName] == NSNotFound
But at the moment you have the opposite - you only try to add the object when it is 'not not found' - i.e. when it is already present in the list.

indexOfObject is not working for an array
Try with containsObject method of an array.
Example :
if([listofBusiness containsObject:feedName]) {
// your code
}

Related

bool for key in NSMutableArray

I have a code like that
if ([dataArray valueForKey:#"success"]) {
[self.feedsArray addObjectsFromArray:dataArray];
NSLog(#"self.feedsArray: %#",self.feedsArray);
} else {
NSLog(#"no feed found ");
}
dataArray is a NSMutableArray which ultimately contains a JSON Dictionary.
but I am getting the same console output independent of success either TRUE or FALSE, but my console output is always same.my console output is:
for FALSE or NO:
self.feedsArray: (
{
action = register;
message = "Invalid parameters";
success = 0;
}
)
and for TRUE or YES:
self.feedsArray: (
{
action = register;
message = "valid parameters";
success = 1;
}
)
in both cases if part is executed.
in NSUserDefaults there is a method boolForKey but how to do this in case of NSMutableArray.
You need to read the fine print for [NSArray valueForKey:], specifically:
Returns an array containing the results of invoking valueForKey: using
key on each of the array's objects.
and:
The returned array contains NSNull elements for each object that
returns nil.
So if the array contains, say, 3 objects and none of them have a success key then you will get an array of 3 NSNull objects returned.
Therefore the if statement will fire whenever dataArray is non-empty, which is obviously not what you intended.
You should check the contents of the returned array:
BOOL succeeded = NO;
NSArray *results = [dataArray valueForKey:#"success"];
for (NSObject *obj in results) {
succeeded = [obj isKindOfClass:[NSNumber class]] && [(NSNumber *)obj boolValue];
if (succeeded)
break;
}
if (succeeded) {
[self.feedsArray addObjectsFromArray:dataArray];
NSLog(#"self.feedsArray: %#",self.feedsArray);
} else {
NSLog(#"no feed found ");
}
You can do this in simple way:
What i see in your response json value is, you have dictionary in dataArray at index 0
NSMutableDictionary *responseDict = [dataArray objectAtIndex:0];
if([[responseDict objectForKey:#"success"] boolValue])
{
NSLog(#"Success: 1");
}
{
NSLog(#"Success: 0");
}
Use index instead of key for an array.
NSDictionary dictionary = (NSDictionary *)dataArray[0];
if ([(NSNumber *)[dictionary objectForKey:#"success"] boolValue]) {
// ...
}
otherwise use if([[[dataArray objectAtIndex:0] valueForKey:#"success"] isEqualToString:#"1"])
An array does not store keys, the only way to access items in an array is by index.
You should be using an NSDictionary/NSMutableDictionary instead. If you want to use a bool store it as a NSNumber, [NSNumber numberWithBool:YES] and then use the instance method valueForBool to read it back.
Try this
if ([[dataArray valueForKey:#"success"]isEqualToString:#"1"]) {
[self.feedsArray addObjectsFromArray:dataArray];
NSLog(#"self.feedsArray: %#",self.feedsArray);
}
else {
NSLog(#"no feed found ");
}
It 'll work out.
use this if you want bool value
if([[dataArray valueForKey:#"success"] boolValue])
{
//i.e success is true
}
if response contains array of dictionaries then we can use loop and check condition,
here i is index variable of array,
if([[[dataArray objectAtIndex:i] objectForKey:#"success"] boolValue])
{
// success is true ,
}
Replace you code line
if ([dataArray valueForKey:#"success"]) {
}
with
if ([[dataArray valueForKey:#"success"] integerValue]) {
}
Hope it will work for you.
its working with replacing the line with
if ([[[dataArray objectAtIndex:0] valueForKey:#"success"] boolValue])

Printing array inside array

I have class Building in which i have one class member NSMutableArray *subnode.I have declared one more array buildingArray which stores the element of type Building.I have tried to print Building class object as shown in following code.But goes in only first for loop.
Second for loop of subnode array is not executing . Is this proper way of printing the object having the array as a one of its class member.
code:
for(Building *b in buildingArray)
{
NSLog(#"inside building array");
for(NSString *str in b.subnode)
{
NSLog(#"inside subnode array");
}
}
If this is for debugging purposes, I would recommend trying the following: Every object that inherits from NSObject inherits its description method.
Add this to Building.m:
#implementation Building
- (NSString *)description {
NSMutableString *description = [NSMutableString stringWithString:[super description]];
// add the following lines for any relevant properties
// [description appendFormat:#", materials == %#", materials];
// then have the subnode print itself:
[description appendFormat:#", subnode == %#", subnode];
return description;
}
#end
You can then print the entire buildingArray by simply calling the following code:
NSLog(#"buildingArray == %#", buildingArray);
for(Building *b in buildingArray)
{
NSLog(#"inside building array");
NSMutableArray *temp = [NSMutableArray arrayWithArray:b.subnode]
for(id *str in temp)
{
NSLog(#"inside subnode array");
}
}
this should work. happy coding :)
Your code seems to be ok. Just check if the array (subnode) is allocated and initialized. Also check if it has some values in it. I have used similar code and it works for me.
Change following code. I don't know what do you mean buy Building . So i just used id instead of Building to avoid any type of confusion.
for(id b in buildingArray)
{
NSLog(#"inside building array");
NSArray *temp = b;
for(NSString *str in temp)
{
NSLog(#"inside subnode array");
}
}
Hope, this will help you;

If statement doesn't work with downloaded data

I've written some code that posts data to a MySql database via PHP and the PHP code returns a value of either 'YES' or 'NO' via JSON. I then have an if statement that checks whether it is YES or NO. The if statement works perfectly when I set the 'worked' string manually, but not if I use the data from JSON. I have checked that it is set correctly using NSLog, and I really can't see what the problem could be. Here is a shortened version of my code:
-(void) dataDownloaded {
NSDictionary *theDictionary = [_theArray objectAtIndex:0];
NSString *worked = [theDictionary objectForKey:#"worked"];
NSLog(#"%#", worked);
if (worked == #"NO") {
//code for if it didn't work
} else if (worked == #"YES"){
//code for if it did work
} else {
//code for if it doesn't return either value
}
}
Thanks in advance to anyone who can work out what the problem is!
Your problem is you're using == to compare. That's not going to work. I think you need to read up on Objective-C - try http://www.cocoadevcentral.com/ for that. Here's how you should fix your code:
-(void) dataDownloaded {
NSDictionary *theDictionary = [_theArray objectAtIndex:0];
NSString *worked = [theDictionary objectForKey:#"worked"];
NSLog(#"%#", worked);
if ([worked isEqualToString:#"NO"]) {
//code for if it didn't work
} else if ([worked isEqualToString:#"YES"]){
//code for if it did work
} else {
//code for if it doesn't return either value
}
}
use isEqualToString: for string comparsions
if ([worked isEqualToString:#"NO"]) {
}

Getting exception as "Collection was mutated while being enumerated"

I am getting the Collection was mutated while being enumerated exception when I am using this code can any one suggest me how to get out of this.
PaymentTerms * currentElement;
for (currentElement in termsArray)
{
printf("\n currentElement Value........%s",[currentElement.days UTF8String]);
printf("\n Str value...%s",[Str UTF8String]);
NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
if(!(range.location != NSNotFound))
{
PaymentTerms *pTerm1 = [[PaymentTerms alloc]init];
pTerm1.days = Str;
printf("\n pTerm1.days...%s",[ pTerm1.days UTF8String]);
[termsArray addObject:pTerm1];
}
}
Hope I get quick response from ur side.
Thank in advance,
Monish.
You cannot change array while you're enumerating it. As a workaround you should accumulate new objects in temporary array and add them after enumeration:
PaymentTerms * currentElement;
NSMutableArray* tempArray = [NSMutableArray array];
for (currentElement in termsArray)
{
NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
if(!(range.location != NSNotFound))
{
PaymentTerms *pTerm1 = [[PaymentTerms alloc]init];
pTerm1.days = Str;
[tempArray addObject:pTerm1];
[pTerm1 release];
}
}
[termsArray addObjectsFromArray: tempArray];
P.S. do not forget to release pTerm1 object you create - your code contains memory leak
In respond to poster's comment (and actual task) - I think the easiest way to make bool flag indicating if day value was found in cycle. If not - add new object after cycle ends:
PaymentTerms * currentElement;
BOOL dayFound = NO;
for (currentElement in termsArray)
{
NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
dayFound = YES;
}
if (!dayFound)
// Create and add new object here
This line [termsArray addObject:pTerm1];
will throw that exception. You CANNOT add/delete an element from an array inside a for each loop. for (currentElement in termsArray)
Yes...we cannot enumerate while the array is getting updated...This might be irritating for the programmers who are from ActionScript background.Some times things go worse like "You even dont get a crash or intimation at runtime when you update an array count while it is being enumerated"-The execution just behaves abnormally at that time.
Btw you can go for this type of implementation where you can have minor changes to your code.
for (int i=0 ; i< termsArray.count ;i++) //counting termsArray on every iteration
{
id currentElement = [ termsArray objectAtIndex:i];
......
.....
}
Of-course,This(i< termsArray.count) might seem bad as we are calculating the count for every iteration...And thats the trick here to have minor changes.But I would strongly recommend VLADIMIR's implementation as its clear for reading.
you are adding an object to your collection as you are looping over it, thats whats causing the error. your if statement is nested inside the for
The error occurs because you are adding new objects to termsArray within the for loop
Create a new empty array (e.g.newTermsArray)
In the first loop create and add these new items to newTermsArray
Then you will need a second loop to add the items from newTermsArray back into the original termsArray
Just dealt with the same bug in a rather complex app. The solution is simple - create a copy and work with the copy of array (and remove it from the original if you want. Then discard the copy.
for(CharacterModelNode* node in self.allPlayers)
{
// Some operation that may mutate allPlayers (ex: player dies from poison damage and is removed from this array at some other part of an app)
}
//workaround in some cases - create a copy of array and run operations that can kill player on this array (it will not be mutated anywhere else in the app
NSArray* allPlayersCopy = [self.allPlayers copy];
for(CharacterModelNode* node in allPlayersCopy)
{
[node.character refreshBuffs];
}
use try and catch for handling exception in nsmutable array
#try {
//code for accessing element.
}
#catch (NSException *exception) {
/// show exception here
}

Testing for contents of an NSArray without risking range error

I'm foolishly saying:
if ([imageCache objectAtIndex:index]) {
Problem is, on my first time through this, I haven't put ANYTHING in my NSMutableArray *imageCache, and this croaks with a range error.
How can I ask an NSMutableArray whether it has anything for a particular index?
The NSArray cluster class cannot store nil. So I think it is sufficient to simply check the bounds:
NSUInteger index = xyz;
if (index < [imageCache count]) {
id myObject = [imageCache objectAtIndex:index];
}
What I find really useful is having a safeObjectAtIndex: method. This will do the check for you and will return nil if the index is out of range.
Just create a new category on NSArray and include the following methods:
- (id)safeObjectAtIndex:(NSUInteger)index;
{
return ([self arrayContainsIndex:index] ? [self objectAtIndex:index] : nil);
}
- (BOOL)arrayContainsIndex:(NSUInteger)index;
{
return NSLocationInRange(index, NSMakeRange(0, [self count]));
}
if (index < [imageCache count])
...
This code answers your question. Unlike the accepted answer, this code handles passing in a negative index value.
if (!NSLocationInRange(index, NSMakeRange(0, [imageCache count]))) {
// Index does not exist
} else {
// Index exists
}
[imageCache count] will return the number of items in your array. Take it from there :-)
Check the number of items in the array first with [imageCache count]. Don't try to ask for anything with an index greater than that result.