I am trying to utilize incase-sensitive case for JSON response on NSDictionary as sometimes my response keys type varies, some are camel case, some are lowercase or other mixed combination. Is there any built in functionality to check for in-sensitivity case for this case?
Thanks.
Lately I've shared two classes that might suit your needs. They provide case-insensitive operations (named after NSDictionary and NSMutableDictionary methods) while keeping the originally inserted keys.
Give it a try:
https://github.com/keeshux/ios-components/tree/master/Components/Utils/KSCIDictionary
The best way would be to set the key for the NSDictionary to be either all lowercase or all uppercase;
For example lets say I have a NSArray of strings. I could get the keyName before I use it and convert it by using the lowercaseString or the uppercaseString
NSString *itemName = #"lastName";
itemName = [itemName lowercaseString];
this will change the string to lastname or if I used uppercaseString it would be LASTNAME
or you can also change the key name when adding to dictionary like so:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:objectToAdd forKey:[key uppercaseString]];
- (NSString *)lowercaseString
It's a default NSString method, just do [key lowercaseString] when adding to, or reading from the NSMutableDictionary.
In my case, I didn't need all of the Dictionary methods or properties. I just needed case-insensitive subscript access. I made a custom class (not a superclass of NSMutableDictionary) and implemented the methods to allow subscripted access and made those case insensitive:
- (id) objectForKeyedSubscript: (NSString *) key {
NSMutableDictionary *theData = self->data;
return theData[[key lowercaseString]];
}
- (void) setObject: (id) newValue forKeyedSubscript: (NSString *) key {
NSMutableDictionary *theData = self->data;
theData[[key lowercaseString]] = newValue;
}
See also:
http://clang.llvm.org/docs/ObjectiveCLiterals.html
Related
Dict is coming from notification, taking out the NSData from dict and adding it to NSMutableArray is crashing the application.
Once in a while this crash is happening not always.
NSData *data=[dict objectForKey:#"obj"];
[self.RFTagData addObject:data];
You can directly add data object by doing this.Instead of converting to string.
Don't type cast NSData to NSString when adding objects into array.You should first convert NSData into NSString then add it to array.So
better way to use this NSData into NSString and add NSString into array.
NSData *data=[dict objectForKey:#"obj"];
NSString *strData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(data != nil self.RFTagData != nil)
{
[self.RFTagData addObject:strData];
.....
}
Example for Converting Data into String
You can directly get the data to array there is no need to cast.
if(self.RFTagData != nil){
self.RFTagData = [dict objectForKey:#"obj"];
}
NSLog(#"array %#", RFTagData);
This will add all data to array under the obj key.
Update:
As user rmaddy & danh suggested, so here needs to take concern over this point regarding use of valueForKey and objectForKey methods and nil check on the array.
objectForKey: This is an NSDictionary method. An NSDictionary is a collection class similar to an NSArray (collections), except instead of using indexes like NSArray, it uses keys to differentiate between items. A key is an arbitrary string you provide. No two objects can have the same key (just as no two objects in an NSArray can have the same index).
valueForKey: This is a KVC method. It works with ANY class. valueForKey: allows you to access a property using a string for its name.
Here both returns the value associated with a given key, so here using valueForKey method provides workaround solution to you. But using objectForKey is the more preferred way to use in such cases.
To check for the null values inside array which are identically appears like literals #"<null>" rather then NSNull objects typically used to represent nils in Cocoa collections. You can filter them out by using NSArray's filteredArrayUsingPredicate method:
NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(id value, NSDictionary *unused) {
return ![str isEqualToString:#"<null>"];
}];
NSArray *filteredAry = [self.RFTagData filteredArrayUsingPredicate:pred];
NSLog(#"array with non null vals %#", filteredAry);
RestKit version: 0.27.0
Is there any way how to let RestKit to serialize the boolean value stored in NSDictionary to x-www-form-urlencoded parameters?
I have NSDictionary filled with values, it is propagated to the encoded string:
product=ACCOUNT&rejected=1&type=NUMBER_OF_LOGINS_MONTH
But I need true/false instead of 1 or 0 as the value for rejected parameter.
Is there any way how to use class specification similar to RKAttributeMapping's propertyValueClass to override the default type NSNumber? Also NSNumber is internally implemented as __NSCFBoolean. Is it possible to use this information to serialize the value as true/false?
I have subclassed RKURLEncodedSerialization and copied the implementation from RKAFQueryStringFromParametersWithEncoding:
static NSString * TSNRKAFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) {
NSMutableArray *mutablePairs = [NSMutableArray array];
for (TSNRKAFQueryStringPair *pair in TSNRKAFQueryStringPairsFromDictionary(parameters)) {
if([NSStringFromClass([pair.value class]) isEqualToString:#"__NSCFBoolean"]) {
pair.value = TSNNSCFBooleanToBooleanStringConvertor(pair.value);
}
[mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]];
}
return [mutablePairs componentsJoinedByString:#"&"];
}
NSString* TSNNSCFBooleanToBooleanStringConvertor(NSNumber* booleanInNSNumber) {
return [booleanInNSNumber boolValue] ? #"true" : #"false";
}
Also remember to copy the other methods/objects and rename them otherwise it will collide when being linked.
The new subclass has to be registered with the RestKit:
[RKMIMETypeSerialization unregisterClass:[RKURLEncodedSerialization class]];
[RKMIMETypeSerialization registerClass:[TSNRKURLEncodedSerialization class] forMIMEType:RKMIMETypeFormURLEncoded];
UPDATE:
This solution works for requests with all methods except GET, HEAD and DELETE. These methods still trigger the original serialisation: not true/false, but 1/0.
You can convert a boolean NSNumber to a string with
NSNumber *number = #YES;
NSString *boolString = number.boolValue ? #"true" : #"false";
NSLog(#"%#", boolString);
I have an NSDictionary created by the AFNetworking class, but now I want to convert that NSDictionary into an array of objects of a class that I made. I have tried using the for-in loop as follows:
for (NSDictionary *item in results)
[_masterList addObject:[[MyObject alloc]initWithType:[item objectForKey:#"type"];
results by the way is my NSDictionary. There are no syntax errors, but when I run my program, nothing comes up. I tried NSLog-ing in the for-in, but didn't get anything, which means that the loop does not even run once. I'm pretty sure the NSDictionary is full, because I NSLoged the result during the AFNetworking process, and it was full:
(
{
address = "Sample Address";
}
)
Anyone have any ideas that I could use? Please express in the comments if I should add any more code. Thanks!
There are no key type, change it to address
for (NSDictionary *item in results)
[_masterList addObject:[[MyObject alloc]initWithType:[item objectForKey:#"address"];
results is a NSDictionary or a NSArray of dictionaries? If it is NSDictionary then you must loop like this:
// loop through each key in dictionary
// let say your key type is NSString
for (NSString* key in results) {
// access your object for key here
NSLog(#"%#", results[key]);
}
Not much of an answer but too big for a comment: you've made a mistake other than in the code presented. Try:
NSArray *results = #[
#{
#"address": #"Sample Address"
}
];
NSLog(#"%#", results);
for (NSDictionary *item in results)
NSLog(#"%# (%#)", item, [item objectForKey:#"address"]);
Output is:
2015-11-10 23:20:22.713 Untitled[1564:1904151] (
{
address = "Sample Address";
}
)
2015-11-10 23:20:22.715 Untitled[1564:1904151] {
address = "Sample Address";
} (Sample Address)
So, definitely the same dictionary, then the same iteration code, with correct results.
Addendum, which may or may not be helpful: one of the things Apple supplies to take advantage of Objective-C's reflective runtime is key-value coding which, assuming your properties obey certain rules, allows them to be written to by name. If you had a dictionary you wanted to commute to an object, and had performed suitable validation, then you might:
NSDictionary *inputDictionary = ... whatever ...
SomeObject *target = [[SomeObject alloc] init];
for (NSString *key in inputDictionary)
[target setValue:inputDictionary[key] forKey:key];
In contrast to Objective-C norms but consistently with most modern languages, that'll raise an exception if the key doesn't exist as a property on target. So in production code you probably want at least a try/catch block if the dictionary is coming from afar.
I have a dictionary with key-value pair populated from JSON returned data.What I wish to do is use the dictionary to populate UITableView.
I have this structure for table:
[Product Name]
By [Manufacturer Name]
What this means is that key is Product Name and Value is Manufacturer Name. I need to get the name of the key and the name of the value. How can this be done? and is it possible without for-loop?
I'd use the enumerateKeysAndObjectsUsingBlock: method. The following code builds a list of the strings you require.
NSMutableArray *names = [NSMutableArray array];
[dictionary enumerateKeysAndObjectsUsingBlock: ^(NSString *key, NSString *object, BOOL *stop) {
[names addObject[NSString stringWithFormat:#"%# By %#",key, object]];
}];
You can use the keyEnumerator of NSDictionary and for each key look up the value. This could look something like this:
for (NSString *p in dict)
{
NSString *m = [dict objectForKey:p];
// do something with (p,m)
}
You should not be concerned with avoiding for-loops. After all, something like a for loop will always happen somewhere underneath.
If your keys are dynamic from json then you can use
NSArray *keys = [dictionary allkeys];
Then in the table View Cell for row at index path method you can populate the table view with the corresponding keys and their values.
NSArray * keys = [results allKeys];
for (int i = 0;i<[keys count];c++){
NSString* productName = [key objectAtIndex:i];
NSString* manufacturerName = [results objectForKey:productName];
}
Hope this helps...
I have assumed the name as strings, you can change the type according to your situation..
I am familiar with getting a string count from a known array
int numberOfWords = [self.wordArray count];
but I have an unknown number of strings in an unknown number of arrays, all referenced by a dictionary. This works - good.
NSMutableDictionary *eqClasses = [[NSMutableDictionary alloc] init];
The arrays and strings are added at runtime (with help of this board):
NSMutableArray* array = [eqClasses objectForKey:wordPattern];
if(!array) {
// create new array and add to dictionary if wordPattern not found
array = [NSMutableArray array];
[eqClasses setObject:array forKey:wordPattern];
}
[array addObject:tempWordStr];
Now I need to iterate through the dictionary and get the array with the largest word count. Is there a way to scroll through all the arrays in the dictionary without using a key (I won't know all the word patterns as they are generated dynamically), AND once I find the array with the most words, get that array/value and key/wordpattern?
Well, there is a way to get all the keys within a dictionary:
NSArray *keyArray = [myDict allKeys];
And then you just go through the array and get the object for each key.
A fast enumeration should work nicely.
for (NSString *string in NSArray){
...
} //Assuming your keys are strings!
You can save each string to a temporary string, and when encountering a new string, compare to find the longer one. If it's longer, replace the old string with the longer one.
Hope this helped! ^_^
^_^
Okay, so now that you have an array full of all the keys in the dictionary,
you can iterate through the entire array and get the corresponding value (the string) for each key.
NSArray *keyArray = [myDict allKeys]; //This gets all the keys
NSString *tempString = #""; //This is the string you will save the longest string in. It gets updated when a longer string is found in the following loop.
for (NSString *string in keyArray){
NSString *stringFromCurrentKey = [myDict objectForKey:string];
if(stringFromCurrentKey.length > tempString.length){
tempString = stringFromCurrentKey;
}
} //By the end, you should be left with the longest string contained in tempString!
^_^ Hope this made sense and helped!
Try this code:
NSArray *largestArray = nil;
for (NSString *key in dictionary)
{
NSArray *array = [dictionary objectForKey:key];
if (array.count > largestArray.count) // largestArray.count is 0 if largestArray is nil
{
largestArray = array;
}
}