- (void)retrieveData
{
NSURL * url = [NSURL URLWithString:#"***/connection.php"];
NSData * data = [NSData dataWithContentsOfURL:url];
_json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
_questionsArray = [[NSMutableArray alloc]init];
for (int i = 0; i < _json.count; i++)
{
NSString * qID = [[_json objectAtIndex:i] objectForKey:#"id"];
NSString * qTitle = [[_json objectAtIndex:i] objectForKey:#"question_title"];
NSString * qA = [[_json objectAtIndex:i] objectForKey:#"A"];
NSString * qB = [[_json objectAtIndex:i] objectForKey:#"B"];
NSString * qC = [[_json objectAtIndex:i] objectForKey:#"C"];
NSString * qD = [[_json objectAtIndex:i] objectForKey:#"D"];
NSString * qAnswer = [[_json objectAtIndex:i] objectForKey:#"question_answer"];
question * myQuestion = [[question alloc] initWithQuestionID:qID andQuestionName:qTitle andQuestionA:qA andQuestionB:qB andQuestionC:qC andQuestionD:qD andQuestionAnswer:qAnswer];
[_questionsArray addObject:myQuestion];
}
[_json enumerateObjectsUsingBlock:^(NSDictionary *questionDictionary, NSUInteger idx, BOOL *stop) {
//Here I'm treating the index like an NSNumber, if your code is expecting a string instead use
//#(idx).stringValue
[_questions setObject:questionDictionary forKey:#(idx)];
//or the modern equivalent
//questions[#(idx)] = questionDictionary;
//If you want to use your 'questions class' then create one and put it into the array instead of the dictionary pulled from the array.
}];
NSLog( #"%#", _questions );
}
Logs (null)
random gobledy gook so my post isn't mostly code
random gobledy gook so my post isn't mostly code
random gobledy gook so my post isn't mostly code
random gobledy gook so my post isn't mostly code
random gobledy gook so my post isn't mostly code
If I understand your question correctly it becomes something like this
self.questions = .... //I assume this is the array you reference 'question' objects that is created by your retrieve data method
//this used to be created by pulling an object out of your questions dictionary with the key i interpreted as a string.
//now that it's an array you should be able to just reference it by index, assuming they were inserted in order
//I'm also assuming that what comes out of the aray is a question object given the code you provided with the signature
//- (id) initWithQuestionID: (NSString *) qID andQuestionName: (NSString *) qName andQuestionA: (NSString *) qA andQuestionB: (NSString *) qB andQuestionC: (NSString *) qC andQuestionD: (NSString *) qD andQuestionAnswer: (NSString *) qAnswer
Question *nextQuestion = self.questions[i];
self.answer = nextQuestion.questionAnswer;
self.questionLabel.text = nextQuestion.questionLabel;
//and so on
I also suggest the following edit to replace your for loop. It uses a for in loop instead, this saves you from having to keep track of an index and looks cleaner. It also helps so you don't keep repeating the [_json objectAtIndex:i] chunk of code. I also use modern objective-c syntax to access the dictionary.
for (NSDictionary *questionDictionary in _json)
{
NSString * qID = questionDictionary[#"id"];
NSString * qTitle = questionDictionary[#"question_title"];
...
question * myQuestion = [[question alloc] initWithQuestionID:qID andQuestionName:qTitle andQuestionA:qA andQuestionB:qB andQuestionC:qC andQuestionD:qD andQuestionAnswer:qAnswer];
[_questionsArray addObject:myQuestion];
}
If you need the key along with the object in the dictionary then you can clean it up in a similar way with the enumerateObjectsUsingBlock
[_json enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
//your code here
}];
EDIT
It sounds like what your really wanting to do is to pull down your JSON but keep all your other code the way it was when you were using a dictionary that you got from your plist. So in this case you want your parsing function to return a dictionary instead of an array. If that's the case it's worth sidestepping into computer science for a second.
NSDictionarys are also known as a hash, map, symbol table, or associative array. Some languages (such as Lua) don't have an array collection like NSArray, they only have dictionaries. From a dictionary you can create many of the other collections your used to like arrays (and sets too). Heres how it works: Instead of an ordered collection of elements with an index, you place the items in a dictionary and use what would have been the index as the key, and the value becomes, well, the value. For example an array and it's equivalent associative array (aka dictionary):
NSArray *array = #[#"hello", #"world", #"!"];
NSDictionary *dictionary = #{#(1): #"hello",
#(2): #"world",
#(3): #"!"};
This is exactly what your doing when you load in the data from your plist because the first elements key is 0 followed by another dictionary, and I'm supposing that the next element in the list is 1 followed by another dictionary. Inside your parsing function it becomes
NSMutableDictionary *questions = [[NSMutableDictionary alloc] init];
[_json enumerateObjectsUsingBlock:^(NSDictionary *questionDictionary, NSUInteger idx, BOOL *stop) {
//Here I'm treating the index like an NSNumber, if your code is expecting a string instead use
//#(idx).stringValue
[questions setObject:questionDictionary forKey:#(idx)];
//or the modern equivalent
//questions[#(idx)] = questionDictionary;
//If you want to use your 'questions class' then create one and put it into the array instead of the dictionary pulled from the array.
}];
This of course assumes that your api is going to return the JSON questions in the order you want.
Related
I am getting String data from server in the format below. I want to get the value for every tag like phonenumber and name etc. I am able to convert it in array by comma separator. how to get individual values?
Company:Affiliated CO,Organization:TECHNICAL EDUCATION
SOCIETY,Organization:SINHGAD,Organization:National Basketball Association,Person:Parikshit N. Mahalle,PhoneNumber:81 98 22 416 316,PhoneNumber:9120-24100154,Position:Professor,SportsEvent:NBA.
Say your original string is stored in rawString.
You need to :
1) split the string by ,
NSArray *pieces = [rawString componentsSeparatedByString:#","];
2) for each item in this array, split it by :, and add it to a dictionary :
NSMutableDictionary *dict = [NSMutableDictionary new];
for (NSString *piece in pieces) {
NSArray *splitPiece = [piece componentsSeparatedByString:#":"];
// key is at splitPiece[0], value is at splitPiece[1]
dict[splitPiece[0]] = splitPiece[1];
}
Then you'll have a dictionary of what you wanted in the first place.
But as suggested in the comments, it would be far better (and more flexible) for you to receive JSON data.
Edit: your original string shows there are multiple fields named Organization. The code I've given is not designed to handle such cases, it's up to you to build upon it.
If this data is not being returned as a JSON object then you'll have to go with #Clyrille answer. But if it is JSON then NSJSONSerialization:JSONObjectWithData:options:error: will be the way to go.
EXAMPLE
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:/*urlResponse*/ options:0 error:nil];
NSString *company = [json objectForKey:#"Company"];
NSString *Organization = [json objectForKey:#"Organization"];
NSString *Person = [json objectForKey:#"Person"];
NSString *PhoneNumber = [json objectForKey:#"PhoneNumber"];
NSString *Position = [json objectForKey:#"Position"];
NSString *SportsEvent = [json objectForKey:#"SportsEvent"];
I am trying to write a method which allows me to create a different String permutations, based on the values I have stored within 3 different arrays. Currently I have a NSMutableDictionary that contains 3 different keys, and associated to each key we have an NSMutableArray array that contains a list of different String objects.
How woulld I loop through each of my NSMutableArray arrays which are stored within my NSMutableDictionary, and build a string value for each node from the arrays. So essentially, something like the following: A1[0] = "Hello", A2[0] = "There", A3[0] = "Guys", which would essentially build me a string like this: "HelloThereGuys".
Any suggestions, or possibly different approaches to this problem will be appreciated.
First of all I want to agree with hochl. ;-) But I think, that you want to create a string containing a word from each array in the same index position?
NSMutableArray *enums = [NSMutableArray new];
for( NSString *key in dictionary )
{
NSEnumerator *enum = [dictionary[key] objectEnumerator]; // Forgot that in prior version
[enums addObject:enum];
}
while( YES )
{
NSMutableString *line = [NSMutableString new];
BOOL done = NO;
for( NSEnumerator *enum in enums )
{
NString *word = [enum nextObject];
if( word == nil )
{
done = YES;
break;
}
[line addString:word];
}
if (done)
{
break;
}
NSLog (#"%#", line );
}
Did I get you right?
Trying to read a plist and change my font color depending on the option that was selected in the following settings bundle.
The following is how I am trying to accomplish it:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
fontSize = [[dict objectForKey:#"slideSwitched"] floatValue];
if ([[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]) {
noteView.textColor = [UIColor purpleColor];
} else {
noteView.textColor = [UIColor blackColor];
}
Any ideas why this is why my app is crashing? How do I read the values and change the color depending on what was selected?
It appears that the top level of your plist is an array, not a dictionary, because at the top it says "Item 1" where all of your content is within that. So you have a dictionary within an array. So you can change your code like this:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
NSDictionary *dict = array[0];
You could also change the structure of your plist so that you have a dictionary as the root instead of an array.
Also, keys are supposed to be on the left-hand side and their values on the right-hand side, so I don't see a key "noteColor". You have a key "key" with a value "noteColor", so you'll need to make that correction. I'm also not seeing a "slideSwitched" key, though it might just be outside the bounds of your screenshot.
Also the following won't work:
[[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]
Whatever you get from [dict objectForKey:#"noteColor"] isn't going to be a dictionary, so calling valueForKey: on that isn't going to give you what you want.
simply you should do this with document directory
NSString *contentPath=[[NSBundle mainBundle] pathForResource:#"PLIST_FILE_NAME" ofType:#"plist"];
NSDictionary *dictionary=[NSDictionary dictionaryWithContentsOfFile:contentPath];
write your logic after this, wait a minute , its seems like you dont have a key "noteColor" also. check your plist
Here is some example code documented up the wazoo. Hopefully it will help you understand how these plists and dictionaries work. Everything will be based on your plist file (which could definitely be improved upon, but that's up to you as I don't know your specific situation).
Your question is "How do I find color based on user selection?" I will assume you get the user selection as an int. Something like "User selected 7".
//Load your plist dictionary
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
//Get the array of validValues and the array of validTitles
NSArray *valuesArray = [dict objectForKey:#"validValues"];
NSArray *titlesArray = [dict objectForKey:#"validTitles"];
//Now get the user selected index from the validValues array
int arraySelection = -1;
for(int i = 0; i < [valuesArray count]; i++)
{
NSNumber *number = [valuesArray objectAtIndex:i];
if([number intValue] == userSelectedInput)
{
arraySelection = i;
break;
}
}
if(arraySelection == -1)
{
//Not found in array
return;
}
//Now with that index get the title of the object that the user selected
NSString *userSelectedTitle = [titlesArray objectAtIndex:arraySelection];
//Now do your checking on what the user selected based on that:
if([userSelectedTitle isEqualToString:#"Purple"])
...
You could boil this down quite a bit. Currently your validValues array is completely useless. If it were out of order or missing numbers then it would be needed, but straight counting can be achieved by the validTitles array.
I came across few posts here related to what I am doing but I am working with some nested objects that I want to extract.
This is a sample of my returned data - https://gist.github.com/ryancoughlin/8043604
I have this in my header so far :
#import "TideModel.h"
#protocol TideModel
#end
#implementation TideModel
-(id)initWithDict:(NSDictionary *)json {
self = [super init];
if(self) {
self.maxheight = [dictionary valueForKeyPath:#"tide.tideSummaryStats.minheight"];
self.minheight = [dictionary valueForKeyPath:#"tide.tideSummaryStats.maxheight"];
self.tideSite = [dictionary valueForKeyPath:#"tide.tideInfo.tideSite"];
}
return self;
}
#end
I have declared a property for each string and i am accessing it accordingly.
But what I have above doesn't work, maybe because it wont know what to drill in to correct?... Or will it?
tide.tideSummaryStats returns an array.
tide.tideInfo returns an array.
So you can't do -valueForKeyPath: all the way.
Also, this is incorrect: [dictionary valueForKeyPath:...];
it should be : [json valueForKeyPath:...];
because json is the name of the NSDictionary variable passed (not dictionary)
Try this (not sure):
-(id)initWithDict:(NSDictionary *)json {
self = [super init];
if(self) {
NSArray *arrOfTideSummaryStats = [json valueForKeyPath:#"tide.tideSummaryStats"];
NSDictionary *dctOfTideSummaryStats = [arrOfTideSummaryStats objectAtIndex:0];
//since self.maxheight and self.minheight are NSString objects and
//the original keys "minheight" & "maxheight" return float values, do:
self.maxheight = [NSString stringWithFormat:#"%f", [dctOfTideSummaryStats valueForKey: #"maxheight"]];
self.minheight = [NSString stringWithFormat:#"%f", [dctOfTideSummaryStats valueForKey: #"minheight"]];
/*============================================================*/
NSArray *arrOfTideInfo = [json valueForKeyPath:#"tide.tideInfo"];
NSDictionary *dctOfTideInfo = [arrOfTideInfo objectAtIndex:0];
self.tideSite = [dctOfTideInfo valueForKey:#"tideSite"];
}
return self;
}
Similar Questions:
How to parsing JSON object in iPhone SDK (XCode) using JSON-Framework
Getting array elements with valueForKeyPath
Keypath for first element in embedded NSArray
Recently had to create a app that worked with a remote RESTful server that returned JSON data and was then deserialised into an object for graphing.
I used unirest for the requests and responses and then deserialised the returned JSON into an object. Below is an extract of the code where "hourlySalesFigures" within dictionary "jsonResponseAsDictionary" was a JSON collection of 24 figures which I put into an array. Please note the function is a lot larger but I removed anything which I thought was distracting.
- (PBSSales*) deserializeJsonPacket2:(NSDictionary*)jsonResponseAsDictionary withCalenderType:(NSString *)calendarViewType
{
PBSSales *pbsData = [[PBSSales alloc] init];
if(jsonResponseAsDictionary != nil)
{
// Process the hourly sales figures if the day request and returned is related to Daily figures
if([calendarViewType isEqualToString:#"Day"]){
NSArray *hourlyFiguresFromJson = [jsonResponseAsDictionary objectForKey:#"hourlySalesFigures"];
PBSDataDaySales *tmpDataDay = [[PBSDataDaySales alloc] init];
NSMutableArray *hSalesFigures = [tmpDataDay hourlySalesFigures];
for(NSInteger i = 0; i < [hourlyFiguresFromJson count]; i++){
hSalesFigures[i] = hourlyFiguresFromJson[i];
}
[[pbsData dataDay] setHourlySalesFigures:hSalesFigures];
[pbsData setCalViewType:#"Day"];
}
}
return pbsData;
}
This is my first question to Stack Overflow. I have been using this site for a while and have used it's resources to figure out answers to my programming questions but I'm afraid I can't find the answer I'm looking for this time.
I've created these five strings:
//List five items from the book and turn them into strings
//1 Josh the Trucker
NSString *stringJosh = #"Josh the Trucker";
//2 The Witch from the Remote Town
NSString *stringWitch = #"The Witch from the Remote Town";
//3 Accepting the curse rules "Willingly and Knowingly"
NSString *stringRules = #"Accepting the curse rules, --Willingly and Knowingly--";
//4 Josh's time left to live--Five Days Alive Permitted
NSString *stringFiveDays = #"Josh's time left to live--Five Days Alive Permitted";
//5 The Fire Demon Elelmental
NSString *stringDemon = #"The Fire Demon Elelmental";
Then, I've put them in an array:
//Create an array of five items from the book
NSArray *itemsArray = [[NSArray alloc] initWithObjects:
stringJosh,
stringWitch,
stringRules,
stringFiveDays,
stringDemon,
nil];
Then, I created this mutable string where I need to loop through the array and append the items to a UIlabel.
NSMutableString *itemsString = [[NSMutableString alloc] initWithString:
#"itemsArray"];
Here's the loop, which displays the items in the console log.
for (int i=0; i<5; i++)
{
NSLog(#"Book Item %d=%#", i, itemsArray[i]);
}
My question is, how do I append these items into the UIlabel?
These functions are in my appledelegate.
In my viewDidAppear function (flipsideViewController) I have:
label8.text =""----thats where the looped info needs to go.
How do I do this?
I feel I need to put them together and append where the NSLog should be...but how do I transfer that info to the textlabel?
I hope I explained myself.
We haven't done ANY append examples, I guess this is where I need to get answers from the "wild"
This is the wildest coding environment I know so I'm hoping I can find some direction here.
Thanks for taking a look!
Once you have all your strings that you want to concatenate in NSArray you can combine them with single call (with whatever separator you want):
NSString *combinedString = [itemsArray componentsJoinedByString:#" "];
If you need more complex logic you can use NSMutableString to create result you want while iterating array, i.e.:
NSMutableString *combinedString = [NSMutableString string];
[itemsArray enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
[combinedString appendFormat:#"Book Item %d=%# ", idx, obj];
}];
Note also that it is better to iterate through collections using fast enumeration or block enumeration rather than using plain index-based for loop.
NSMutableString *labelText = [NSMutableString string];
int i = 0;
for (NSString *item in itemsArray)
[labelText appendFormat:#"Book Item %d=%#\n", i++, item];
label8.text = labelText;
DO this
UILabel *mainlabel;
mainlabel.text = [origText stringByAppendingString:get];
Add your text to mainlabel.. orig text is mutable string or else in forloop just append array object at index text to label.put above line of code in forloop