I know how to fetch data from NSSURL, but i wana ask how i can filter the data like the page contains both text, images , videos etc how i can specify like only to extract images. And lets say if all the data is downloaded all together how i can filter it.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(#"%#",str);
[receivedData appendData:data];
}
Like in this how i can filter if all the data is downloaded all together. or to specify the type of data before downloading. thx in advance
From NSURLResponse you can check MIMEType
NSURLResponse * httpResponse = (NSURLResponse *) response;
NSString *fileMIMEType = [[httpResponse MIMEType] lowercaseString];
You can consider using this delegate method for NSURLConnection
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSString *mime = [response MIMEType];
//do something with mime
}
Related
I have followed a handful of examples on NSURLConnection, see latest below, but yet I keep getting null on the returned FinishLoading. I checked didReceiveResponse and its getting the data. What am I not doing right here?
EDITED: Now works as expected.
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
_dataDictionary = [NSMutableDictionary new];
_theReceivedData = [NSMutableData new];
[_theReceivedData setLength:0];
// add object
[_dataDictionary setObject:_theReceivedData forKey:[connection description]];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSMutableData *imageData = _dataDictionary[ [connection description] ];
[imageData appendData:data];
if([connection description]!=nil && imageData!=nil)
{
[_dataDictionary setObject:imageData forKey:[connection description]];
}
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
NSData *imageData = _dataDictionary[ [connection description] ];
if(imageData!=nil)
{
NSLog(#"%#",imageData);
Take NSMutableData *theReceivedData out. Make it a class variable. Your problem is theReceivedData is being deallocated in every method. You are creating a new object in every method. Retain the old one.
NSMutableData *_theReceivedData;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
_theReceivedData = [NSMutableData new];
[_theReceivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[_theReceivedData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
// LOOK AT THIS http://stackoverflow.com/questions/1064920/iphone-corrupt-jpeg-data-for-image-received-over-http
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"%#",_theReceivedData);
I never use web API and don't know what i may read about this. I read FAROO Return Values doc, but i don't understand how i may get result-array (or dictionary) in cocoa.
Please anybody give me example or tutorial how to use Faroo API (or other web API) in objective-c.
Thank you.
To use web API and FAROO API in particular i use NSURLConnection class and NSURLConnectionDelegate protocol:
- (IBAction)search:(id)sender {
NSString* requestString = [NSString stringWithFormat:#"http://www.faroo.com/api?q=%#&start=1&length=10&l=ru&src=news&f=xml&YOUR_API_KEY",[searchField stringValue]];
// NSLog(#"str %#",requestString);
NSURL* requestUrl = [NSURL URLWithString:requestString];
NSURLRequest* searchRequest = [NSURLRequest requestWithURL:requestUrl cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:60];
[self performSelectorOnMainThread:#selector(startConnectionWithRequest:) withObject:searchRequest waitUntilDone:NO];
}
- (void)startConnectionWithRequest:(NSURLRequest*)request {
NSURLConnection* connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
if (connection) {
//update GUI and do something...
theData = [NSMutableData data];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"Receive data");
[theData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"Http status code %ld",(long)[httpResponse statusCode]);
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Finish");
//do something with data and update GUI
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSAlert* searchFailedAlert = [NSAlert alertWithError:error];
[searchFailedAlert runModal];
}
One other way of doing things is to declare the missing method yourself as a category of the class in question. This will get the compiler to stop complaining about not finding the method, though of course you'll still need the runtime check you're already doing to avoid actually calling the method. You might also want to wrap such a declaration using availability macros, so that it will be ignored once you do move up to using the 10.5/10.6 SDK and you won't get a different compiler complaint down the line. That would look something like this:
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4 //ignore when compiling with the 10.5 SDK or higher
#interface NSPropertyListSerialization(MissingMethods)
+ (NSData *)dataWithPropertyList:(id)plist format:(NSPropertyListFormat)format options:(NSPropertyListWriteOptions)opt error:(NSError **)error;
#end
#endif
I have a URL where I can download a PDF, but I cannot use something like:
[myWebView loadRequest:urlRequest];
since this link will send out some challenges...
However, I managed to get the PDF raw data NSURLConnection(to be exact, I can get the data in the delegate method:
(void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data).
And then I want to know, how I can show this PDF? Does anyone has any idea? Thanks a lot!
I have made my own, pdf download class, but this is the bits you'll need. In the .h of the class. Declare:
NSMutableData *_data;
NSString *pdfPath;
Also subclass the delegates for the connection
<NSURLConnectionDataDelegate, NSURLConnectionDelegate>
Then in the implementation file, in - viewDidLoad:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
pdfPath = [documentsDirectory stringByAppendingPathComponent:#"pdfName.pdf"];
The connection:didReceiveData: method:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if(!_data) _data = [[NSMutableData data]init];
[_data appendData:data];
progressView.progress = ((float) [_data length] / (float) downloadSize);
}
The connectionDidFinishLoading: method:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
unsigned char byteBuffer[[_data length]];
[_data getBytes:byteBuffer];
[_data writeToFile:pdfPath atomically:YES];
}
So when it receives data, it builds up the _data, then when it finishes it writes it to the path. Make sure the connection delegate is set to self.
After that, you can open the path to the PDF as you did before.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
iPhone/iOS JSON parsing tutorial
I have been reading many tutorials on how to parse JSON data in Objective C but still I am unable to figure it out. I want to parse data from the JSON file and show it up on screen.
For example,
I want to parse data from here and get all the values of different retailers in different variables, so that I can use them later.
How can I do it?
Assuming that you have your data in a NSData object you can use NSJSONSerialization class available in iOS 5 and up.
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error
This is a class method that will convert your data into objects like NSArray, NSDictionary, NSNumber etc. depending on the contents of your data object.
Here is how you would download and parse the data from a web server. Note that all these methods are part of the same class and there are instance variables named _downloadData of type NSMutableData* and _downloadConnection of type NSURLConnection*. Also note this code assumes ARC is not being used. If it is, just remove the object releases and retains and make sure the instance variables are strong references.
-(void)startDownload {
NSURL* jsonURL = [NSURL URLWithString:#"http://isbn.net.in/9781449394707.json"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:jsonURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
_downloadData = [[NSMutableData dataWithCapacity:512] retain];
_downloadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[_downloadData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_downloadData appendData:data];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[_downloadConnection release];
_downloadConnection = nil;
[_downloadData release];
_downloadData = nil;
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError* jsonError = nil;
NSDictionary* jsonDict = nil; // your data will come out as a NSDictionry from the parser
jsonDict = [NSJSONSerialization JSONObjectWithData:_downloadData options:NSJSONReadingMutableLeaves error:&jsonError];
if ( nil != jsonError ) {
// do something about the error
return;
}
[_downloadConnection release];
_downloadConnection = nil;
[_downloadData release];
_downloadData = nil;
// now do whatever you want with your data in the 'jsonDict'
}
After pounding my head all day long, I am down to StackOverflow to pull me through.
I am making a NSURLRequest in my iPhone App ...
NSURL* url = [[self serviceUrl] URLByAppendingPathComponent:[NSString stringWithFormat:#"Json"]];
NSString* json = [NSString stringWithFormat:#"{\"id\":\"%#\"}", id];
NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]];
this is returning to me a JSON string, which comes back to me but it is broken in the since that the string will not parse correctly.
However if I make a normal request to the same url in the Safari browser then JSON is returned correctly. I am validating this JSON here.
So whats the deal? Is there a limit to the length of data in a NSString* that a 32Kb json file would not be stored in memory correctly? Sometimes the JSON can be parsed, which leads me to believe that I am not clearing my JSON string correctly after each request.
_json = [[NSString alloc] initWithData:_dataResponse encoding:NSUTF8StringEncoding];
NSArray* retrievedData = (NSArray*)[_json JSONValue];
// removed for brevity
_json = #"";
Other information, I am using ASP.NET MVC 3 to provide the web services for this app.
EDIT
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{
_loader.hidden = NO;
[_loadingIndicator startAnimating];
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
_dataResponse = [[NSMutableData alloc] init];
[_dataResponse setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_dataResponse appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error receiving response: %#", error);
_loader.hidden = YES;
[_loadingIndicator stopAnimating];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
_json = [[NSString alloc] initWithData:_dataResponse encoding:NSUTF8StringEncoding];
// Removed for brevity
_json = #"";
_loader.hidden = YES;
[_dataResponse release];
_dataResponse = nil;
[_loadingIndicator stopAnimating];
}
FINAL SOLUTION
I was making multiple calls to have data already stored for views in order to switch views in a tab bar controller. I wasn't checking the connection during the appending of the data, I was checking the connection when it was finished in order to store the data correctly. My final solution was to make each call sychronously after the previous one during the finished method call.
Unfortunately, nothing blatant is jumping out at me.
Some things to try that will hopefully help:
double check your NSUrlConnection pattern against this doc. The only diff I see is they're doing [[NSMutableData data] retain] instead of alloc, init. They also create NSMutableData with the connection request (not in response) and only length=0 in response. Not sure why it would matter though ...
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
try something like Charles Proxy. It allows you to sniff the wire. You can see what's different between browser and simulator/phone access. At a minimum, you'll see what's coming over the wire in the bad cases.
add lots of logging. everytime you append data, log some details. After you convert to string and before the json call, log. Log sizes, etc... Something may offer you a hint.
the use of _json string seems a bit off. You're reallocating and then setting to empty string. You should either have an iVar that you alloc and release (not set to "") or create a #property with retain, copy.
You should definitely include charset=utf8 in you content-type header. And how do you know that the response you get is encoded as utf8? You should also set content-size header.