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])
Related
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*/
}
Currently I am using the following method to validate the data for not being Null.
if ([[response objectForKey:#"field"] class] != [NSNull class])
NSString *temp = [response objectForKey:#"field"];
else
NSString *temp = #"";
Problem comes when the response Dictionary contains hundreds of attributes (and respective values). I need to add this kind of condition to each and every element for the dictionary.
Any other way around to accomplish?
Any Suggestion for making any change to the web service (except not inserting the null value to database)?
Any Idea, Anyone ??
What I've done is put a category on NSDictionary
#interface NSDictionary (CategoryName)
/**
* Returns the object for the given key, if it is in the dictionary, else nil.
* This is useful when using SBJSON, as that will return [NSNull null] if the value was 'null' in the parsed JSON.
* #param The key to use
* #return The object or, if the object was not set in the dictionary or was NSNull, nil
*/
- (id)objectOrNilForKey:(id)aKey;
#end
#implementation NSDictionary (CategoryName)
- (id)objectOrNilForKey:(id)aKey {
id object = [self objectForKey:aKey];
return [object isEqual:[NSNull null]] ? nil : object;
}
#end
Then you can just use
[response objectOrNilForKey:#"field"];
You can modify this to return a blank string if you'd like.
First a minor point: your test is not idiomatic, you should use
if (![[response objectForKey:#"field"] isEqual: [NSNull null]])
If you want all keys in your dictionary that have a value of [NSNull null] to be reset to the empty string, the easiest way to fix it is
for (id key in [response allKeysForObject: [NSNull null]])
{
[response setObject: #"" forKey: key];
}
The above assumes response is a mutable dictionary.
However, I think you really need to review your design. You shouldn't be allowing [NSNull null] values at all if they are not allowed in the database.
It's not quite clear for me what you need but:
If you need to check whether the value for key is not NULL you can do this:
for(NSString* key in dict) {
if( ![dict valueForKey: key] ) {
[dict setValue: #"" forKey: key];
}
}
If you have some set of required keys, you can create static array and then do this:
static NSArray* req_keys = [[NSArray alloc] initWithObjects: #"k1", #"k2", #"k3", #"k4", nil];
Then in the method where you check your data:
NSMutableSet* s = [NSMutableSet setWithArray: req_keys];
NSSet* s2 = [NSSet setWithArray: [d allKeys]];
[s minusSet: s2];
if( s.count ) {
NSString* err_str = #"Error. These fields are empty: ";
for(NSString* field in s) {
err_str = [err_str stringByAppendingFormat: #"%# ", field];
}
NSLog(#"%#", err_str);
}
static inline NSDictionary* DictionaryRemovingNulls(NSDictionary *aDictionary) {
NSMutableDictionary *returnValue = [[NSMutableDictionary alloc] initWithDictionary:aDictionary];
for (id key in [aDictionary allKeysForObject: [NSNull null]]) {
[returnValue setObject: #"" forKey: key];
}
return returnValue;
}
response = DictionaryRemovingNulls(response);
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.
I have a certain NSDictionary with couple of keys but they go much in dept in hirerchy such as:
Person:
Gender:
Name:
Address:
Location:
So you can see if I insert this in nsdictionary, initially I just have two keys as "Person" and "Location", however I am trying to iterate in each one of the keys to check for null value and set it to #"" empty string.
Does anyone know how to iterate through such dept?
Thanks
you can't store a nil in an NSDictionary. Either you'll be looking for [NSNull null] or you'll be looking for dictionaries that lack the keys you are looking for....
enumerateKeysAndObjectsUsingBlock: is faster than for( ... in ...).
if you are modifying the contents of the dictionaries, you must use mutable dictionaries. If you are unarchiving from a property list, there are options for creating mutable containers with immutable nodes (which is probably what you want).
Recurse is the answer, though non of the answers that show recursion are correct.
- (void)filterMutableDictionary:(NSMutableDictionary*)aDictionary
{
// check if aDictionary is missing any keys here
if (![aDictionary objectForKey:#"DesiredKey"]) {
... fill in key/value here ...
}
// enumerate key/values, filtering appropriately, recursing as necessary
[aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
if ([value isKindOfClass: [NSMutableDictionary class]]) {
[self filterMutableDictionary: value];
} else {
... filter value here ...
}
}];
}
In the simplest form:
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]]) [dictionary setValue:[NSString stringWithString:#""] forKey:key];
} ];
You could use a recursive method, like this:
- (void)recursive:(NSDictionary*)aDictionary {
for (id key in aDictionary) {
id value = [aDictionary objectForKey:key];
if ([value isKindOfClass:[NSDictionary class]]) {
[self recursive:value];
} else {
// Do something else, the value is not a dictionary
}
}
}
Inside your loop as you are checking for values use this for checking against null.
if ([[dict objectForKey:#"Gender"] isKindOfClass:[NSNull class]]) {
// null value
myGender = #"";
}
- (void)recursive:(NSDictionary)dictionary {
for (NSString *key in [dictionary allKeys]) {
id nullString = [dictionary objectForKey:key];
if ([nullString isKindOfClass:[NSDictionary class]]) {
[self recursive:(NSDictionary*)nullString];
} else {
if ( (NSString*)nullString == nil)
[dictionary setObject:#"" forKey:#"key"];
}
}
}
I am having a NSMutableDictionary. I have to dynamically rename any Key in the dictionary to a new value, in my code.. I can't find any built-in API to do this..
How can I do this? Is there any built-in API available to do this?
Thanks everyone..
// assumes that olkdey and newkey won't be the same; they can't as
// constants... but...
[dict setObject: [dict objectForKey: #"oldkey"] forKey: #"newkey"];
[dict removeObjectForKey: #"oldkey"];
Think about what "directly editing an existing key" means. A dictionary is a hash; it hashes the contents of the keys to find a value.
What happens if you were to change the contents of a key? The key would need to be rehashed (and the dictionary's internal structures re-balanced) or the value would no longer be retrievable.
Why do you want to edit the contents of a key in the first place? I.e. what problem does that solve that the above does not?
This should work:
- (void) renameKey:(id<NSCopying>)oldKey toKey:(id<NSCopying>)newKey{
NSObject *object = [dictionary objectForKey:oldKey];
[object retain];
[dictionary removeObjectForKey:oldKey];
[dictionary setObject:object forKey:newKey];
[object release];
}
This does exactly the same as bbum's answer but, if you remove the old key first (like in this example) then you have to retain the object temporarily otherwise it might get deallocated in the way ;)
Conclusion: Unless you need explicitly to remove the old key first do as bbum.
#interface NSMutableDictionary (KAKeyRenaming)
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey;
#end
#implementation NSMutableDictionary (KAKeyRenaming)
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey
{
id value = [self objectForKey:oldKey];
if (value) {
[self setObject:value forKey:newKey];
[self removeObjectForKey:oldKey];
}
}
#end
This also handles the case where the dictionary doesn't have a value for the key nicely.
I have to navigate a complete JSON response object that holds fields, sub-dictionaries and sub-arrays. All because one of the JSON fields is called "return" which is an iOS reserved word, so can't be used with the JSONModel Cocoa Pod.
Here's the code:
+ (id) sanitizeJSON:(id) dictIn {
if (dictIn) //check not null
{
// if it's a dictionary item
if ([dictIn isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictOut = [dictIn mutableCopy];
// Do the fix replace "return" with "not_return"
if ([dictOut objectForKey: #"return"])
{[dictOut setObject: [dictIn objectForKey: #"return"] forKey: #"not_return"];
[dictOut removeObjectForKey: #"return"];}
// Continue the recursive walk through
NSArray*keys=[dictOut allKeys]; //get all the keys
for (int n=0;n<keys.count;n++)
{
NSString *key = [keys objectAtIndex:n];
//NSLog(#"key=%# value=%#", key, [dictOut objectForKey:key]);
if (([[dictOut objectForKey:key] isKindOfClass:[NSDictionary class]]) || ([[dictOut objectForKey:key] isKindOfClass:[NSArray class]]))
{
// recursive call
id sanitizedObject = [self sanitizeJSON:[dictOut objectForKey:key]];
[dictOut removeObjectForKey: key];
[dictOut setObject:sanitizedObject forKey:key];
// replace returned (poss modified) item with this one
}
}
return dictOut; //return dict
}
else if ([dictIn isKindOfClass:[NSArray class]]) //Or if it's an array item
{
NSMutableArray *tempArray = [dictIn mutableCopy];
// Do the recursive walk across the array
for (int n=0;n< tempArray.count; n++)
{
// if array item is dictionary
if (([[tempArray objectAtIndex:n] isKindOfClass:[NSDictionary class]]) || ([[tempArray objectAtIndex:n] isKindOfClass:[NSArray class]]))
{
// recursive call
id sanitizedObject = [self sanitizeJSON:[tempArray objectAtIndex:n]];
// replace with the possibly modified item
[tempArray replaceObjectAtIndex:n withObject:sanitizedObject];
}
}
return tempArray; //return array
}
return dictIn; //Not nil or dict or array
}
else
return dictIn; //return nil
}