all Keys and Objects from a NSDictionary to a NSString - objective-c

I've got a NSDictionary and I'd like put all of it's objects and keys into a NSString, so that I can finally display them in a label like this:
key1: object1
key2: object2
key3: object3
... ...
Any ideas?

Build the string and then set it to the labels text.
NSMutableString *myString = [[NSMutableString alloc] init];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[myString appendFormat:#"%# : %#\n", key, obj];
}];
self.label.text = myString;
Note
The docs (String Programming Guide) for the %# format specifier state:
%#
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
So if these are your own custom objects in the dictionary you will most likely need to override the description method to provide more meaningful output
Update
You mention that you need your output sorted by keys - dictionaries are not ordered so you will have to do it differently - this example assumes that your keys are strings
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableString *myString = [[NSMutableString alloc] init];
for (NSString *key in sortedKeys) {
[myString appendFormat:#"%# : %#\n", key, [dictionary objectForKey:key]];
}
self.label.text = myString;

try this
for(id key in [dictionary allKeys])
{
id value = [dictionary objectForKey:key];
NSLog(#"%# : %#", key, value);
}

NSString *row;
for (id key in dictionary) {
row = [NSString stringWithFormat:"%#: %#", key, [dictionary objectForKey:key]];
// do something with your row string
}

Iam trying to append two time values from my TCTime object and display in label, even though I added "\n" towards the end it is printing only the first value but not the second value.
_feedTimes is NSArray.
NSMutableString *myString = [[NSMutableString alloc] init];
TCTime *time = _feedTimes[indexPath.row];
[myString appendFormat:#"%s : %#\n", "Time 1 ", time.Time1];
[myString appendFormat:#"%s : %#\n", "Time 2 ", time.Time2];
self.label.text = myString;

Related

NSString parsing for specific values

I have an NSString that returns a list of values like this:
test_1=value_1
test/2=value_2
test3=value_3 value_4
test_4=value_5/value_6
...
More realistic result values:
inameX=vlan2
hname=server
lanipaddr=192.168.1.1
lannetmask=255.255.255.0
islan=0
islwan=0
dhcplease=604800
dhcplease_1=302400
ct_tcp_timeout=0 1200 40 30 60 60 5 30 15 0
ct_timeout=10 10
ct_udp_timeout=25 60
ctf_disable=1
ddnsx0=
cifs2=0<\\192.168.1.5
and so on...
If I do:
for (id key in dict) {
NSLog(#"key: %#, value: %#", [dict objectForKey:key], key);
}
it outputs:
key: inameX, value: vlan2
key: hname value: server
key: lanipaddr value: 192.168.1.1
key: lannetmask value: 255.255.255.0
This list is stored in one NSString *result. Not sure if I should put it in an array for this but I need to be able to call a function or command that will return a specific value_X based on the argument to match the variable. For example, get value of test_1 variable then it would return value_1. Or get test_4 then it would return value_5/value_6
Any idea how I can do that?
I appreciate your help. Thanks!
You probably want the method in NSString called componentsSeparatedByCharactersInSet: to split up that one string into an array. Since your values are separated by '=' and new line characters ('\n'), you want the set to include those two characters:
NSArray *strings = [NSString componentsSeparatedByCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#"=\n"]];
And then you can make this into a dictionary with NSDictoinary's dictionaryWithObjects: AndKeys: But first, you need to split that array into two arrays; one with objects, one with keys:
NSMutableArray *keys = [NSMutableArray new];
NSMutableArray *values = [NSMutableArray new];
for (int i = 0; i < strings.count; i++) {
if (i % 2 == 0) { // if i is even
[keys addObject:strings[i]];
}
else {
[values addObject:strings[i]];
}
}
Then you put them into an NSDictonary
NSDictionary *dict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
NSLog(#"%#", dict[#"test_1"]) // This should print out 'value_1'
Hope that helps!
Use an NSDicationary. NSDictionaries are key value stores. In other words, there are a list of keys. Each key is unique. Each key has an associated value. The value can be any data type and the key has to conform to the NSCopying protocol (typically an NSString). If you try to access the value for a key that doesn't exist in your NSDictionary, the return value will be nil.
//create the dictionary and populate it
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"value_1" forKey:#"key_1"];
[dict setObject:#"value_2" forKey:#"key_2"];
[dict setObject:#"value_3" forKey:#"key_3"];
[dict setObject:#"value_4" forKey:#"key_4"];
NSString *stringInput = [self getStringInput];//however you find out your input
//find your string value based on the key passed in
NSString *strValue = [dict objectForKey:stringInput];
You can use a NSScanner to make this work.
Scan for the string for which you want the value, and then scan the string until you encounter \n and then use it for your requirement.
NSScanner *scan =[NSScanner scannerWithString:theString];
[scan scanString:keyString inToString:nil];
[scan setScanLocation:[scan scanLocation]+1];
[scan scanString:#"\n" inToString:requiredString];
So requiredString is the string which you want.

Replacing a specified dictionary in NSMutableArray

I'm trying to replace a dictionary in a mutable array.
Steps 1 through 4 should be good, but I'm having some trouble in step 5 - 6. Can you show me what has to be done to make this function work:
- (void) updatePlist {
// 1: String with plist path:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory
stringByAppendingPathComponent:#"Object.plist"];
// 2: Create a mutable dictionary containing current object and write
// "Yes" to the "Favorite" string:
NSMutableDictionary *mutDict = [NSMutableDictionary
dictionaryWithDictionary:[detailsDataSource objectAtIndex:detailIndex]];
[mutDict setObject:#"Yes" forKey:#"Favorite"];
// 3: Make a string containing current object name:
NSString *nameString = [[detailsDataSource objectAtIndex:detailIndex]
valueForKey:#"Name"];
// 4: Make a mutable array containing all objects:
NSArray *allObjectsArray = [[NSArray alloc] initWithContentsOfFile:path];
NSMutableArray *tmpMutArr = [NSMutableArray arrayWithArray:allObjectsArray];
// 5: Search for the dictionary in tmpMutArr with "Name" value matching nameString:
int *index;
for(int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:[NSString
stringWithFormat:#"%#", nameString]])nameString];)
{
index = i;
}
}
}
// 6: Replace the old dictionary with the new one and write array to plist:
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
allObjectsArray = nil;
allObjectsArray = [[NSArray alloc] initWithArray:tmpMutArr];
[allObjectsArray writeToFile:path atomically:YES];
}
EDIT:
Now the problem is:
for(int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:
[NSString stringWithFormat:#"%#", nameString]])nameString];)
{
index = i; // Here 1
}
}
}
// ---------------------------- v And here 2
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
1: Incompatible integer to pointer conversion assigning to 'int' from 'int'; take the adress with &
2: Incompatible pointer to integer conversion sending 'int *' to parameter of type NSUInteger' (aka 'unsigned int')
Replace the line:
if([tempDict valueForKey:#"Name" == [NSString stringWithFormat:#"", nameString];)
with this line:
if([[tempDict valueForKey:#"Name"] isEqualToString: [NSString stringWithFormat:#"%#", nameString]])
since you are using string comparison here.
As pointed out in the comments by Martin R, you are trying to save an int value into a int pointer variable.
int index; //instead of 'int *index;'
That change should do the trick.
It could have worked if you had written int *index; and then index = &i;, since you are saving a pointer to an integer that way. But it doesn't seem to be what you are trying to do.
The second error is due you are providing an int pointer instead of an integer to this method:
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
But declaring index as an integer solves both errors already.

Extracting number from NSString

I have an NSString which when logged gives me an answer like this one:
Response: oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z
The two numbers change every single time.
Is there a way to extract the two numbers and create two strings with one of each??
Like:
NSString *key = #"9tmqsojggieln6z";
//copy the string in a new string variable
NSMutableString *auth_token = [NSMutableString stringWithString:response];
NSRange match = [auth_token rangeOfString: #"&oauth_token="];
[auth_token deleteCharactersInRange: NSMakeRange(0, match.location+13)];
//auth_token will now have the auth token string
NSMutableString *auth_token_secret = [NSMutableString stringWithString:response];
NSRange range1 = [auth_token_secret rangeOfString:[NSString stringWithFormat:#"&oauth_token=%#", auth_token]];
[auth_token_secret deleteCharactersInRange:range1];
NSRange range2 = [auth_token_secret rangeOfString:#"oauth_token_secret="];
[auth_token_secret deleteCharactersInRange: range2];
//auth_token_secret will have the required secret string.
I had the same problem. As response I get the ids of objects sometimes as string sometimes as numbers. Then I wrote a category for NSDictionary which has the following method:
- (NSString *)stringFromStringOrNumberForKey:(NSString *)key
{
id secret = [self objectForKey:key];
if ([secret isKindOfClass:[NSNumber class]]) {
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
secret = [numberFormatter stringFromNumber:secret];
}
return secret;
}
I would try the following:
NSString *_response = #"oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z";
NSMutableDictionary *_dictionary = [[NSMutableDictionary alloc] init];
NSArray *_parameters = [_response componentsSeparatedByString:#"&"];
for (NSString *_oneParameter in _parameters) {
NSArray *_keyAndValue = [_oneParameter componentsSeparatedByString:#"="];
[_dictionary setValue:[_keyAndValue lastObject] forKey:[_keyAndValue objectAtIndex:0]];
}
// reading the values
NSLog(#"token_secret : %#", [_dictionary valueForKey:#"oauth_token_secret"]);
NSLog(#"token : %#", [_dictionary valueForKey:#"oauth_token"]);

FMDB Query with dictionary

I need to run a query that looks would look like
INSERT INTO Appointments (field1, field2, field3, ..., field30) VALUES (value1, value2, value3, ..., value30)
I have my Appointments being stored inside a Dictionary and would like to loop through that dictionary to make the keys equal the fields and the values equal the values.
I'm trying to use the executeUpdate:... withParameterDictionary:... but can't figure out how to make that work with multiple fields if I don't know the field names. The field names are being sent via JSON and instead of manually typing out 30 fields I would just like to loop through the dictionary and get them that way.
I have even tried
NSMutableArray *keys = nil;
NSMutableArray *values = nil;
for (NSDictionary *dict in [json objectForKey:#"data"]) {
keys = [NSMutableArray array];
values = [NSMutableArray array];
for (id key in dict) {
[keys addObject:key];
[values addObject:[NSString stringWithFormat:#":%#", key]];
}
NSString *keyString = [keys componentsJoinedByString:#","];
NSString *valueString = [values componentsJoinedByString:#","];
[[dataObj db] executeUpdate:#"DELETE FROM Appointments"];
NSLog(#"INSERT INTO Appointments (%#) VALUES (%#)", keyString, valueString);
[[dataObj db] executeUpdate:#"INSERT INTO Appointments (?) VALUES (?)", keyString, valueString];
}
The code above prints the NSLog how the query should looks but nothing is being inserted into the database. I know this because I am opening the simulator database file after the queries run and it is still blank.
How can I get the above code to work or how can I get the executeQuery:... withParameterDictionary:... to work with multiple names.
I ran a couple of quick tests, and this works for me:
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:#"AAAA44", #"a", #"BBBB44", #"b", #"CCCC44", #"c", nil];
NSMutableArray* cols = [[NSMutableArray alloc] init];
NSMutableArray* vals = [[NSMutableArray alloc] init];
for (id key in dict) {
[cols addObject:key];
[vals addObject:[dict objectForKey:key]];
}
NSMutableArray* newCols = [[NSMutableArray alloc] init];
NSMutableArray* newVals = [[NSMutableArray alloc] init];
for (int i = 0; i<[cols count]; i++) {
[newCols addObject:[NSString stringWithFormat:#"'%#'", [cols objectAtIndex:i]]];
[newVals addObject:[NSString stringWithFormat:#"'%#'", [vals objectAtIndex:i]]];
}
NSString* sql = [NSString stringWithFormat:#"insert into test (%#) values (%#)", [newCols componentsJoinedByString:#", "], [newVals componentsJoinedByString:#", "]];
NSLog(#"%#", sql);
BOOL updateSuccess = [db executeUpdate:sql];
The trick is to add ' to the data in the arrays.
NSDictionary *argsDict
= [NSDictionary dictionaryWithObjectsAndKeys:#"My Name",
#"name", nil];
[db executeUpdate:#"INSERT INTO myTable (name) VALUES (:name)"
withParameterDictionary:argsDict];
Here is some sample code I just wrote to support optional values at insert time. Just briefly tested but I think it works.
NSMutableDictionary* fieldsandvalues = [NSMutableDictionary dictionary];
fieldsandvalues[#"word"] = userphrase.word;
fieldsandvalues[#"translation"] = userphrase.translation;
if (userphrase.samplesentence.length > 0) {
fieldsandvalues[#"samplesentence"] = userphrase.samplesentence;
}
if (userphrase.notes.length > 0) {
fieldsandvalues[#"notes"] = userphrase.notes;
}
NSMutableArray* keyswithcolon = [NSMutableArray array];
for (NSString* key in fieldsandvalues.allKeys) {
[keyswithcolon addObject:[NSString stringWithFormat:#":%#", key]];
}
NSString* sql = [NSString stringWithFormat:#"INSERT INTO userphrase (%#) VALUES (%#)", [fieldsandvalues.allKeys componentsJoinedByString:#","], [keyswithcolon componentsJoinedByString:#","]];
// DLog(#"sql: %#", sql);
if (![self.db executeUpdate:sql withParameterDictionary:fieldsandvalues]) {
NSAssert(NO, #"Failed inserting userphrase into database! Last error: %# - %#", self.db.lastError, self.db.lastErrorMessage);
return nil;
}

NSDictionary - List all

In a NSMutableDictionary like this:
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithString:firstName], #"NAME",
[NSNumber numberWithFloat:familyName], #"SURNAME",
nil];
How can all of its elements be converted to the NSString? with the requirement that names and surnames are arranged in string like this: "name, surname, name, surname..."?
This gives a string with all the names but not surnames:
NSString * result = [[urlArray valueForKey:#"NAME"] componentsJoinedByString:#", "];
Is there a way similar to the one above to create a string with all the values of NSMutableDictionary?
Try something like this:
NSString *result = [NSString stringWithFormat:#"%#, %#", [urlArray valueForKey:#"SURNAME"], [urlArray valueForKey:#"NAME"]];
The %# represents an objective-c object for more details see the Apple docs
The code to make a NSString from an NSDictionary may look like (if you're trying to print out everything in the NSDictionary)
NSMutableString* mutableString = [NSMutableString string];
NSDictionary* dictionary;
for(NSString* key in [dictionary allKeys])
{
[mutableString appendString:[[dictionary objectForKey:key] description]];
}