Extract data from Json into Label Text IOS - ios

So I am using the pokedex API as a learning curve for IOS and web services,
Here is my didrecivedata when the connection completes
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
//If the resposne recieved is good the call this function
// NSLog(#"data is %#", data);
//NSString *myString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//NSLog(#"string is %#", myString);
//Put data into a string
NSError *e = nil;
pokeDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&e];
NSLog(#"dictionary is %#", pokeDictionary);
}
This outputs Json to the console, I can log it into the console like this
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// do something with the data
// receivedData is declared as a method instance elsewhere
NSLog(#"Succeeded!");
NSLog(#"The Pokemon's name is %#", pokeDictionary[#"name"]);
NSLog(#"The Pokemon's attack is %#", pokeDictionary[#"attack"]);
NSLog(#"The Pokemon's speed is %#", pokeDictionary[#"speed"]);
}
However tried to extract Json into text fields like this
{
self.pokemonAttack.text = (#"The Pokemon's speed is %#", pokeDictionary[#"name"]);
self.pokemonAttack.text = (#"The Pokemon's speed is %#", pokeDictionary[#"attack"]);
self.pokemonSpeed.text = (#"The Pokemon's speed is %#", pokeDictionary[#"speed"]);
}
Error is "expression result unused", I guess my main issue is I am not comfortable with objective-c and just hacking around in IOS. For this I apologise and understand the comments of saying do objective-c courses
If you can point me in the right direction I can continue my trial by fire, I guess I should also be moving to swift soon

First of all you should know that the delegate method connection:didReceiveData: may be called multiple times as the connection loads the data incrementally. It may be called once if your returned data is very short, but it will most likely break at some point as you'll end up trying to parse incomplete data.
Regarding the warning you're getting - you just can't format strings like that. You're trying to use string formatting like you're calling NSLog, but the NSLog method does the formatting for you. You need to do something like this:
self.pokemonAttack.text = [NSString stringWithFormat:#"The Pokemon's speed is %#", pokeDictionary[#"speed"]];

Related

JSON or NSDATA incomplete / truncated after server pull [duplicate]

This question already has answers here:
NSLog on devices in iOS 10 / Xcode 8 seems to truncate? Why?
(7 answers)
Closed 5 years ago.
I'm pulling a .json file from my server and trying to read it into an NSDictionary in my app. Some of the file is being correctly parsed but it is incomplete - only some of the file is being read.
The strange thing is that the NSData is an equal length to the actual file, so it seems that it has full access, at least at some stage. When I log the NSData however, it seems to be way too short for the size of the file.
Here's the code I'm using to find the bug:
//SYNC BOOL
if (isSyncing){ return; }
isSyncing = true;
//FETCH BOOTSTRAP
NSError * fetchError = nil;
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:syncPath]
options:kNilOptions
error:&fetchError];
if (fetchError){ [self error]; return; }
//PARSE JSON
NSError * jsonError = nil;
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&jsonError];
if (jsonError){ [self error]; return; }
NSLog(#"data length is %lu", data.length);
NSLog(#"json is %#", json);
I've tried loading remotely from the server and locally from NSBundle - same result.
Could this be related to encoding / a rogue character in the JSON / some NSData max length?
Those options on the NSData fetch method and JSON Serialisation method, I've always left blank with no issue in the past, in terms of what's being pulled it's the same. I've also tried requests and sessions etc with no love.
EDIT:
I should add that when I log the the .allKeys of the json dictionary, it returns all keys correctly (including those not included in the log of the dictionary itself). This coupled with the correct NSData length implies that the data is in fact there, in completion. An explanation would be if the NSLog itself is somehow being truncated, implying an error when none exists. The problem is I haven't changed anything there. It could be a beta bug in the new Xcode.
EDIT B:
Logger Error on Xcode 9?
NSString * string = #"";
for (int n = 0; n < 10000; n++){
string = [NSString stringWithFormat:#"%# %i",string,n];
}
NSLog(#"string is %#", string);
Outputs to 6.7k not 10k.
See if you get different results with:
NSLog(#"json is %#", json.description);
Or to rule out NSLog altogether, maybe breakpoint the code there, and right click on json in the variables pane of the debug area and choose Print description of "json"
My experience is NSJSONSerialization will return an error for malformed JSON.
This is some silly feature in Xcode itself it seems. This define works for the full NSLog:
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
Taken from here:
NSLog on devices in iOS 10 / Xcode 8 seems to truncate? Why?
How many developers will spend time looking for imaginary bugs in the lazy logger...
For those coming afterwards, I'm running Xcode 9.0.

Json string limit

I am working on an iPhone app which runs remote queries on my db and displays them in a table view. I have a PHP script which fetches the data and encodes it in Json to be downloaded in Xcode. Right now, my app works for smaller queries but but not for larger ones.
When I was researching my issue, I read a few posts about Json issues with the length limit of the content of a string. I am not sure I 100% grasp the concept though... Right now, for small outputs, it displays everything properly, but for large ones it displays an empty table. When I print out all the fields of any one of my element (ex Name, Address, City) those values are always null (for the large queries).
Can anyone explain how the length of my string affects my fields and how would I go about fixing it? I saw some solutions online (such as breaking up the string) but since I do not yet fully understand the problem I didn't want to rush into things. Any explanation would be great.
I have attached the code for convenience (from the tutorial http://codewithchris.com/iphone-app-connect-to-mysql-database/):
#interface HomeModel()
{
NSMutableData *_downloadedData;
}
#end
#implementation HomeModel
- (void)downloadItems
{
// Download the json file
NSURL *jsonFileUrl = [NSURL URLWithString:#"http://localhost/www/service.php"];
// Create the request
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:jsonFileUrl];
// Create the NSURLConnection
[NSURLConnection connectionWithRequest:urlRequest delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// Initialize the data object
_downloadedData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the newly downloaded data
[_downloadedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Create an array to store the locations
NSMutableArray *_locations = [[NSMutableArray alloc] init];
// Parse the JSON that came in
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:_downloadedData options:NSJSONReadingAllowFragments error:&error];
NSLog(#"JSON IS %#.", jsonArray);
// This log prints it out fine
for (int i = 0; i < jsonArray.count; i++){
NSDictionary *jsonElement = jsonArray[i];
Location *newLocation = [[Location alloc] init];
newLocation.name = jsonElement[#"name"];
NSLog(#"PRINTING project_id %#", jsonElement[#"name"]);
//Here the log will print out NULL
...
}
}
}
I was able to fix my problem. It wasn't related to the json, which was properly formatted all along. My issue had to do with how I was storing the fields and printing them out, sorry. Thank you for the help.

Getting Flickr RecentActivity images

I want to retrieve Recent Activity images from flickr application, please any one suggest me how to retrieve that. thanks in advance.
This is not the best way of doing this but I will provide you a way to retrieve recent pictures on flickr. Standford iTunesU had a few lectures that related to this. I am getting almost all of my information from them. Here is a link to the course material:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
For the basic, non multithreaded version look under lecture 10 and download Shutterbug Universal. You will also need a flickr API key which you can currently get here:
http://www.flickr.com/services/api/misc.api_keys.html
I will attempt to outline for you though how to go about completing your request, especially since either of those links may not be around for long.
You will want to create a class FlickrFetcher or something, then have a public class method
+ (NSArray *)latestGeoreferencedPhotos;
Implementation
+ (NSArray *)latestGeoreferencedPhotos
{
NSString *request = [NSString stringWithFormat:#"http://api.flickr.com/services/rest/?method=flickr.photos.search&per_page=500&license=1,2,4,7&has_geo=1&extras=original_format,tags,description,geo,date_upload,owner_name,place_url"];
return [[self executeFlickrFetch:request] valueForKeyPath:#"photos.photo"];
}
Where executeFlickrFetch is implemented:
+ (NSDictionary *)executeFlickrFetch:(NSString *)query
{
query = [NSString stringWithFormat:#"%#&format=json&nojsoncallback=1&api_key=%#", query, FlickrAPIKey];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil;
if (error) NSLog(#"[%# %#] JSON error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
return results;
}
You will need to get your API key and either define it (#define FlickrAPIKey #"myAPIkey") or just directly insert it here.
In the Standford course they call latestGeoreferencedPhotos from a TVC subclass and set an array of photos in viewDidLoad:
// photos is a defined property
self.photos = [FlickrFetcher latestGeoreferencedPhotos];
Then in the setter for photos they reload a tableView that presents the images:
- (void)setPhotos:(NSArray *)photos
{
_photos = photos;
[self.tableView reloadData];
}
photos is now an array of dictionaries where so you can access specific image data by doing things like:
return [self.photos[row][#"title"] description]; // description because could be NSNull
I did find a github resource that may be valuable:
https://github.com/lukhnos/objectiveflickr.
I did not look into it much but it is probably worth checking into!
Your question did not provide much detail so I hope that this answer is sufficient for your needs.

What causes NSURLConnection to stop receiving before it's done?

My game needs to fill tableView cells with a bunch of things from my server database. This has been working fine. Then I upgraded Xcode to 4.6 and targeted iOS6.1, to please the App Review Team folks. Now, one of my connections never completes. (All of the other Posts seem to work correctly, as always.) Here's my post:
- (void) fillCells {
Cell_QtoA *newCell = [[Cell_QtoA alloc] initCellUser:usrID Grp:grpID Qtn:0 Gnm:#"na" Cat:#"na" Sit:#"na" Pfl:#"na" Lks:0 isA:0 ddA:0 ];
NSMutableURLRequest *reqPost = [SimplePost urlencodedRequestWithURL:[NSURL URLWithString:kFillCells] andDataDictionary:[newCell toDictC]];
(void) [[NSURLConnection alloc] initWithRequest:reqPost delegate:self];
}
I think it's working fine. The PHP and database haven't changed. Everything worked great yesterday, before the upgrades. Here's my connection method:
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"data = %#", data);
NSString *error;
NSArray *array = (NSArray *)[NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:0 errorDescription:&error];
if( error ) {
NSLog(#"Error = %#", error);
return;
}
NSLog(#"1st object in array of %d is %#", [array count], array );
}
Because I suspected net speeds to be an issue, I added a timer to the call, which I never needed before:
timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(fillCells) userInfo:nil repeats:YES];
The timer didn't help. Still get errors:
"Unexpected EOF" and "Unexpected character z (or whatever) at Line 1"
The NSLog of data shows hex data that appears cut off, like:
<3c3f786d 6c207665 ... 63743e0a 3c2f6172 7261793e 0a3c2f70 6c697374 3e>
It's like the reception is being interrupted. Anyone know what's happening here? Thanks!
You aren't using all the response data; as mention in the NSURLConnectionDelegate reference:
The newly available data. The delegate should concatenate the contents
of each data object delivered to build up the complete data for a URL
load.
So you need to create an NSData instance variable; clear before the request and append to it whenever new data arrives. Then use the didFinishLoading delegate method to trigger the call to propertyListFromData with the complete response.

Sending Player Alias (Game Center) via struct with ARC

What is the best approach for sending the local player's alias (or any text for that matter) to another device, since I can't put an NSString in my struct because of ARC/pointers?
So far, I've tried converting to & from a char array, using the __unsafe_unretained- option and trying to create a class to put the text in. Though all three of these attempts worked through compiling, they crashed the device (simulator keeps running but no alias displays.)
Is sending text in multiplayer games really difficult when using ARC? The issues I'm facing are most likely a result of the fact that I am not very experienced at programming... so if anyone could point me in the right direction or provide me with some snips of code, I'd really appreciate it.
You can easily encode and decode strings to NSData objects and send them over Game Center.
To encode: use this method on a string
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
With encoding:NSUTF8StringEncoding
This will return a NSData object
To decode;
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Edit:
Essentially you'll never have to send player aliases explicitly. There are 2 cases:
1: GKTurnBasedMatch
If you're using this, then here's how to get a list of all of the aliases (including yours)
NSMutableArray *playerIds = [NSMutableArray arrayWithCapacity:match.participants.count];
for (GKTurnBasedParticipant *part in match.participants) {
if([participant.playerID isKindOfClass:[NSString class]]){
[playerIds addObject:part.playerID];
}
} //at this point you have an array full of playerID strings, next you call this:
[GKPlayer loadPlayersForIdentifiers:(NSArray *)playerIds withCompletionHandler:(void (^) (NSArray *players, NSError *error))completionHandler {
for (GKPlayer *playa in players) {
NSLog(#"%#",playa.alias); // here i'm just logging the aliases but you can do whatever..
}
}];
2.GKMatch : this case is much easier since your GKMatch has already playerIDs array, same as before:
[GKPlayer loadPlayersForIdentifiers:(NSArray *) match.playerIDs withCompletionHandler:(void (^)(NSArray *players, NSError *error))completionHandler {
//again you get the array players full of GKPlayer objects , simply pull the alias you want
}];

Resources