call async asihttp in different view controller - iphone

I try to use UINavigationController to navigate from one view controller to another.
In both viewController , the viewWillAppear
I call asihttp using async mode.
but this always cause the app crash.
I try to use the function of asihttp '[request cancel]'
in the wiewWillDisaaoear, but the error still exist
Welcome any comment

I used Following code in my app and i also did forth-back using UINavigationController but it didn't give me any crash. I suggest you to show your code here so it will help you a lot to find out your resolution.
Here, I am showing you my code..see if it will help you.
-(void)viewWillAppear:(BOOL)animated
{
[self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:1];
NSURL *urlf = [NSURL URLWithString:#"Your url"];
ASIHTTPRequest *requestdiff = [[ASIHTTPRequest alloc]initWithURL:urlf];
[requestdiff setDelegate:self];
[requestdiff release];
[self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:1];
}

Related

UIWebView shouldStartLoadWithRequest only fires once when calling a modal view from inside

I have part of my app written in JS and running inside of a WebView. I'm using the UIWebView shouldStartLoadWithRequest method to capture http requests as a means of communicating between JS and obj-c. This works great until I attempt to load a Modal View Controller over my webview from inside the shouldStartLoadWithRequest method. Once this happens, shouldStartLoadWithRequest is no longer called. Sometimes I need to dismiss this modal view controller and go back to the webview and do some things and then re-present the modal controller. The modal controller comes up the first time just fine, then I dismiss it and attempt to present it again by navigating to a URL from javascript and it no longer will present itself. NSLogs inside shouldStartLoadWithRequest are never run.
In my javascript I do something like this:
window.location='myapp:whateverMethod';
objective c code looks like this:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSLog(#"REQUEST URL: %#", requestString);
if([requestString hasPrefix:#"myapp:"]) {
NSArray *components = [requestString componentsSeparatedByString:#":"];
NSString *function = [components objectAtIndex:1];
if([self respondsToSelector:NSSelectorFromString(function)]) {
[self performSelector:NSSelectorFromString(function)];
}
return NO;
}
return YES;
}
-(void) whateverMethod {
NSLog(#"whateverMethod called!");
// This is a quick way to grab my view controller from the storyboard, so assume it exists
UIViewController *splash = [self.storyboard instantiateViewControllerWithIdentifier:#"splashViewController"];
[self presentModalViewController:splash animated:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self dismissModalViewController:splash animated:NO];
});
}
At this point my webview is still visible. I navigate from page to page in my webapp and all javascript works great in it but the "shouldStartLoadWithRequest" delegate method of the webview no longer is called. I cannot figure out why. Does anyone have any ideas?
I noticed that Cordova doesn't set the window.location property. Instead it has two options: it either creates an iframe and sets the src of the iframe to that url, or it creates an XMLHttpRequest object e.g. in the iOSExec() function:
if (bridgeMode) {
execXhr = execXhr || new XMLHttpRequest();
// Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
execXhr.open('HEAD', "file:///!gap_exec", true);
execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', nativecomm());
}
execXhr.send(null);
} else {
execIframe = execIframe || createExecIframe();
execIframe.src = "gap://ready";
}
That being said, it may be beneficial to use something like Cordova instead of trying to roll it yourself (even if it's just embedding their view controller), since they handle a lot of the headaches that come up with webview delegates.
I've just had the same problem, but related to using a href="#" anchor.
This Stack Overflow answer sorted it
There are more answers on that thread that deal with widow.location, so you may have luck with them.
Checked out Cordova and they have their own queuing system, not really a help. But...
Disobedient Media's answer gave me an idea. Instead of window.location, why not try window.location.hash.
Now some JS code for logging is:
function sendMsgToNative(msg)
{
window.location.hash = '~cmd~' + msg;
}
console.log = function (msg) { sendMsgToNative('log~js ' + msg); };
and the Objective-C code is:
NSString *req = [request.URL absoluteString];
NSArray *components = [req componentsSeparatedByString:#"~"];
// Check for your protocol
if ([components count] > 1 && [(NSString *)[components objectAtIndex:1] isEqualToString:#"cmd"])
{
// Look for specific actions
if ([(NSString *)[components objectAtIndex:2] isEqualToString:#"log"])
{
NSString *logStr = [(NSString *)[components objectAtIndex:3] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
LOGI("%#", logStr);
}
}
You get the full URL including 'http:...' so I chose tilde instead of colon, and incremented the indices.
Now you can log all willy-nilly and send whatever amount of commands you want and they will all get through :-)
I (embarrassingly) spent a couple of hours working on this today, and realised that in my viewDidDisappear: I was setting the UIWebViewDelegate to nil!
All I needed to do to fix was once the modal was dismissed, re-set the UIWebViewDelegate and everything worked again.

IOS 5 showing SVProgressHUD when loading feed in separate thread does not work

Im developing an IOS 5 app which takes a feed from a url and displays the posts in a tableview. I have a View controller that loads the table cells with the posts in the feed. This all works perfectly.
However, i wanted to use the SVProgressHUD to show whilst the feed is being loaded in a separate thread.
So in my -(void)viewDidLoad method I have the following:
- (void)viewDidLoad
{
[super viewDidLoad];
[SVProgressHUD showInView:self.view status:#"loading.." networkIndicator:YES];
dispatch_async(kBgQueue, ^{NSData* data = [NSData dataWithContentsOfURL: latestFeedURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];});
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(foregroundRefresh:) name:UIApplicationWillEnterForegroundNotification object:nil];
self.pull = [[PullToRefreshView alloc] initWithScrollView:(UIScrollView *) self.feedTableView];
[self.pull setDelegate:self];
[self.feedTableView addSubview:self.pull];
self.title = #"Latest";
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSMutableArray* latestFeed = [json objectForKey:#"posts"]; //2
self.feedUpLoads = latestFeed;
NSLog(#"objects: %#", latestFeed); //3
[self.feedTableView reloadData];
[SVProgressHUD dismiss];
}
This all works fine, im getting the data which is loaded in a background thread and my table is displaying the posts with all the detail required. The problem I have is that the SVProgressHUD is not showing at all. Even if I put the [SVProgressHUD showInView line in the fetchData method, it's still not showing. (by the way i know the SVProgressHUD code works because I can actually make it show forexample in the viewWillAppear method.
Im guessing that it's not working because at the point when I'm calling it the view does not yet fully exist? But if that's the case where should I call it so that it shows whilst the feed is being called and where should I remove it?
Any help appreciated! thanks in advance!!
For anyone else having a similar problem, this can also happen because you have a long loop or a piece of code that takes a long time to execute. If this happens, your progress bar wont be shown until after the loop, which kind of defeats the purpose.
To solve this issue you need to you this:
(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
Basically your code would look something like this:
- (IBAction)submitPost:(id)sender {
//now we show the loading bar and submit the comment
[SVProgressHUD showWithStatus:#"Submitting post" maskType:SVProgressHUDMaskTypeGradient];
SEL aSelector = #selector(submitDataOfPost);
[self performSelectorInBackground:aSelector withObject:sender];
}
This will basically load the progress bar, and in a background thread, the method you want to execute will be called. This makes sure that the UI is updated (shows the progress hud) at the same time that your code is executed.

NSURLConnection Async Request and display a "Loading" alert view or subview while fulfilling request

I'm trying to figure out the optimal way to perform an NSURLConnection Async Request and have the UI shielded with an alert view while the request is being fulfilled. I've had a lot of trouble getting this to work with a synchronous request because I could not figure out how to use the multi threading features or operation queues effectively with a synchronous request, so I figure this is the best way to go. Pseudo code or actual code is fine, I just need to know which direction to go. So far I figure:
Create a UIAlertView property
Create a void function that initiates the NSURLConnection, and display the view right after it initiates
Use the delegate method to close the AlertView window -(void)connectionDidFinishLoading or something like that.
Is it this simple, or am I missing something?
Probably the easiest way to do it is to use the UIApplication.networkActivityIndicatorVisible property, and do a sync request in a background thread.
-(void)loadURLInBackground:(NSURL*)url {
NSURLRequest* req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
NSURLResponse* response = nil;
NSError* err = nil;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSData* data = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&err];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if( data != nil ) {
[self performSelectorOnMainThread:#selector(processData:) withObject:data waitUntilDone:NO];
} else {
[self performSelectorOnMainThread:#selector(processError:) withObject:err waitUntilDone:NO];
}
}
Use [self performSelectorInBackground:#selector(loadURLInBackground:) withObject:url]; to call the method, then just implement processData: and processError:.
You do not want to use a UIAlertView - that is a modal dialog.
You want to use something like UIActivityIndicatorView to show the spinner while the background activity is going on.
Then, as you say, your delegate method can stopAnimating the activity indicator view.
If you want to show a message like "Downloading ...", then you can wrap your activity indicator inside another view, display that view, and remove it when the delegate calls back.

iOS 4.2 - Return to app after phone call

I can successfully initiate a phone call within my app using the following:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel://123456789"]];
However, is it possible to automatically return back to the app once the phone call has been terminated? It seems this was not possible under iPhone OS 3.0 but I am hoping it is now possible under iOS 4.2 with multitasking (I wasn't able to find any information on this question specific to iOS 4.2).
Thanks in advance for any assistance!
I know the question is very old, but currently you can do this (at least on iOS 5) by using telprompt://, like:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"telprompt://123456789"]];
iPhone will show alert view confirmation and when call ends, your app shows again, instead of iPhone's call app.
As far as I'm aware, because control is passed to the phone.app to make the call, once the call has ended, as far as iOS is concerned phone.app is the current app so that stays in the foreground.
There doesn't seem to be anything you can do about this at the moment. It might be worth putting in a feature request to allow for a "modal phone call" similar to MFMessageComposer that allows you to send emails/sms within your own app.
EDIT
You can follow the advice that Frin gives in the answer below as this contains more up to date information.
I believe the issue is that you're still making the sharedApplication call and as per the other thread, there is no need to add the web view as part of your hierarchy.
I took your code, modified it as below, and it works just fine:
NSString *phoneStr = [NSString stringWithFormat:#"tel:%#", phoneNumber];
NSURL *phoneURL = [[NSURL alloc] initWithString:phoneStr];
// The WebView needs to be retained otherwise it won't work.
if (!mCallWebview)
mCallWebview = [[UIWebView alloc] init];
[mCallWebview loadRequest:[NSURLRequest requestWithURL:phoneURL]];
Following the call your own app runs as before.
This is definitively possible since the introduction of iOS 4.0. The best way to handle this is to use a UIWebView, load the "tel:0123456" URL in the WebView without adding it to the view hierarchy. The iOS will automatically display an alert with the phone number and ask the user to confirm by pressing "Call".
Once the call is completed, your app will be brought back to foreground automatically. This is detailed in this other thread: Return to app behavior after phone call different in native code than UIWebView
I have given this answer in iPhone SDK: Launching an app after call ends I will also post my code here.. here you can make a call without closing you app..
-(IBAction) dialNumber:(id)sender{
NSString *aPhoneNo = [#"tel://" stringByAppendingString:[itsPhoneNoArray objectAtIndex:[sender tag]]] ; NSURL *url= [NSURL URLWithString:aPhoneNo];
NSURL *url= [NSURL URLWithString:aPhoneNo];
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
if ([osVersion floatValue] >= 3.1) {
UIWebView *webview = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
[webview loadRequest:[NSURLRequest requestWithURL:url]];
webview.hidden = YES;
// Assume we are in a view controller and have access to self.view
[self.view addSubview:webview];
[webview release];
} else {
// On 3.0 and below, dial as usual
[[UIApplication sharedApplication] openURL: url];
}
}
With iOS 9.3.4, every technique that I try has control return to the calling app after the phone call. Has this behavior changed recently? This example is just a Swift and simplified version of https://github.com/jatraiz/RZTelpromptExample:
class ViewController: UIViewController {
let phoneNumber = "7204790465"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func callWithTelPushed(sender: AnyObject) {
if let url = NSURL(string: "tel:" + self.phoneNumber) {
UIApplication.sharedApplication().openURL(url)
}
}
#IBAction func callWithTelpromptPushed(sender: AnyObject) {
if let url = NSURL(string: "telprompt:" + self.phoneNumber) {
UIApplication.sharedApplication().openURL(url)
}
}
#IBAction func callWithRZTelpromptPushed(sender: AnyObject) {
RZTelprompt.callWithString(self.phoneNumber)
}
}

mapview is not showing before it load all data

i have one application it has mapview .
problem is that i want to show map. means right now when all data loaded then it show mapview. i want to show mapview before it loaded . how can i do this ?
Edit:
for show map i use this [self performSelector:#selector(methoname) withObject:nil afterDelay:0.02];
but by this other problem generate .problem is ,it show me two times activity indicator. any other thing ,like performselector but without activity indicator.
i dont want to show this thing.
You want to look at multithreading.
Basically, you should be retrieving your data in a background thread. If you do what you're doing right now (loading everything in the main thread) the UI cannot be updated until everything is loaded.
So, do something like this:
-(void)viewDidLoad{
mapView.hidden = NO;
[self performSelectorInBackground:#selector(getExtraMapData)];
}
-(void)getExtraMapData{
NSAutoReleasePool *pool = [[NSAutoreleasePool alloc] init];
[self downloadMapData];
[map addTheDataIDownloaded];//I've never used the mapView,
// so I don't know it's methods.
[pool release];
}
-(void)downloadMapData{
NSURL *mapDataURL = [NSURL URLWithString:#"http://aURLWithInfoForMyMap.com"];
NSData *mapData = [NSData dataWithContentsOfURL:mapDataURL];
}