I need to download three different sets of data from three different URLs. I decided to use ASIHTTPRequest. Two of the URLs are JSON feeds which I need to parse and one of them is a .txt file online that I need to store locally.
Now the example that is on ASIHTTPRequest's website for an asynchronous request shows the following:
- (IBAction)grabURLInBackground:(id)sender {
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
To pass multiple URLs, I can call "request" on three different URLs. But I am not sure how I would handle them in the requestFinished method. The documentation shows it as:
- (void)requestFinished:(ASIHTTPRequest *)request {
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
How would this method differentiate between different requests, so that I can handle it differently?
Thank you,
You can differentiate between different requests by
setting the userInfo dictionary of the request
setting the didFinishSelector (and didFailSelector etc.) to different methods
using different classes as delegate
using blocks
using the request's tag property
subclass ASIHTTPRequest and override override requestFinished: and failWithError: (only recommended for complex situations)
You just need two snippets of code. One to 'tag' your url:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:#"identifierX", #"typeOfRequest",nil]];
and another one to identify it:
if ([[[request userInfo] valueForKey:#"typeOfRequest"] isEqualToString:#"identifierX"]){
// Do here whatever you need to do for the url associated with identifierX
}
and that should be it!
you can set the Username and tag of req.
this is the example of imageview. req.
UIImageView *imgV=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 416)];
ASIHTTPRequest *req=[ASIHTTPRequest requestWithURL:[NSURL URLWithString:[self.arr objectAtIndex:i]]];
[req setUsername:[NSString stringWithFormat:#"%i",i]];
[req setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:imgV,#"imgV",nil]];
[req setDelegate:self];
[req startAsynchronous];
[imgV setContentMode:UIViewContentModeScaleToFill];
[imgV setClipsToBounds:YES];
[imgV setTag:kTagImageViewInScrollView];
[scr2 addSubview:imgV];
[scr2 setDelegate:self];
[imgV release]; imgV=nil;
and in requestFinished
- (void)requestFinished:(ASIHTTPRequest *)request {
[(UIImageView*)[[request userInfo] valueForKey:#"imgV"] setImage:[UIImage imageWithData:[request responseData]]];
}
You can check the originalURL property of ASIHTTPRequest if you have different URLS.
Or you can use [request hash] to get the NSObject hash for each object and check that later.
Related
I am trying to set up a cache, however the method I am using 'as below' is not being accessed by the thread.
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
I am initializing the connection like this, and connectionDidFinishLoading is accessed so I am not sure what I am missing.
- (IBAction)searchRequest:(NSData *)postBodyData
{
//Set database address
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"https://127.0.0.1:88"];
NSURL *url = [NSURL URLWithString:databaseURL];
NSString *postLength = [NSString stringWithFormat:#"%d", [postBodyData length]];
//SynchronousRequest to grab the data, also setting up the cachePolicy
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0]; //if request dose not finish happen within 60 second timeout.
// NSInputStream *fileStream = [NSInputStream inputStreamWithData:postBodyData];
[request setHTTPMethod: #"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/octet-stream" forHTTPHeaderField:#"content-type"];
[request setHTTPBody:postBodyData];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData data];
} else {
// Inform the user that the connection failed from the connection:didFailWithError method
}
}
any help would be appreciated.
connection:willCacheResponse: is only called in cases when the response will be cached. POST requests are not cacheable in most cases. (More details: Is it possible to cache POST methods in HTTP?)
You should probably look at something like MKNetworkKit which handles a lot of this kind of caching, particularly for REST protocols.
You can also look at Drop-in offline caching for UIWebView. You'd have to modify it significantly, but NSURLProtocol can be used to solve this kind of problem. AFCache is currently working to integrate this approach, and is another toolkit to consider. (Read through the comments in the blog post for more background on the issues.)
I am currently working on an application I need to receive the data in order its very important so instead of going with asynchronous I am using synchronous. However this introduces a very unfortunate side effect, the synchronous request locks up the UI thread.
What I am doing to combat this issue is introduce Multithreading into my app with the use of the life saving "Grand Central Dispatch" services, which seems to be very easy to get my head around so far.
So with all this in mind I am having an issue with what I am doing, Previously I was using asynchronous and everything worked sweet, changing that to synchronous gives me this error
Error Domain=ASIHTTPRequestErrorDomain Code=1 "A connection failure occurred" UserInfo=0x68052a0 {NSUnderlyingError=0x683d250 "The operation couldn’t be completed. Connection refused", NSLocalizedDescription=A connection failure occurred}
Heres my code so far.
- (IBAction)setRequestString:(NSString *)string
{
//Set database address
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"http://192.168.1.1:8778/Data/"]; // iphone development
//PHP file name is being set from the parent view
[databaseURL appendString:string];
//call ASIHTTP delegates (Used to connect to database)
NSURL *url = [NSURL URLWithString:databaseURL];
//Used to Check which ASI cache to use (also used in requestFinished
xmlFileName = [[NSString alloc] initWithFormat:string];
//Set up multithread with GCD
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
//Create If statments here to set up the different caches to be passed down to the next view
if ([string isEqualToString:#"high.xml"]){
//Cache stuff goes in here
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request setSecondsToCache:60*60*24*30]; // Cache for 30 days - this will change to cache until DBVersion changes
[request setDelegate:self]; // this calls the delegate function requestFinished
dispatch_sync(queue, ^ {
[request startSynchronous];
});
}else if ([string isEqualToString:#"low.xml"]){
//Cache stuff goes in here
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request setSecondsToCache:60*60*24*30]; // Cache for 30 days - this will change to cache until DBVersion changes
[request setDelegate:self]; // this calls the delegate function requestFinished
dispatch_sync(queue, ^ {
[request startSynchronous];
});
}
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
//.... etc
hopefully that gives you a better idea of what im trying to do, I think maybe I am missing something with the way I am declaring my syncronious start.. as in the asihttprequest help file they say to declare it like this
- (IBAction)grabURL:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *response = [request responseString];
}
}
however Im working with data.. so this line
NSString *response = [request responseString];
will not work? dose it need to be NSData.. etc I dunno if someone could help me out that would be great.
You can use nsoperationqueue...
you can create one NSoperationInvoke and add those to NSoperationQueue in order(after reciving data sending another request)...You can add observer to NSOperationQueue to ensure that how many request will process at a time...in your case it will be just one...after receiving the notification in the observer that the synchronous process is completed it will call a selector by performonMainThread for starting another request in the observer itself...
on NSString *response = [request responseString];
issue you can check the request object by [request iskindofClass:[ClassName class]];
or nslog("%#",[request describe]);
it will tell what kind of object request is
Have you considered just adding a serial queue to your code?
dispatch_queue_t queue = dispatch_queue_create("com.myapp", NULL);
You are using a concurrent thread and it's causing multiple operations to occur at the same time. Also, wrap properly your ASIHttpRequest code within the queue blocks.
Give that a try and let us know
I need to connect to a protected site and try to use ASIHTTPRequest
Here is my code:
url = [NSURL URLWithString:#"http://myurl/page.aspx"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUsername:username];
[request setPassword:password];
[request setDomain:domain];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
[webView loadHTMLString:[request responseString] baseURL:[request url]];
}
When I use NSLog to see [request responseString], I get the correct HTML, but the result is a blank white webview.
From the outgoing request warnings that little snitch displays, I see the initial request and one going to an external resource.
My guess so far is that the inital request correctly uses the authentication from ASIHTTPRequest and fetches the page, but the uiwebview will try to load the included .js files and since uiwebview is not authenticating, it will not render the page at all ...
Anybody knows how to fix my problem?
Have you tried ASIWebPageRequest? My guess is you have resources in that page that are not downloaded, like http://myurl/image.jpg
ASIHttpRequest runs asynchronously. You need to put your webview loading code into the ASIHTTPRequest callbacks. (requestFinished).
Add a method to your class as follows:
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSError *error = [request error];
if (!error) {
[webView loadHTMLString:[request responseString] baseURL:[request url]];
}
}
There is also a requestFailed method that you can use to trap additional errors, you should implement this as well. One or the other of these methods will be called once ASIHttpRequest completes.
Note you will probably also need to set the delegate on the request before making the asynch call. (so same place you set the auth stuff).
request.delegate = self;
I have two methods in my NSObject.
I would like to know how to set the text in one method from another, and then execute that method from the one where I set the text?
This is what I have done so far.. just getting abit lost trying to pass things between views and setting up tableviews.
- (IBAction) getManufacturers
{
//set manufacture.php
NSString *manufactureString = [[NSString alloc] initWithString:#"manufacture.php"];
submissionString = manufactureString;
self.grabURLInBackground; //<--- this is wrong, how do I call my other method?
}
//...
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://127.0.0.1:8888/CodeTest/%#", settexthere];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
//UPdated:
So what I ended up doing is just adding a NSString paramater to grabURLInBackground method which is set from my other method like describeded below
[self grabURLInBackground:submissionString];
all is well.
Now I just need to figure out how to pass the data I have coming in to a new uitableview.. :)
thanks for the help guys.
[self grabURLInBackground:nil];
this should work if you declared the function in the prototype
I think you want to set the string? In this case you need a new function
prototype
- (void) grabURLInBackgroundWithSubmission:(NSString*):submission;
implementation
- (void) grabURLInBackgroundWithSubmission:(NSString*):submission{
NSURL *url = [NSURL URLWithString:#"http://127.0.0.1:8888/instaCodeTest/%#", submission];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
and call it with
[self grabURLInBackgroundWithSubmission:submissionString];
Like this?
[self grabURLInBackground:nil]
But you may want to move the functionality from grabURLInBackground to another method so that you won't have to pass a dummy nil parameter.
i am new to iphone....when i need to connect to one of the web service i am using follwing code tat is using ASIHTTP request..when i add this code its coming error
ASIHTTPRequest is undeclared declare it first where i shd declare and wat i shd declare?i am using UIViewController class
how i shd declare? wat i shd do?plz suggest me
the code is given below
-(void)callWebService
{
//this is a typical url for REST webservice, where you can specify the method that you want to call and the parameters directly with GET
NSURL *url = [NSURL URLWithString:#"http://www.yourserver.net/webservice/rest/?method=myMethod&par1=ok"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDidFinishSelector:#selector(requestCompleted:)];
[request setDidFailSelector:#selector(requestError:)];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestCompleted:(ASIHTTPRequest *)request
{
NSString *responseString = [request responseString];
}
- (void)requestError:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
thank u...
First check that you have asihttp package attached in your project.
After that check you have
#import "ASIHTTPRequest.h" import this in your viewcontroller
Dont forget to check that you have attached the following frameworks. CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics and libz framework.
You have not tell which method to use
[request setRequestMethod:#"GET"]; BEFORE [request startAsynchronous];
When you will right click on framework folder this popup will appear.