IOS Push ViewController from AppDelegate.h - ios

I'm using a StoryBoard which contains various ViewControllers and a TableViewController, one in particular is ImageViewController which just displays an image. My DetailViewController contains a UIWebView, here I have a link, when pressed I am trying to load a my ImageViewController.
The link is View Image`
In AppDelegate.m I get the filename value by handling handleOpenURL.
I'm new to IOS and struggling how to load my ImageViewController from the handleOpenURL method in AppDelegate.m.
My code is:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
NSString *param = [keyValueParm objectForKey:#"filename"];
NSLog(#"Param: %#",param);
ImageViewController *imageViewController =[[ImageViewController alloc]init];
imageViewController.imageString = param;
UIViewController *root = self.window.rootViewController;
[root.navigationController pushViewController:imageViewController animated:YES];
return true;
}
At present nothing happens.

You should't implement the application:handleOpenURL: method. Not only it is deprecated, but what it does is ask the application delegate to allow opening an URL in the browser.
What you want to do instead is implement the UIWebViewControllerDelegate protocol in the DetailViewController. Specifically you should implement the – webView:shouldStartLoadWithRequest:navigationType: method. In it:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
[ImageViewController *imageViewController =[[ImageViewController alloc]init];
imageViewController.imageString = param;
[root.navigationController pushViewController:imageViewController animated:YES];
return YES;
}
In this method, the UIWebView instance asks its delegate for permission to open an url.
Hope it helps

Take care, this method is depecrated :
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html
Also, be sure to have your app delegate application:didFinishLaunchingWithOptions: method to return YES or if your delegate implements the applicationDidFinishLaunching:, your code won't get called :
This method is not called if the delegate returns NO from its implementation of the application:didFinishLaunchingWithOptions: method. if your application implements the applicationDidFinishLaunching: method instead of application:didFinishLaunchingWithOptions:, this method is called to open the specified URL after the application has been initialized.

Related

iOS : How to override the button action of UIWebView and call our own Objective C method

I am loading a url in UIWebView in iOS. the url contains a button. I want to call a objective C method, when i click on this button. Please help.
This is source code
NSString *strUrl = #"<html><body><button type=\"button\" id=\"success_id\" style=\"width:200px;margin:0px auto;text-align:center; background:#1B2F77;color:#fff;padding:10px;font-size:10px;border:0px;\" name=\"continue\" onclick=\"ok.performClick();\">Continue</button></body></html>";
[_tempWebView loadHTMLString:strUrl baseURL:nil];
I want to load this string to UIWebview and When I click on button , then I want to open my own viewcontroller.
You need to do three things:
Override shouldStartLoadWithRequest delegate method of UIWeBView.
shouldStartLoadWithRequest method returns a bool value so return false, then it will not load the link.
Inside this method write whatever functionality you want to perform.
If it is your page, communicate with app via JavaScript otherwise you can override shouldStartLoadWithRequest method and check if this specific request is called
some code:
- (BOOL)isItThatButtonEvent:(NSURLRequest *)req {
if([req.URL.absoluteString isEqualString:#"that.specific.url.or.some.other.way.to.check.that"]) {
return YES;
}
return NO;
}
#pragma mark UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if([self isItThatButtonEvent:request]) {
[self methodThatOpensYourViewController];
return NO;
}
return YES;
}

iOS Open WebView href in new WebView

I am building an iOS application that uses the SWRevealViewController to display slide-out menus.
In my slide out menu, I have a WebView which contains some links. When a user clicks the link, I want the SWRevealViewController to slide back (I can do that easy enough), and the URL opens in the MainViewController WebView (not so easy for me).
I want to make sure, if possible, that the URL doesn't change at all in the SWRevealViewController. Just starts the action to open the URL in MainViewController.
How can I achieve this?
Add UIWebViewDelegate as an protocol your view controller implements.
Set yourself as the delegate to the UIWebView
Add the method - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType to your view controller.
Return NO from this method (unless it is for the initial page load) and capture the URL to navigate to in another view controller.
In your header add the UIWebViewDelegate protocol
#interface MyViewController : UIViewController <UIWebViewDelegate>
In your viewDidLoad set the delegate (Assuming you have an #property for the webView with an IBOutlet set to the UIWebView)
self.webView.delegate = self;
Then add the delegate method for loading requests.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString* urlStr = [[request URL] absoluteString];
if(request == nil || [urlStr isEqualToString:#"http://YourInitialURL"])
{
return YES;
}
//Use this url to change the other web view in your main view controller
NSURL* url = [request URL];
return NO;
}

Call viewdidload from appDelegate

I want to call the viewDidLoad in my view controller from my appDelegate. How do I do so?
- (void)applicationDidBecomeActive:(UIApplication *)application
{
TCAViewController *uiTCA = [[TCAViewController alloc] init];
if(uiTCA.failed == 1){
//Here I want to call viewDidLoad
// I thought something like this would work but I get an error
// [self uiTCA.viewDidLoad];
}
}
You don't call viewDidLoad, the system calls it when all the outlets have been set on the view controller.
Create a method - (void)doSomething; in your TCAViewController class and call that in your AppDelegate.
[uiTVA doSomething];

Common webViewDidStartLoad by category

I think implement completely same method to every viewController with UIWebView (and delegate=self)is not smart. So tried to setup common loading method with all UIWebView. But it did not work.
Is it wrong to achieve with category?
UIWebView+Loading.m
-(void)webViewDidStartLoad:(UIWebView*)webView
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
ViewController.h
#interface ViewController : UIViewController <UIWebViewDelegate>
ViewController.m
#import "UIWebView+Loading.h"
//abbr...
-(void)viewWillAppear:(BOOL)animated
{
UIWebView *someWebView = [[UIWebView alloc] init];
someWebView.delegate = self;
//and HTTP request
NSURLRequest *req = (abbr);
[someWebView loadRequest:req];
}
The method webViewDidStartLoad: is not being called because it is a part of UIWebViewDelegate protocol, not a method of UIWebView class itself. You have to implement it in your ViewController.m file.
Also, you may want to read about delegation pattern in iOS.
Dont need a category like UIWebView+Loading.m for this purpose.
The webview delegate methods will get executed when the loading stats and the delegate method
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(#"Started loading");
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(#"Finshed loading");
}
will get executed.The code you written is enough.Since the delegate is set to self .In the viewcontroller define these methods and thats it .You will have it working

Zombie UIWebView when it's deallocated just after alert() called from javascript

I'm using a UIWebView, and it pops an alert when a button is clicked(from javascript). There is another button (in native side), which closes controller, so deallocs also UIWebView.
The problem is, if I touch the button in UIWebView, and touch to close button before alert is populated, my controller and UIWebView are deallocated, but alert remains on screen. Then if I click any button on alert, application crashes and gives following error:
[UIWebView modalView:didDismissWithButtonIndex:]: message sent to deallocated instance
And this method is called from private method
[UIModalView(Private) _popoutAnimationDidStop:finished:]
I'm using ARC, and my dealloc is like this:
- (void)dealloc {
[_myWebView stopLoading];
_myWebView.delegate = nil;
_myWebView = nil;
}
But this does not solve my problem because I think UIModalView has a reference of my webview as a delegate, and I could not set it to nil because its private.
How can I solve it?
Regards
Find a way to set the delegate on UIAlertView to nil before deallocating UIWebView.
This is an Apple bug in their handling of the alert view. Open a bug report.
In the meantime, here are some workarounds:
Create a category on UIAlertView:
#interface UIAlertView (QuickDismiss) #end
#implementation UIAlertView (QuickDismiss)
- (void)__quickDismiss
{
[self dismissWithClickedButtonIndex:self.cancelButtonIndex animated:NO];
}
#end
Now, in your view controller's dealloc method, call this:
[[UIApplication sharedApplication] sendAction:#selector(__quickDismiss) to:nil from:nil forEvent:nil];
This will dismiss all alert views that are currently open, including the ones displayed by your web view.
If that does not work, you can always iterate all subviews of all UIApplication.sharedApplication.windows objects, checking whether [view.class.description hasPrefix:#"UIAlertView"] is true, and dismissing that. This is a less elegant method than the previous one, and should be last resort.
Good luck.
Finally, I find a great solution which actully works. I use method swizzle to hook UIAlertView Delegate function - (void)didPresentAlertView:(UIAlertView *)alertView
- (void)didPresentAlertView:(UIAlertView *)alertView
{
if ([self.delegate respondsToSelector:#selector(didPresentAlertView:)]) {
[self.delegate didPresentAlertView:alertView];
}
if ([self.delegate isKindOfClass: [UIWebView class]]) {
uiWebView = self.delegate;
}
}
I just retain UIWebView instance in this function so that the UIWebView instance as UIAlertView's delegate will not be released before UIAlertView instance being released.

Resources