I am trying to print MySQL result sets with PHP in JSON format, and read it with iOS.
This is my JSON-string:
[{"partnerid":"1","code":"SUMU6003","partnerName":"Company name","street":"Some Street 5323","zipCode":"8732","city":"Berlin","languages":"English","workers":"Name 1, Name 2","lineup":"Kids"},{"partnerid":"2","code":"DEMO8884","partnerName":"Partner 2","street":"Third street 2","zipCode":"383838","city":"Berlin","languages":"Greek","workers":"Petra","lineup":"Kids"}]
In this method I get the NSDictionary:
#pragma mark - ServiceConnectorDelegate -
-(void)requestReturnedData:(NSData *)data {
NSDictionary *dictionary = [NSDictionary dictionaryWithJSONData:data];
# process dictionary and grep strings from json-string
# ...
}
Can you please tell me how to access the different result sets in a loop? I want to access each key separately.
I know that the NSDictionary contains data, because NSLog(#"%#",dictionary); prints:
2012-12-20 19:13:20.661 myapp[576:907] (
{
city = Berlin;
code = SUMU6003;
languages = English;
lineup = Kids;
partnerName = "Company name";
partnerid = 1;
street = "Some Street 5323";
workers = "Name 1, Name 2";
zipCode = 8732;
},
{
city = Berlin;
code = DEMO8884;
languages = Greek;
lineup = Kids;
partnerName = "Partner 2";
partnerid = 2;
street = "Third street 2";
workers = Petra;
zipCode = 383838;
}
)
Thank you very much for the help.
Sometimes introspection can be useful here. For instance NSLog(#"dictionary is of type: %#", [dictionary class]);
The reason I say that is based on your output it appears that dictionary is in fact an array containing two NSDictionaries. If that is the case you would want to do something like this:
for (NSDictionary *actualDictionary in dictionary<this is really an array>)
{
NSString *myStringValue = [actualDictionary objectForKey:#"city"];
// etc...
}
You have to find out what data types your actually dealing with first though.
Do this:
#import <objc/runtime.h>
NSLog(#"The class name is %s", object_getClassName(dictionary);
the response dictionary you have is containing array of dictionaries so you can run the dictionary values by fast enumerating the dictionary and cast each as dictionary and get its value like the following :
-(void)requestReturnedData:(NSData *)data {
NSDictionary *dictionary = [NSDictionary dictionaryWithJSONData:data];
# process dictionary and grep strings from json-string
for(id item in dictionary )
{
NSDictionary *dic = (NSDictionary *)item;
NSLog(#"%#",[dic objectForKey:#"city"]);
NSLog(#"%#",[dic objectForKey:#"code"]);
......
}
}
Related
Like the title says, my UITextView is setup to print data found within "userName". Instead of behaving appropriately, it prints "userName".
PHP code:
<?php
header('Content-Type: application/json');
$arr = array ('userName'=>'derekshull', 'userBio'=>'This is derekshulls bio','userSubmitted'=>'15');
echo json_encode($arr);
?>
Objective C:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *myURL = [[NSURL alloc]initWithString:#"http://techinworship.com/json.php"];
NSData *myData = [[NSData alloc]initWithContentsOfURL:myURL];
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:&error];
if(!error)
{
for (id element in jsonArray) {
textview.text = [NSString stringWithFormat:#"%#", [element description]];
// text view will contain last element from the loop
}
}
else{
textview.text = [NSString stringWithFormat:#"Error--%#",[error description]];
}
}
What am I missing here? Also, when run, the application does not crash and give error. However, the following is documented in the DeBug Area.
2014-03-24 20:20:53.258 testtest[11434:60b] Unknown class textview in Interface Builder file.
I don't currently have a OSX computer available so I can't evaluate my code.
It seems like the array you have in you PHP code is an associative array and the JSON will be similar. When you are parsing the JSON string in your Obj-C code try assigning it to a NSDictionary, this way you will have access to the associative array.
NSDictionary *jsonArray = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:&error];
When using the data in the jsonArray don't iterate it, use the NSDictionary method objectForKey to get get the value you want.
As an example, to get the value of userName, you can do this:
[jsonArray objectForKey: #"userName"] // jsonArray is not actually a array, but a dictionary now
And to change the text of the textview, you can do the following:
textview.text = [NSString stringWithFormat:#"%#", [jsonArray objectForKey: #"userName"]];
Ask if something is unclear!
Cheers!
I have This PHP Code With Arrays And Loops, Trying to convert it into Objective-c "iOS"
foreach($arr as $item)
{
$data[$item[date]][]=$var;
}
What i did so far is :
for(id theKey in result)
{
leEvent[[NSString stringWithFormat:#"%#",[theKey objectForKey:#"event_date"]]]=#"asd";
}
but it still overlaps each other if same key.
So any Idea ? Thanks in advance.
UPDATE :
I have this JSON:
[{"id":"1","title":"test","event_date":"2014-01-28","description":"this
is a test desc ","time_stamp":"2014-01-28
13:04:12"},{"id":"2","title":"test2","event_date":"2014-01-29","description":"this
is a test desc2 ","time_stamp":"2014-01-28
13:21:36"},{"id":"3","title":"test3","event_date":"2014-01-29","description":"this
is a test desc3","time_stamp":"2014-01-28 13:21:36"}]
I want To make out of it Array That They key of Array is the Date : and inside each date other information
Expmple $data['2014-01-29'] should have 2 arrays in side it but i want to do it in iOS
We have "for in" loop in objective C
For example:
for( NSNumber *num in numArray)
{
//Write your code here
}
Let me know if this is not what you want or you need some more info
Update:
You don't need a ForLoop in here.
Let's say result is your NSDictionary object.
So,
[result objectForKey:#"event_date"]
will give object for key "event_date".
By your code.. It seems like you are trying to set value for the key "event_date".
So your code would be something like this,
[result setObject:#"asd" forKey:#"event_date"];
Let me know if it does not help.
I would suggest you to use JSONSerialization. This might ease up your task.
NSError* err = nil;
NSString* myJSONFile = [[NSBundle mainBundle] pathForResource:#"myFileName" ofType:#"json"];
NSArray* dataTypes = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:myJSONFile] options:kNilOptions error:&err];
NSLog(#"Imported data Types: %#", dataTypes);
//This will print the data you just imported..
NSMutableArray *myArray= [[NSMutableArray alloc]init];
[dataTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
if([obj objectForKey:#"event_date"] isEqualTo:#"myDate")
{
[myArray addObject:obj];
}
}];
I've checked this code... Working fine.. Let me know if any issues are there
I'm building an IOS app that queries a database. I keep getting the results out of order, and in some functionality in the app, like comments, it's crucial that I get them in order. It's obvious JSON is returning a dict, but I need the results ordered. Here's the server side code:
function sendResponse($status = 200, $body = '', $content_type = 'text/html') {
$status_header = 'HTTP/1.1 ' . $status . ' ' . getStatusCodeMessage($status);
header($status_header);
header('Content-type: ' . $content_type);
echo $body;
}
$result = array();
$i = 0;
$sqlGetComments = mysqli_query($link, "SELECT * FROM photo_comments WHERE photo_id='$photoID' ORDER BY post_date DESC");
while ($row = mysqli_fetch_array($sqlGetComments)) {
$result[$i] = array(
'photoID' => $row['photo_id'],
'userID' => $row['userID'],
'username' => $row['username'],
'comment' => $row['comment'],
'postedDate' => $row['post_date'],
);
$i++;
} // end while
sendResponse(200, json_encode($result));
I have IOS code that parses that, but out of order from how I need it. So there has to be something I can do server side.
Update, Here is the client side code:
[request setCompletionBlock:^{
NSString *responseString = [request responseString];
[self updateComments:responseString];
}];
- (void)updateComments:(NSString *)update {
NSDictionary *root = [update JSONValue];
NSEnumerator *enumerator = [root keyEnumerator];
id key;
while (key = [enumerator nextObject]) {
NSDictionary *value = [root objectForKey:key];
_photoID = [value objectForKey:#"photoID"];
NSString *photoID = [value objectForKey:#"photoID"];
NSString *userID = [value objectForKey:#"userID"];
NSString *username = [value objectForKey:#"username"];
NSString *comment = [value objectForKey:#"comment"];
NSString *postedDate = [value objectForKey:#"postedDate"];
NSString *cellString = [NSString stringWithFormat:#"%# \n %# \n %#", username, comment, postedDate];
[_queryResultsMessage addObject:cellString];
}
[_tableView reloadData];
}
Here's the print out keeping in mind that "Test" string in the comment field is how the JSON string should print out:
{"1":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 6","postedDate":"7 hrs ago"},"2":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 5","postedDate":"8 hrs ago"},"3":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 4","postedDate":"8 hrs ago"},"4":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 3","postedDate":"8 hrs ago"},"5":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 2","postedDate":"8 hrs ago"},"6":{"photoID":"1","userID":"17","username":"kismet","comment":"Test 1","postedDate":"8 hrs ago"}}
It prints out OK but I'm guessing it's getting jumbled when being assigned to NSDictionary. If nobody has any answers, I'll try to fiddle around with it by assigning it to an NSArray and see if I can parse that somehow.
A little client side IOS hackery was needed
For those who are still interested in the solution:
NSDictionary *userData = [update JSONValue];
NSArray *keys = [[userData allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSMutableArray *array = [NSMutableArray arrayWithCapacity: [keys count]];
int i = 0;
for (NSString *key in keys) {
[array addObject: [userData objectForKey: key]];
i++;
}
for (NSDictionary *myDict in array) {
NSString *comment = [myDict objectForKey:#"comment"];
NSLog(#"USERCOMMENT %#", comment);
}
Returns JSON all in order:
USERCOMMENT Test 6
USERCOMMENT Test 5
USERCOMMENT Test 4
USERCOMMENT Test 3
USERCOMMENT Test 2
USERCOMMENT Test 1
It's worth noting that
- You're requesting the items ordered from MySQL
- Ergo, PHP is generating the JSON in order.
Because of this, I would simply suggest editing the loop in PHP...
while ($row = mysqli_fetch_array($sqlGetComments)) {
$result[$i] = array(
'photoID' => $row['photo_id'],
'userID' => $row['userID'],
'username' => $row['username'],
'comment' => $row['comment'],
'postedDate' => $row['postedDate'],
'orderBy' => $i
);
$i++;
} // end while
... and organising them by "orderBy" in Obj-C.
Note, all I've done is add an extra variable to the JSON items - "orderBy"; as the MySQL results will be in the correct order, and thus are parsed in the correct order, this "orderBy" variable could act like a key.
It's a while since I've worked with the iOS SDK - but I'm pretty sure they will be a method to sort an NSMutableArray; if not - a simple loop could work; requesting each object with the key of x, whilst x < length of NSMutableArray. I'll look up the "correct" way of doing it however, as that will bug me!
I would suggest investigating the real reason behind the results coming in out of order though! That shouldn't be happening! I haven't done similar in iOS but I would assume this isn't the correct behaviour when requesting JSON.
Troubleshooting steps may be checking the returned JSON in-browser or on a desktop environment and ensuring the PHP is returning it correctly, then seeing how it's returned to the app - ensuring all data is present and whether there is a pattern to the distortion of order.
Edit: I've noticed you're saying it's returning an array of dictionaries. My bad.
I did find another question that goes into sorting an array of dictionaries.
In your MySql query, you are sorting on post_date, but then refer to postedDate when adding it to your results array. Do both exist?
If post_date does not in fact exist then your database query is not sorting as you expect...
I hope someone can help me put because I've trying the whole day :( ( newly stuff )
I have a database mySQL, which contains one table "products" ( two rows : "id" and "stock" ).
And I want my ios5 app to send an "id" and receive the "stock" of that product.
In my PHP code:
echo json_encode(array(
'id'=>$id,
'stock'=>$stock, ));
Which I believe sends a JSON to my app, my app receives this JSON in a function called:
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSString *responseStringWEB = [request responseString];
NSLog(#"STRING:: %# \n", responseStringWEB); //3
NSDictionary *responseDict = [responseStringWEB JSONValue];
NSLog(#"DICT: %# \n", responseDict); //3
NSString *id_producto = [responseDict objectForKey:#"id"];
NSString *stock = [responseDict objectForKey:#"stock"];
NSLog(#"ID: %#\n", id_producto); //3
NSLog(#"stock: %#", stock); //3
}
and checking the console I get:
**`STRING`::**
Connection establishedDatabase selected..
***{"id":"3","stock":"46"}***
Connection closedDesconectado
2011-12-26 18:58:57.170 CaeDeCajon[1998:16403] Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x984aeb0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
2011-12-26 18:58:57.171 CaeDeCajon[1998:16403] **`DICT`**: (null)
2011-12-26 18:58:57.171 CaeDeCajon[1998:16403] **`ID`**: (null)
2011-12-26 18:58:57.171 CaeDeCajon[1998:16403] **`stock`**: (null)
The question is : I do not know what format the JSON is coming ( array, How should I parse the NSstring responseStringWEB to get those two values ( ID and STOCK ). It seems I receive them from the database but I do not reach to extract them.
HELP :) thank you ,
EDITING::
Thanks. It really Helped.
It seemed that there has had something to do with the multiple echos I used in the PHP code. Now I only have one echo, sending data in json format. It works perfectly with my database and my app: I receive the whole table ( "id" and "stock" ) of all items. Thanks.
But I have found another obstacle ( no wonder ), is that I need to change the database once the products have been sold, and as they´re not usually sold 1 by 1 must post arrays into PHP,, my intention is to POST the id and reductor(reductor represent how many products of that "id" were sold ) of the products/items affected ( array_id and array_reductor).
IOS5 CODE:
NSArray *array_id=[[NSArray alloc]initWithObjects:#"0",#"3",#"5", nil];
//with the id products;
NSArray *array_reductor=[[NSArray alloc]initWithObjects:#"10",#"5",#"40", nil];
//with the number of products sold ( so I have to decrease the previous stock number in the database by these to obtain the current stock numbers ).
NSURL *url=[[NSURL alloc]initWithString:#"http://www.haveyourapp.com/promos/"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:array_id forKey:#"id"];
[request setPostValue:array_reductor forKey:#"reductor"];
[request setDelegate:self];
[request startAsynchronous];
MY PHP FILE:
if (isset($_POST['id'])&&isset($_POST['reductor'])) // check if data is coming
{
$id = array(); // I create arrays
$reductor = array();
$id=$_POST['id']; // and store arrays in them ( At least is what I believe )
$reductor=$_POST['reductor'];
$connection = new createConnection(); //i created a new object
$connection->connectToDatabase(); // connected to the database
$connection->selectDatabase();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Stock reduction in the items affected////////////////////////////////
$num=mysql_numrows($id);
$i=0;
$stock_anterior=array();
while ($i < $num) {
$query=" SELECT stock FROM productos WHERE id = $id[$i]";
$stock_anterior[$i] = mysql_query($query);
++$i;
}
$l=0;
$num2=mysql_numrows($id);
while ($l < $num2) {
$stock_reductor[$l] = $stock_anterior[$l] - $reductor[$l];
$query = "UPDATE productos SET stock = '$stock_reductor[$l]' WHERE id = $id[$l] ";
mysql_query($query);
++$l;
}
$connection->closeConnection();
But my code is not working, I don not know if the problem is in my app or in the PHP file ( likely ), but how can I receive those two arrays and work with them????
Thanks in advance
I spend a lot of time on stack Overflow: VERY USEFULLLLLLLL!!!!!
json_encode works only with UTF-8 encoded data, so when find a invalid character, it returns NULL for all.
Check your data is encoded in UTF-8.
Also check your file is using UTF-8.
An alternative to json_encode:
// función interna: comprueba si un array es puro o no
// es puro si sus índices son: 0, 1, 2, ..., N
function aputio($a) {
$i=0;
foreach ($a as $n=>$v) {
if (strcmp($n,$i)) return(true);
$i++;
}
return(false);
}
// cambiar quotes, \n y \r para devolver cadenas válidas JSON
function qcl2json($qcl) {
return str_replace('"','\"',str_replace("\n",'\n',str_replace("\r",'\r',$qcl)));
}
// devolver variable en formato json
function ajson($av,$level=0,$utf8=false) {
if (($av===null) && !$level) return("null");
if (!is_array($av)) return (gettype($av)=="integer"?$av:'"'.($utf8?utf8_encode($av):$av).'"');
$isobj=aputio($av);
$i=0;
if (!$level) $e=($isobj?"{":"["); else $e="";
foreach ($av as $n=>$v) {
if ($i) $e.=",";
if ($isobj) $e.=(is_numeric($n) && !is_string($n)?$n:"\"".qcl2json($utf8?utf8_encode($n):$n)."\"").":";
if (!is_array($v)) {
if (is_bool($v)) $e.=($v?"true":"false");
else if ($v==NULL) $e.='""';
else if (is_int($v)||is_double($v)) $e.=$v;
else $e.='"'.qcl2json($utf8?utf8_encode($v):$v).'"';
} else {
$e.=(count($v)
?(aputio($v)
?"{".ajson($v,$level+1)."}"
:"[".ajson($v,$level+1)."]")
:"{}");
}
$i++;
}
if (!$level) $e.=($isobj?"}":"]");
return($e);
}
Avoid using this functions if you can use UTF-8.
your json encoding is correct try add this line to your php script because IOS may be really strict with the response.
add this to your php script:
header('Content-type: application/json');
besides that check you are matching the case of your parameters. I see your php script sends id but looks like your ios script is looking for ID
Check the PHP script output using a tool such as HTTPScoop. I suspect that something is wrong, based on the console output, which contains the lines Connection establishedDatabase selected.. and Connection closedDesconectado...
**`STRING`::**
Connection establishedDatabase selected..
***{"id":"3","stock":"46"}***
Connection closedDesconectado
It looks like you've got some logging from that script that is printed before the JSON starts, which isn't accepted by the JSON parser on the iOS end.
I am trying to load png images into UIImage from a SQlite database. The images are stored as binaries in a blob column. I've created the binaries using PHP fread, so I guess my first question is: is this a form of output that objective c will be able to use? If this isn't causing issues, then there must be an error somewhere in my objective c code.
Here is how I load the data:
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(selStmt, 2) length:sqlite3_column_bytes(selStmt, 2)];
When I NSLog data, I am able to see the numbers (a long list) for the 7 images I currently have. I assume I am getting the data from the column.
What is strange is that when I send this data to an UIImage, I get nulls:
item.archThumb = [UIImage imageWithData:data];
or
UIImage *theimage = [[UIImage alloc]init];
theimage =[UIImage imageWithData:data];
My second question is: am I missing an extra step?
Here is the method I am using to read the items from the database:
-(void)readItems{
if (!database) return; // earlier problems
// build select statement
if (!selStmt)
{
const char *sql = "SELECT items.arch_id, items.arch_name, arch_thumbs.thumbs_image FROM items LEFT JOIN arch_thumbs ON items.arch_id = arch_thumbs.thumbs_arch_id ORDER BY items.arch_name ASC;";
if (sqlite3_prepare_v2(database, sql, -1, &selStmt, NULL) != SQLITE_OK)
{
selStmt = nil;
}
}
if (!selStmt)
{
NSAssert1(0, #"Can't build SQL to read items [%s]", sqlite3_errmsg(database));
}
// loop reading items from list
int ret;
while ((ret=sqlite3_step(selStmt))==SQLITE_ROW)
{ // get the fields from the record set and assign to item
// primary key
NSInteger n = sqlite3_column_int(selStmt, 0);
Item *item = [[Item alloc] initWithPrimaryKey:n]; // create item
// item name
char *s = (char *)sqlite3_column_text(selStmt, 1);
if (s==NULL) s = "";
item.name = [NSString stringWithUTF8String:(char *)s];
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(selStmt, 2) length:sqlite3_column_bytes(selStmt, 2)];
if (sqlite3_column_blob(selStmt, 2) != NULL) {
item.archThumb = [UIImage imageWithData:data];
NSLog(#"the image is:%#", item.archThumb);
}
else{
NSLog(#"read a NULL image");
}
[items addObject:item]; // add to list
[item release]; // free item
[data release];
}
sqlite3_reset(selStmt); // reset (unbind) statement
}