Reputation: 1304
I have a php web service returning JSON to an objective iphone app using NSJSONSerialization. I've called the web service manually and confirmed the json is valid however it's returning
The operation couldn’t be completed. (Cocoa error 3840.)
On top of this sometimes it works and other times it does not. The times it does not work the method
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
actually gets called twice. The php web service code is:
$cu = new CacheUtil(getGlobalSetting("category_cache_file_name"));
$cu -> keyValue = FALSE;
$cu -> log = $log;
$categories = $cu -> getCache();
foreach ($categories as $key => $value) {
//TODO: make this category handling better. should array of arrays returned
array_push($tmp, $value -> id);
array_push($tmp, $value -> category);
array_push($tmp, $value -> parentCategory);
array_push($tmp, $value -> count);
array_push($tmp, $value -> itemCount);
array_push($return, $tmp);
$tmp = array();
}
} catch (Exception $e) {
$error = "TRUE";
$error_desc = $e -> getMessage();
$log -> lwrite($e -> getMessage());
}
sendResponse(200, json_encode(array("error" => $error, "error_desc" => $error_desc, "categories" => $return)));
return TRUE;
this is returning quite a large result set, a truncated version of which looks like:
{"error":"FALSE","error_desc":"","categories":[["1","All Categories","0","0","7"],["2","Antiques","0","20","0"],["3","Architectural, Garden","2","0","0"],["4","Art Deco (1925 - 1940)","2","0","0"],["5","Art Nouveau","2","0","0"],["6","Art","2","0","0"],["7","Asian Antiques","2","34","0"],["8","Amulets","7","0","0"],["9","Baskets","7","0","0"],["10","Bells","7","0","0"],["11","Bowls","7","0","0"],["12","Boxes","7","0","0"],["13","Bracelets","7","0","0"],["14","Brush Pots","7","0","0"],["15","Brush Washers","7","0","0"],["16","Cabinets","7","0","0"],["17","Chairs","7","0","0"],["18","Chests","7","0","0"],["19","Cups, Mugs","7","0","0"],["20","Fans","7","0","0"],["21","Glasses","7","0","0"],["22","Incense Burners","7","0","0"],["23","Kimonos","7","0","0"],["24","Masks","7","0","0"],["25","Military","7","0","0"],["26","Necklaces, Pendants","7","0","0"],["27","Other Asian","7","0","0"],["28","Paintings","7","0","0"],["29","Plates","7","0","0"],["30","Pots","7","0","0"],["31","Rings","7","0","0"],["32","Scrolls","7","0","0"],["33","Seals","7","0","0"],["34","Snuff Bottles","7","0","0"],["35","Statues","7","0","0"],["36","Swords","7","0","0"],["37","Tables","7","0","0"],["38","Tea Caddies","7","0","0"],["39","Teapots","7","0","0"],["40","Tsuba","7","0","0"],["41","Vases","7","0","0"],["42","Books, Publications","2","0","0"],["43","Decorative Arts","2","26","0"],["44","Bowls","43","0","0"],["45","Brass","43","0","0"],["46","Bronze","43","0","0"],["47","Cast Iron","43","0","0"],["48","Ceramics, Porcelain","43","0","0"],["49","Clocks","43","0","0"],["50","Copper","43","0","0"],["51","Cups, Saucers","43","0","0"],["52","Figurines","43","0","0"],["53","Glass","43","0","0"],["54","Gold","43","0","0"],["55","Jars","43","0","0"],["56","Jugs","43","0","0"],["57","Kitchen Tools","43","0","0"],["58","Lamps","43","0","0"],["59","Mirrors","43","0","0"],["60","Other Ceramics","43","0","0"],["61","Other Decorative Arts","43","0","0"],["62","Other Metalware","43","0","0"],["63","Pitchers","43","0","0"],["64","Plates, Platters","43","0","0"],["65","Teapots, Sets","43","0","0"],["66","Tin","43","0","0"],["67","Vases","43","0","0"],["68","Woodenware","43","0","0"],["69","Wrought Iron","43","0","0"],["70","Decor","2","0","0"],["71","Furniture","2","9","0"],["72","Beds","71","0","0"],["73","Cabinets, Cupboards","71","0","0"],["74","Chairs","71","0","0"],["75","Desks","71","0","0"],["76","Dining","71","0","0"],["77","Other Furniture","71","0","0"],["78","Sofas, Chaises","71","0","0"],["79","Stands","71","0","0"],["80","Tables","71","0","0"],["81","Maps, Atlases, Globes","2","0","0"],["82","Maritime","2","0","0"],["83","Musical Instruments","2","0","0"],["84","Other Antiques","2","0","0"],["85","Other Art Deco","2","0","0"],["86","Restoration and Care","2","0","0"],["87","Rugs, Carpets","2","0","0"],["88","Science, Medicine","2","0","0"],["89","Silver","2","0","0"],["90","Statues","2","0","0"],["91","Textiles, Linens","2","0","0"],["92","Art","0","13","0"],["93","Aboriginal Art","92","0","0"],["94","Art Cards, ACEO","92","0","0"],["95","Drawings","92","0","0"],["96","Fabric Art","92","0","0"],["97","Folk Art","92","0","0"],["98","Mixed Media, Collage","92","0","0"],["99","Other Art","92","0","0"],["100","Paintings","92","0","0"],["101","Photographs","92","0","0"],["102","Posters","92","0","0"],["103","Prints","92","0","0"],["104","Sculptures","92","0","0"],["105","Self-Representing Artists","92","0","0"],["106","Baby","0","19","0"],["107","Baby Clothing","106","12","0"],["108","Bottoms","107","0","0"],["109","Hair Accessories","107","0","0"],["110","Hats","107","0","0"],["111","....
The objective method is:
#pragma NSURLCONNECTION
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//**Getting called twice
NSLog(@"Data output");
NSLog(@"%@", [NSString stringWithFormat:@"%@", [NSString stringWithUTF8String:[data bytes]]]);
MCUtility * util = [MCUtility alloc];
//Extract basic json
NSDictionary * dictionary = [util parseJson:data];
....
}
- (NSMutableDictionary *)parseJson : (NSData *) json
{
NSError *error;
NSMutableDictionary *dictionary = [NSJSONSerialization
JSONObjectWithData:json
options:NSJSONReadingMutableContainers
error:&error]; //** error here!!
if( error )
{
NSLog(@"parseJson");
NSLog(@"%@", [error localizedDescription]);
return nil;
}
return dictionary;
}
This is really confusing me, especially as it occasionally works. If it helps the webservice currently is located at http://mycobber-dev-msimcox-aaasrdivrh.elasticbeanstalk.com/webservice/iCategories.php for the full output.
I validated it at the following website http://json.parser.online.fr/ successfully.
EDIT Thanks to Wain for the pointer. Once further question has popped up (newbie alert)
I've declared the instance variable
@implementation MCCategoryTableViewController
{
NSMutableData *receivedData;
}
in the .m file and am appending as
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"Data Received");
NSLog(@"%@", [NSString stringWithFormat:@"%@", [NSString stringWithUTF8String:[data bytes]]]);
[receivedData appendData:data];
}
and finally on completion
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Retrieved all data");
NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
// NSLog(@"%@", [NSString stringWithFormat:@"%@", [NSString stringWithUTF8String: [receivedData bytes]]]);
[self populateCategoryPageOne:receivedData];
if ( connection != nil ) {
connection = nil;
receivedData = nil;
}
}
however received data is nil? I've missed something fundamental here, could someone advise
Upvotes: 0
Views: 519
Reputation: 119031
You should expect connection:didReceiveData:
to be called multiple times. Each time it is called you should append the new data to a mutable data instance that you hold as a property. Then, when connectionDidFinishLoading:
you use that mutable data instance to deserialize the entire response.
Your current code will try to process partial responses currently so the format will be invalid.
Upvotes: 1