i have one simple question, if i'm using ASIFormDataRequest when i need to release the request object?
NSURL *url = [NSURL URLWithString:#"url"];
ASIFormDataRequest *requestForm = [ASIFormDataRequest requestWithURL:url];
[requestForm addPostValue:[[NSUserDefaults standardUserDefaults] stringForKey:#"user"] forKey:#"user"];
[requestForm setRequestMethod:#"POST"];
[requestForm setDelegate:self];
[requestForm startAsynchronous];
Thanks
You need to remember that you are always responsible for releasing an object if the method from which you receive it contains new, copy, or init.
In this case, you don't need to release it. The ASIHTTPRequest class autoreleases it for you.
A quick search in the implementation file shows that it'll be autoreleased.
+ (id)requestWithURL:(NSURL *)newURL
{
return [[[self alloc] initWithURL:newURL] autorelease];
}
Your request is autoreleased in your code, so you don't need to release it (as others have said).
However, you are starting an asynchronous request - it'll complete/fail sometime in the future, and if it is associated with other objects which will get freed when the view exits you're potentially leaving yourself open to a crash. So I'd suggest you would want to make requestForm a property of your class (so when you assign the request to self.requestForm it will get retained for you), and explicitly release & nil it when the request completes.
If it's a very simple app with just one view you may get away without that though.
Related
I have an application in which I need to have a settings page,which has some credentials of the user then he can edit that.its a table view loading from an array taken from the httprequest.by clicking on each of this it will have the option to go to another view and update that value and come back. I have done the update call to the server on that update view like this..
dispatch_async(backgroundQueue_, ^{
[self performSelectorInBackground:#selector(load) withObject:nil];
dispatch_sync(dispatch_get_main_queue(), ^{
[self showHUD];
});
because in the mainqueue i am doing the popping back operation.so i need that update service to be called in the background.But the problem is when i coming back i am calling another service in the settings viewcontroller.to load the updated value.some times the delegates of the request is getting crashed.I am calling the service like this.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:uidstr forKey:#"userId"];
request.userInfo=[NSDictionary dictionaryWithObject:#"update" forKey:#"type"];
[request setPostValue:self.string forKey:#"age"];
[request setDelegate:self];
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];
[self showHUD1];
[request startAsynchronous];
Can anybody point me how i can do this with out crashing my app.I think the problem is the delegate getting nil.
Decouple your network requests from your view controller code. That way if the views are unloaded, the network delegate will still exist.
For example: Make a NetworkRequest singleton class that does all the communication with the network, and then you could use a mechanism like NSNotifications, or an #protocol interface in the singleton class that view controllers could become delegates of, to pass results and status changes as needed.
For a good tutorial on singletons in Objective-C, see: http://www.galloway.me.uk/tutorials/singleton-classes/
Better drop usage of ASIHTTP since this framework is no longer supported by the developers. You won't get support for possible changes of future iOS versions.
I am using ASIHTTPRequest (I know, I know, it is not being maintained - that doesn't matter; it works and it is what my app is built on) to run a series of HTTP requests through ASINetworkQueue.
The problem is that my queue will have many requests (thousands), and it will take a while to run. In the time that it is running, some of the data in the app may have changed which would make some of the request unnecessary. I would like to run a validation method on each request right before it runs, and if the validation method does not check out, then it will cancel that request and go on to the next one.
Right now, I am using the following code to create my ASIHTTPRequests:
ASINetworkQueue *myQueue = [ASINetworkQueue queue];
NSURL *URL = [NSURL URLWithString:#"http://mywebsite.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setStartedBlock:^{
NSLog(#"Request started: %#", request.url.absoluteString);
}];
[request setCompletionBlock:^{
NSLog(#"Request completed: %#", request.url.absoluteString);
// do some code here to clean up since it's finished
}];
[myQueue addOperation:request];
My current thinking is to put something into the startedBlock, so it would do:
[request setStartedBlock:^{
NSLog(#"Request started");
if (![self myValidationMethod]) {
[request cancel]; // <----------
}
}];
However when I do this, I get the following warning from Xcode:
"Capturing 'request' strongly in this block is likely to lead to a retain cycle."
First, is this the right method to go about doing this? I can't seem to find a way to remove a specific ASIHTTPRequest from an ASINetworkQueue. Second, is this warning from Xcode something that I will need to worry about?
About the warning you capture the blocks 'container' and form a cycle... just say:
__weak ASIHTTPRequest *rw = request;
and use that in the block.
as for the started block approach. doesnt sound perfect to me but I dont know a better approach...
NSURLRequest delegate methods are not getting called when i run the application on the device. It works perfectly on the simulator though. Also its not the case of my view loading before the request is fulfilled because i enable to view to be loaded only once the connection has received the data.
My code requesting url is here. Any help greatly appreciated.
- (void)viewWillAppear:(BOOL)animated
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://-dev01x/content"]; cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
[request setHTTPMethod:#"GET"];
_getData = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"HELLO %#",_getData);
}
Your code as provided here makes no sense:
_getData = [[NSURLConnection alloc] initWithRequest:request delegate:self];
That line returns a pointer to a NSURLConnection object, your variable name is misleading. If you want to block at this point (and does that even work) then it would appear you need to use sendSynchronousRequest at that point.
I do something similar to what you want to do, but in a more traditional way. In viewDidLoad or even in the initWithFrame, I will start up an asynchronous connection, set a flag, and set the view backgroundColor to black or white (I use a spinner too normally). When I get viewWillAppear, if the connection has completed, all is well and I set the various UI elements. If not, then don't do anything, and later, when the connection completes, pull down the spinner and update the UI.
The only way I can think of to block the main thread at the point you are trying to would be to use that synchronous request (which IMHO is a really bad way to deal with this).
The beauty of doing things in the background is that if its taking too long, the user can tap the back button or go somewhere else in the app [in which case you cancel the connection and tear everything down.]
Check url u provide to NSMutableURLRequest when checked in browser gives nothing
NSMutableURLRequest needs valid url
This is a tough question.
When I press on the button, it is supposed to connect to a URL, which will initiate that method of my wcf service. However, when I debug, I noticed that the connection fails (like none of the delegate methods are called and stuff). I know that my WCF service works because when i type the URL in safari directly, it works perfectly, and performs that method. Here is my code:
- (IBAction)RBCButtonPressed:(id)sender {
//[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:\\Program Files (x86)\\Bank of the Future"]];
NSString *urlString = #"http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:\\Program Files (x86)\\Bank of the Future";
NSLog(urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url ];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
if(connection)
self.valueReturned = [[NSData data] retain];
else
NSLog(#"data failed");
NSLog(#"connection failed");
[captureView addSubview:loader];
}
I'm not including the delegate methods cause they aren't called anyway.
It prints "connection failed."
UPDATE: When I use a method that takes in only one parameter, it works fine from both the browser and the device (the connection succeeds and the delegate methods are called). However, when there are two parameters, it works fine only from the browser. The connection always fails.
Possibilities - the use of the backslash confuses it somehow (?).
This is urgent and any help would be greatly appreciated.
EDIT: It will always print "connection failed" I realize, but I know that the connection fails because 1) the delegate methods aren't called and 2)the application does not turn on, which it will if the method is called.
If you check your NSURL object in the debugger, you'll find it's nil immediately after you try to initialize it. This is because it's malformed. Try URL encoding it first.
Notice the URL you pasted into safari changes to this:
http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:%5C%5CProgram%20Files%20(x86)%5C%5CBank%20of%20the%20Future
See all the %20s and %5Cs, etc.? That's because safari URL encodes it before sending the request. You must do the same.
Best regards.
It's failing because you are releasing connection right after you create it. If you're not using ARC, you could create it with autorelease, or just use ARC and forget about the releases.
So I'm trying to load a simple URL (http://www.google.com) into a web view. I had this in the application I was working with, but boiled it down to a basic application to remove other variables. I have an absolute minimal application setup, one view controller with a webview as its primary view. For code I have
-(void)viewDidLoad
{
[super viewDidLoad];
UIWebView *webView = (UIWebView*)self.view;
NSMutableString *urlString = [[NSMutableString alloc] initWithString:#"http://www.google.com"];
NSURL* url = [[NSURL alloc] initWithString:urlString];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url];
NSLog(#"Sending web request to %#", urlString);
[webView loadRequest:urlRequest];
[urlRequest release];
[url dealloc];
[urlString dealloc];
}
And when it loads, I get an EXC_BAD_ACCESS crash within the Web Thread. I am unsure if this is a problem related to the fact that I am working in the simulator, or something I've just screwed up with the setup.
DO NOT CALL dealloc. Call release on url and urlString instead.
This is because other objects have references to those objects, and when you say dealloc, you are explicitly destroying them. This is causing the EXC_BAD_ACCESS, because when other objects try to access the url and string objects, they have already been destroyed.
This is the whole point of reference counting. YOU are done with those objects, so if you say:
[url release];
[urlString release];
You are declaring that. This decrements the count of references to those objects. But up above, you said:
NSURL* url = [[NSURL alloc] initWithString:urlString];
This means url probably has a reference to that string. So it would have retained it when you created it. So after you release the string, it does not get destroyed because url still has a reference to it. When IT is done with it, it too will release it, and then (if no one else has claim to the object), it will automatically be dealloced, because its count will have dropped to zero.
Always keep in mind who else might be using your objects when you are dealing with this sort of memory management. You can read more about it in Apple's docs.