Object at index in NSArray - iphone

I have an array. I want to check whether there is an object present in a particular index or not. How to do this? Please help.

if you just want to check if there is an object
if (myIndex < [array count])
if you want to find a specific object
[array indexOfObject:myObject];
if you want to know if the object at some index is of some class
[[array objectAtIndex:myIndex] isKindOfClass:[TheClassToCompareTo class]];

BOOL exists = index < [array count] ? YES : NO;

You can use containsObject method to check weather your array contains the specific object or not. If contains, then get its index by indexOfObject method
if ([yourArrayArray containsObject:yourObject])
{
NSLog(#"Found");
int index = [yourArray indexOfObject:yourObject];
}

I know this is old thread but just trying to help.
You can add a category to NSArray something like this
#implementation NSArray (Safe)
- (id)safeObjectAtIndex:(NSUInteger)index {
if (index >= [self count]) return nil;
return [self objectAtIndex:index];
}
#end

You should check the length of the array (using the count method) and given NSArray cannot contain nil it must therefore contain something:
- (BOOL)arrayContainsSomethingAtIndex:(NSUInteger) index
{
return [_myArray count] > index;
}

Use indexOfObject: method.
if ([Array indexOfObject:object]==index) {
//code
}

check like this
if([array objectAtIndex:i]!= nil)
{
NSLog("Object present");
}
else{
NSLog("Object Not Present")
}
Modified:
You should make like this
if(i<=[array count]){
if([array objectAtIndex:i]!= nil)
{
NSLog("Object present");
}
else{
NSLog("Object Not Present")
}
}
This will not raise exception and object in array should compare with nil value

First you must check if the index of that object is smaller than the size of the array, then you query the array at that index.
if (index < [array count] && [array objetAtIndex:index]){
/* 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])

Check two NSArrays for containing each other's objects (NSManagedObject)

I'm stuck at following problem for quite some time now:
I've got two NSArrays, both containing NSManagedObject subclass-objects.
They're fed by different sources but the objects in them still have the same properties/values.
What I want to do now is check if array A contains objects from array B and vice versa.
Unfortunately NSArray's containsObject-method doesn't seem to work here.
I think it uses id-testing for the equality check on each object, doesn't it?
So, does anybody have a clue, what to try?
I even tried to encapsulate my objects in NSSets, using member: as my comparison-method but this didn't work out as well, especially because "you must not override" isEqual etc. for NSManagedObject subclasses.
Here's a code snippet:
//manufacturers is an array, parsed out of some xml here...
for(Manufacturer *manu in [fetchedResultsController fetchedObjects])
{
if(![manufacturers containsObject:manu])
{
NSLog(#"Deleting %#", manu.name);
[self.mContext deleteObject:manu];
}
}
for(Manufacturer *manu in manufacturers)
{
if(![[fetchedResultsController fetchedObjects] containsObject:manu])
{
NSLog(#"Adding %#", manu.name);
[newArray addObject:manu];
}
}
Thanks in advance for any hint ;)
I'm not sure if this works, but you could try to match the dictionaries you get with dictionaryWithValuesForKeys:.
Something like this:
NSArray *keysToCompare = [NSArray arrayWithObjects:#"FooAttribute", #"BarAttribute", nil];
// create an array with the dictionary representation of the managedObject
NSMutableArray *fetchedObjectsDictionaries = [NSMutableArray arrayWithCapacity:[[fetchedResultsController fetchedObjects] count]];
for (NSManagedObject *object in [fetchedResultsController fetchedObjects]) {
NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare];
[fetchedObjectsDictionaries addObject:dictionaryRepresentation];
}
// another array with dictionaries for managedObjects
NSMutableArray *manufacturersDictionaries = [NSMutableArray arrayWithCapacity:[manufacturers count]];
for (NSManagedObject *object in manufacturers) {
NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare];
[manufacturersDictionaries addObject:dictionaryRepresentation];
}
// compare those dictionaries
for (NSInteger i = 0; i < [fetchedObjectsDictionaries count]; i++) {
NSDictionary *dictionary = [fetchedObjectsDictionaries objectAtIndex:i];
if (![manufacturersDictionaries containsObject:dictionary]) {
// get the corresponding managedObject
NSManagedObject *object = [[fetchedResultsController fetchedObjects] objectAtIndex:i];
[newArray addObject:object];
}
}
if that won't work you can write your own isEqualToManufacturer: method and enumerate trough the arrays manually.
There would be 3 types of equality you can check for: same memory address, managed object id equality, and value equality. Your current code already checks to see if the objects share the same memory address and this is most likely not what you are interested in. This leaves two possible options. Using the managed object id equality method you can check if the manufacturers point to the same row in the database. Using the value equality you can check if two manufacturers are equal based on the shared values. Below is a way to check for NSManagedObjectID equality.
for(Manufacturer *manu in [fetchedResultsController fetchedObjects])
{
id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop){
return [[checkManu objectID] isEqual:[manu objectID]];
};
if([manufacturers indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound)
{
NSLog(#"Deleting %#", manu.name);
[self.mContext deleteObject:manu];
}
}
for(Manufacturer *manu in manufacturers)
{
id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop){
return [[checkManu objectID] isEqual:[manu objectID]];
};
NSArray * fetchedObjects = [fetchedResultsController fetchedObjects];
if([fetchedObjects indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound)
{
NSLog(#"Adding %#", manu.name);
[newArray addObject:manu];
}
}
You need to override -isEqual: since that's what -[NSArray containsObject:] calls into:
- (BOOL)isEqual:(id)other;
{
if (![other isKindOfClass:[Manufacturer class]]) {
return NO;
}
Manufacturer *otherManufacturer = other;
return ([self.name isEqual:otherManufacturer.name] &&
...
);
}
Checking for containment inside an NSSet is cheaper (and may make sense if you run into performance problems). It only works if you have a relatively decent -hash implementation, but it's easy to implement like this:
- (NSUInteger)hash;
{
return [self.name hash] + [self.foo hash] + ...;
}
Don't go trough too much trouble with the hash, just use 2 - 3 values that are most likely to uniquely identify the object.

how do I create fresh NSMutableArray?

I have an NSMutableArray which only lasts during the session.
Currently I create it like this
NSMutableArray *temp = [[NSMutableArray alloc] initWithCapacity:10];
[self setScoreArray:temp];
[temp release];
Problem is when I go to check each index I'm getting an array outofbounds error
NSNumber *previousScore = [[self scoreArray] objectAtIndex:[self quizNum]];
if ( previousScore != nil )
{
[self clearQuizBtns];
NSInteger previousScoreValue = [previousScore integerValue];
[self selectButtonAtTag:previousScoreValue];
}else {
[self clearQuizBtns];
}
I've read in other posts that initWithCapacity doesn't actually create the array. So what can I populate the array with initially?
Thanks in advance.
Two ways:
first: to initiate array with default values of NSNull class
NSMutableArray *temp = [[NSMutableArray alloc] initWithCapacity:10];
for (int i = 0 ; i < 10 ; i++)
{
[temp insertObject:[NSNull null] atIndex:i];
}
[self setScoreArray:temp];
[temp release];
and then to check: if object is kind of NSNull class means it was a never set before
id previousScore = [[self scoreArray] objectAtIndex:[self quizNum]];
if (![previousScore isKindOfClass:[NSNull class]])
{
[self clearQuizBtns];
NSInteger previousScoreValue = [(NSNumber *)previousScore integerValue];
[self selectButtonAtTag:previousScoreValue];
}else {
[self clearQuizBtns];
}
second: store scores in NSMutableDictionary and use NSNumber's as keys
// scoreDictionary property of NSMutableDictionary class must be declared in self
NSNumber *previousScore = [self.scoreDictionary objectForKey:[NSNumber numberWithInt:[self quizNum]]];
if (previousScore != nil)
{
[self clearQuizBtns];
NSInteger previousScoreValue = [previousScore integerValue];
[self selectButtonAtTag:previousScoreValue];
}else {
[self clearQuizBtns];
}
NSArray does not support "holes". The capacity is just a hint to the initializer.
You could either fill the array with placeholder objects or, more typically, change your algorithm to either fully prepopulate the array or to lazy load it linearly.
Your problem seems to be that you're never actually setting any score in the score array.. are you? NSArrays have an actual count of items in them, and accessing an index beyond that count will blow up, as you've seen. If there will only ever be a fixed (small) number of scores, like 10, then you could set them all initially to something default like:
for (int i = 0; i < 10; i++) {
[temp addObject:[NSNumber numberWithInt:0]];
}
P.S. -initWithCapacity does "create the array", it just doesn't create any objects in the array. The capacity is a hint only.
Using the arrayWithObject: or arrayWithObjects: methods can provide an array with pre-populated values.
One cool thing about NSMutableArrays is that you can just do an "init" and the array will handle adding and removing objects on the fly. Remember that you generally addObject: or removeObjectAtIndex: when dealing with mutable arrays.

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.

NSMutable Array

I have a NSMutableArray:
NSMutableArray *temp = //get list from somewhere.
Now there is one method objectAtIndex which returns the object at specified index.
What I want to do is that, I want to first check whether an object at specified index exists or not. If it exists than I want to fetch that object. Something like:
if ([temp objectAtIndex:2] != nil)
{
//fetch the object
}
But I get exception at the if statement saying that index beyond bound.
Please anyone tell me how to achieve this.
you cannot have 'empty' slots in an NSArray. If [myArray count]==2 ie array has two elements then you know for sure that there is an object at index 0 and an object at index 1. This is always the case.
Check the length first using the count method.
if ([temp count] > indexIWantToFetch)
id object = [temp objectAtIndex:indexIWantToFetch];
you could do this way:
When you initialize, do something like:
NSMutableArray *YourObjectArray = [[NSMutableArray alloc] init];
for(int index = 0; index < desiredLength; index++)
{
[YourObjectArray addObject:[NSNull null]];
}
Then when you want to add but check if it already exists, do something like this:
YourObject *object = [YourObjectArray objectAtIndex:index];
if ((NSNull *) object == [NSNull null])
{
/// TODO get your object here..
[YourObjectArray replaceObjectAtIndex:index withObject:object];
}
Just check that the index is >= 0 and < count
Returns the number of objects currently in the receiver.
- (NSUInteger)count
int arrayEntryCount = [temp count];
First of all you check the length of array-
NSMutableArray *temp = //get list from somewhere.
now check-
if(temp length)
{
Your objectclass *obj = [temp objectAtIndex:indexnumber];
// indexnumber is 0,1,2 ,3 or anyone...
}