I'm getting data from a MySQL-database in JSON-format. In an Objective-C file the data gets modified and put into an NSMutableArray ("_data"). By the function "itemsDownloaded" the delegate gets notified as soon the download from the database is finished and receives the "_data"-array.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Create an array to store the data
NSMutableArray *_data = [[NSMutableArray alloc] init];
// Parse the JSON that came in
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:_downloadedData options:NSJSONReadingAllowFragments error:&error];
// Loop through Json objects, create question objects and add them to our questions array
for (int i = 0; i < jsonArray.count; i++)
{
NSDictionary *jsonElement = jsonArray[i];
// Create a new data object and set its props to JsonElement properties
Data *newData = [[Data alloc] init];
newData.sozialversicherungsnummer = jsonElement[#"Sozialversicherungsnummer"];
newData.messzeitpunkt = jsonElement[#"Messzeitpunkt"];
newData.puls = jsonElement[#"Puls"];
newData.sauerstoffgehalt = jsonElement[#"Sauerstoffgehalt"];
// Add this question to the locations array
[_data addObject:newData];
}
// Ready to notify delegate that data is ready and pass back items
if (self.delegate)
{
[self.delegate itemsDownloaded:_data];
}
}
My aim is to access the properties "sozialversicherungsnummer", "messzeitpunkt", "puls" and "sauerstoffsättigung" of "newData" (in the above file). The class "Data" defines these four properties.
Now I want to display these properties inside of a chart in a swift file. For example I want to display "messzeitpunkt" on the x-axis and "puls" on the y-axis. I know how to handle the chart but my problem is that I don't know how to get access to the properties inside of the swift file.
If I write these lines into my swift file:
var data: NSArray = [];
func itemsDownloaded(items: [AnyObject]!) {
data = items
print("\(data)")
}
I get this on my output:
(
"<Data: 0x7ca5ff60>",
"<Data: 0x7ca5dab0>",
"<Data: 0x7be497e0>",
"<Data: 0x7ca42c00>"
)
Can somebody please help me?
The problem is that you don't want an NSArray. Swift doesn't know what's inside an NSArray. You want a Swift array, namely a [Data]. That way, Swift knows that each item is a Data, and you can access its properties.
Your output is:
(
"<Data: 0x7ca5ff60>",
"<Data: 0x7ca5dab0>",
"<Data: 0x7be497e0>",
"<Data: 0x7ca42c00>"
)
And that is exactly what you want and expect! You have an array of four Data objects. The only problem is that you have forgotten to tell Swift about this. You need to type the array as a [Data] or cast it to a [Data].
For example, where you are now saying:
func itemsDownloaded(items: [AnyObject]!) {
data = items
print("\(data)")
}
Try saying this:
func itemsDownloaded(items: [AnyObject]!) {
let datas = items as! [Data]
datas.forEach {print($0.messzeitpunkt)}
}
That is legal, because now you have told Swift what is in the array. And you will see that your data is there, exactly as you intend.
Related
I am developing simple app in iOS that gets data web api my code returned json data correctly but when I want to specific for example student name from json returned null.
Here is my data :
{
Sudent(
{
{"id":"20",
"name":"Alan",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"London"},
{
"id":"40",
"name":"John",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"usa"},
"id":"50",
"name":"Nora",
"email":"simpl#gmail.com",
"phone":"1234567890",
"location":"kenya"},
})}
Here my code that gets data as json and stored NSMutableArray named Student:
-(void)proxydidFinishLoadingData:(id)data InMethod:(NSString*)method
{
if ([method isEqualToString:#"getstudentdata"]){
defaultDict = [[NSMutableDictionary alloc]init];
[defaultDict addEntriesFromDictionary:[NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]];
Student = [defaultDict objectForKey:#"data"];
}
}
this codes it works ok and correctly and returned json data but the problem is when I want to get specific index such as names of students it is not work it returns null value.
the code that does this work is here:
NSMutableDictionary *response = [[defaultDict valueForKey:#"data"] mutableCopy];
NSString *name = [[response valueForKey:#"name"]];
];
NSLog(#"%#" ,name);
Please help me this to get student names
You are checking "name" key in "data" key, but in fact it is present in "Student" key.
Parse to Student object and using for loop get one by one "name" key value.
Use this site http://www.json4swift.com/ to create Model.(Just you have to Put JSON response here).
Var dataModelArray = [Your_Model_Type]()
if let data = data[“student”] as? [String: AnyObject] {
dataModelArray = Your_Model_type.modelsFromDictionaryArray(array: data)
}
//And you will have array of data in your dataModelArray
//Example you can access like this
dataModelArray[0].name
I am running a Kii Query that returns the expected number of results. However the results array contains object formatted as follow
"<KiiObject: 0x130471ae0>"
this is the output from
NSLog(#"%#",results);
I am confident that the Query is working correctly as i can add and remove objects from the bucket and the number of results in the array changes according, i just don't know how to take the results and get the corresponding object.
I have gone over everything in the Kii Doc's
link to Kii Docs
The result is to short to be the object id(uuid string) and i can't find any other reference in the docs that makes sense.
You can refer to bellow snippet
NSError *error = nil;
// Build "all" query
KiiQuery *allQuery = [KiiQuery queryWithClause:nil];
// Create an array to store all the results in
NSMutableArray *allResults = [NSMutableArray array];
// Create a placeholder for any paginated queries
KiiQuery *nextQuery;
// Get an array of KiiObjects by querying the bucket
NSArray *results = [bucket executeQuerySynchronous:allQuery
withError:&error
andNext:&nextQuery];
if (error != nil) {
// Error handling
return;
}
//obtain single KiiObject
KiiObject* firstObject = allResults.firstObject; // now you should get all the object properties
NSLog(#"MaxScore : %#",[firstObject getObjectForKey:#"maxScore"]); //i.e to get "maxScore" value
Below is the links for querying KiiObjects.
http://docs.kii.com/en/guides/ios/managing-data/object-storages/querying/
Sorry guys, this problem I am running into is pretty trivial. I just can't wrap my head around it so hope someone can help me. Your help is really appreciated. I am getting JSON data through NSURLConnectDelegate with a web API. I get something like this back:
(
{
id = 340
name = Vicent },
{
id = 339
name = Johny },
{
id = 338
name = Eric }
)
and I save it in a NSMutableArray as a global variable. Now, I have a NSSet of "ids". For example:
{
340, 339
}
In the numberOfRowsInSection, I return the set's count. I am trying to load only the ids in the NSSet from the array with the data saved from the webAPI, so I do something like this in cellForRowIndexPath:
for (NSNumber *num in [set allObjects]) {
NSString *newString = [[savedArray objectAtIndex:indexPath.row]
NSString *new = [num stringValue];
if ([new isEqual:newString]) {
}}
How can I just populate the ids I want?
The JSON makes it look like you have an array of dictionaries, which is a reasonable data structure to use as the data source for a table view.
It sounds like you're trying to filter your array to only include the items that are in your set. Is that right?
If so, you could write code that would create a new array containing the subset of your array elements who's ID is also in your set. There are at least a half-dozen ways to do that. One fairly simple approach would be to use the NSArray method indexesOfObjectsPassingTest. You'd pass that method a block of code that would check each array element to see if it's id object was in your set.
That would give you an NSIndexSet with the indexes of the items in your array who's ID are in your set. Then you could use the NSArray method objectsAtIndexes to get an array of only the objects that are also in the set. Something like this (Assuming that your array of dictionaries is called savedArray and your set is called allObjects:
//get the indexes of items in the array savedArray who's id appears in the set allObjects
NSIndexSet *indexes = [savedArray indexesOfObjectsPassingTest:
^(NSDictionary *obj,
NSUInteger idx,
BOOL *stop)
{
return [allObjects member: obj[#"id"]] != nil;
}
];
//Now build an (immutable) array of just the objects who's ID are in the set
NSArray *subArray = [savedArray objectsAtIndexes: indexes];
The array subArray created above is immutable. If you need a mutable array you would need to make a mutable copy, which is a one-line change.
Disclaimer: I still struggle a little with block syntax, so the above might not be exactly correct, but it gives you the general idea.
I need to parse a json string to a NSMutableArray... I did it as follows:
JsonString = "{
"list":[
{
"IDI":{
"IDI_ID":1
},
"PAR_VPARAM":"param1",
"PAR_VALUE":"value1"
},
{
"IDI":{
"IDI_ID":2
},
"PAR_VPARAM":"param2",
"PAR_VALUE":"value2"
},
{
"IDI":{
"IDI_ID":3
},
"PAR_VPARAM":"param3",
"PAR_VVALUE":"value3"
}
]
}";
NSData *data = [JsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&err];
NSMutableArray *resultArray = [json objectForKeyedSubscript:#"list"];
I have an object called PARAMETERS, and it has the same structure of a single item of JSON: "list". When i parse it, it works, the problem is in the object inside of each item in the json: "IDI", always parse with null value.
for(NSObject *obj in resultArray){
Parameters *paritem = (Parameters *)obj;
int test = paritem.IDI.IDI_ID; //Error here!
}
How can i do it?
NSJSONSerialization won't map your JSON data to your custom class. It will provide NSString, NSNumber, NSDictionary, and NSArray objects (or their mutable counterparts, if you specify the right NSJSONReadingOptions).
If you want to map this data to your Parameters class, you have to provide that logic yourself. You cannot simply cast NSDictionary.
for(NSObject *obj in resultArray){
Parameters *paritem = [[Parameters alloc] init];
paritem.PAR_VPARAM = obj[#"PAR_VPARAM"];
paritem.PAR_VALUE = obj[#"PAR_VALUE"];
// To capture the IDI property, you will either have to
// define a new IDI class with a property named "IDI_ID",
// live with NSDictionary, or add an "IDI_ID" property
// to your Parameters class.
// In this example, I left the value as a dictionary.
paritem.IDI = obj[#"IDI"];
// Here's how you would get the IDI_ID:
NSNumber *IDI_ID = paritem.IDI[#"IDI_ID"];
}
With that out of the way, here are a couple unsolicited stylistic tips:
For variables and properties in Obj-C, lowerCamelCase is conventional. Instead of paritem.PAR_VPARAM, use parItem.parVParam (note the capital I in parItem).
Your class names should have a two- or three-letter "namespace" (much like NSString, UIView, or CGPoint). If you can't come up with a couple letters to represent this specific project, use an abbreviation of your company's name. If all else fails, use your initials.
Your parameter names are extremely vague, and somewhat redundant. Does every property really need to be prefixed with PAR_? Do you really need IDI_ID to be nested within the IDI property of your Parameters object? You could make your code much more readable by being more concise.
Here's what your code might look like if you took this advice (I'm making some assumptions of your source data):
for(NSObject *obj in resultArray){
APParameters *parItem = [[APParameters alloc] init];
parItem.parameterName = obj[#"PAR_VPARAM"];
parItem.parameterValue = obj[#"PAR_VALUE"];
// To capture the IDI property, you will either have to
// define a new IDI class with a property named "IDI_ID",
// live with NSDictionary, or add a property to your
// Parameters class which holds the IDI_ID value directly.
// In this example, I grabbed the IDI_ID value directly.
parItem.itemID = obj[#"IDI"][#"IDI_ID"];
}
First of all, I'd suggest you to cast JSON data to an NSArray instead of NSMutableArray if you're not going to add or remove new objects to the array.
About "IDI" indices, they are not being parsed as strings like other indices since they're dictionaries. You also should create Parameters object manually instead of casting directly.
An example:
// In Parameters.h
#property (nonatomic, strong) NSString *PAR_VPARAM;
#property (nonatomic, strong) NSDictionary *IDI;
Then after parsing JSON,
for (NSDictionary *obj in resultArray){
Parameters *paritem = [[Parameters alloc] init];
paritem.PAR_VPARAM = [obj valueForKey:#"PAR_VPARAM"];
paritem.IDI = [obj valueForKey:#"IDI"];
int test = (int)[paritem.IDI valueForKey:#"IDI_ID"];
}
This should work well and you can create new properties for other JSON indices.
This question already has answers here:
Appending NSDictionary to other NSDictionary
(3 answers)
Closed 9 years ago.
Im working with flickr and in the sample fetch I get this:
{
"api_key" = {
"_content" = 3c6eeeae4711a5f478d3da796750e06b;
};
format = {
"_content" = json;
};
method = {
"_content" = "flickr.test.echo";
};
nojsoncallback = {
"_content" = 1;
};
stat = ok;
}
This is a dictionary with 5 entries (api_key, format, method, nojsoncallback & stat). The first 4 entires are dictionaries themselves.
First off, there is a 5th element in my original dictionary, which is not a dictionary, it is simply the last entry in the original dictionary (the one stat=ok). Furthermore, I want the _content key in every subentry to appear in my individual cells but I dont want to hardcode any values. Do I HAVE to setup an array?
NSDictionary has a nifty little method called valueForKeyPath. Thats your savior here.
[dict valueForKeyPath:#"api_key._content"]
[dict valueForKeyPath:#"format._content"]
[dict valueForKeyPath:#"method._content"]
[dict valueForKeyPath:#"nojsoncallback._content"]
What it does is traverse the key path and fetch the values of content in each JSON substructure. Otherwise you would have had to written a for-loop and loop through it. Neat huh?
Try this
for (NSString *key in dictionary){
id object = dictionary[key];
if ([object isKindOfClass:[NSDictionary class]]) {
//Now you can work on the dictionary object
}
}