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
Related
I'm a newbie in iOS programming, i am trying to make an iOS library that can be useful on my future applications. The app will have a button that will call the library and will load a website(the address link will come from the application).
I tried searching but none of it is working.
WebLibrary.h
#import <Foundation/Foundation.h>
#interface WebLibrary : NSObject
- (void)showUIWebView:(NSURL*)urlToOpen
{
/* UIViewController *myVC = [self.navigationController.viewControllers lastObject];
//This is your last view in the navigationController hierarchy.
UIWebView *newWebView = [[UIWebView alloc] initWithFrame:myVC.view.frame];
[myVC.view addSubview:newWebView];
*/
}
#end
WebLibrary.m
#import "WebLibrary.h"
#implementation WebLibrary
/* -(void) showUIWebView:(NSURL*)urlToOpen
{
//some codes here
}
*/
#end
If you want to load an URL on your webview, you need to call the loadRequest: method to perform it, example:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:_urlPath]];
[request addValue:#"YES" forHTTPHeaderField:#"Mobile-App"];
[_webView loadRequest:request];
You can add the webview to your viewcontroller in viewDidLoad method:
-(void) viewDidLoad{
[super viewDidLoad];
//custom your view
_webView = [[UIWebView alloc] initWithFrame: self.view.frame];
_webView.scalesPageToFit = YES;
[self.view addSubView: _webView];
}
You should read about UIViewController and the methods in it to understand clearly.
In my app, I am trying to make a splash image appear as my UIWebView loads so it is not just a blank screen. However my webViewDidFinishLoad method will not work. This means that the splash image appears but does not disappear from the screen once the UIWebView has loaded.
My code for the method is:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(#"content loading finished");
[loadingImageView removeFromSuperview];
}
Any help on why the method will not work would be appreciated greatly.
My .h:
#interface ViewController : UIViewController
-(IBAction)makePhoneCall:(id)sender;
#property (nonatomic, strong) IBOutlet UIWebView *webView;
#property(nonatomic, strong) UIImageView *loadingImageView;
#end
My ViewDidLoad and webViewDidFinishLoading:
- (void)viewDidLoad {
UIWebView *mWebView = [[UIWebView alloc] init];
mWebView.delegate = self;
mWebView.scalesPageToFit = YES;
[super viewDidLoad];
}
//**************** Set website URL for UIWebView
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.sleafordpizza.com/food"]]];
//**************** Add Static loading image to prevent white "flash" ****************/
UIImage *loadingImage = [UIImage imageNamed:#"LittleItalyLogo.png"];
loadingImageView = [[UIImageView alloc] initWithImage:loadingImage];
loadingImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"LittleItalyLogo.png"],
nil];
[self.view addSubview:loadingImageView];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(#"content loading finished");
// Remove loading image from view
[loadingImageView removeFromSuperview];
}
Hi probably you do not set proper delegate.
This is small code tip for you.
-(void)viewDidLoad {
mWebView = [[UIWebView alloc] init];
mWebView.delegate = self;
mWebView.scalesPageToFit = YES;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
[loadingImageView removeFromSuperview];
NSLog(#"finish");
}
In you're .h file add.
#interface MyView: UIViewController <UIWebViewDelegate> {
UIWebView *webView;
}
Code fixes.
For .h file
#interface ViewController : UIViewController<UIWebViewDelegate>
-(IBAction)makePhoneCall:(id)sender;
#property (nonatomic, strong) IBOutlet UIWebView *webView;
#property(nonatomic, strong) UIImageView *loadingImageView;
#end
For .m file
- (void)viewDidLoad
{
[super viewDidLoad];
webView.delegate = self;
//**************** Set website URL for UIWebView
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.sleafordpizza.com/food"]]];
//**************** Add Static loading image to prevent white "flash" ****************/
UIImage *loadingImage = [UIImage imageNamed:#"LittleItalyLogo.png"];
loadingImageView = [[UIImageView alloc] initWithImage:loadingImage];
loadingImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"LittleItalyLogo.png"],
nil];
[self.view addSubview:loadingImageView];
}
At certain times, this delegate method actually never gets fired. I have had severe problems with the same thing in some of my projects.
At one occasion, I actually had to solve it with a timer, checking the state of the web view every second or so to see if I could proceed.
In that particular case, I just needed a certain element to be present. Still, the view did not trigger the finish loading event, due to external script errors being injected.
So, I just started a trigger when the web view begun loading, then called a method every now and then to see if the web view contained the element in question.
- (void)methodCalledByTimer {
if (<I still do not have what I need>) {
//The web view has not yet finished loading; keep checking
} else {
//The web view has finished loading; stop the timer, hide spinners and proceed
}
}
You could also check if the web view is actually loading, if that is absolutely necessary:
- (void)methodCalledByTimer {
if (self.webView.isLoading) {
//The web view has not yet finished loading; keep checking
} else {
//The web view has finished loading; stop the timer, hide spinners and proceed
}
}
Then, naturally, I'd check for the finishedLoading event as well, just to be sure. Remember to also implement the webView:didFailLoadWithError: method as well.
When waiting for a web page to finish loading, there are some things to keep in mind.
For instance, do you really need it to stop loading, or is there anything else you can do? In my case, I needed an element. Being able to properly execute a script is another thing that may be required.
Second, is the loading page using any external resources? I once had external script errors causing the webViewDidFinishLoad: method to not being called at all. If I removed the external scripts, it worked.
Third, if the page is using external resources, you are exposed not only to the loading capacity of your own resources, but that of the external resources as well. Tracking scripts, ads etc...if one resource provider is delivering content sloooowly (or not at all), you could page could be stuck in loading state forever.
So, I'd go with checking for something else. :)
I see you aren't handling errors. If there is an error, all subsequent delegate calls will not happen. I was surprised to find that this is true when the webview uses a plugin too. It calls this error method telling you that the webview handed off to the delegate, in my case the movie player.
implement this and see if that is it.
-(void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
if (error.code == 204) {
//request was handled by a plugin instead of by the webview directly
...
}
else
{
NSLog(#"didFailLoadWithError. ERROR: %#", error);
}
}
I was able to do all the remaining loading work in this method instead of the webviewdidfinishLoad
I am a real noob in ios dev. Now i am working on my study project using Zxing.
I make my own project which included dependency third party libraries(Zxing).
Once I scan QRCode which contains with a URL inside, my project will call a class in Zxing library then alert an alertView.
After that, once I click open button on pop-up alertView, it would open that URL by activating Safari.
the code in Zxing looks like this:
//============================================================
- (void)openURL {
[[UIApplication sharedApplication] openURL:self.URL]; //<===== open URL by Safari browser.
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != [alertView cancelButtonIndex]) {
// perform the action
[self openURL];
}
}
//========================================================
However, my wish is I would like to open that URL in my own webView which constructed by Interface Builder in my "own project" NOT by Safari. Do you have any suggestions? What I have to code in (void)openURL {} ? I got stuck with this issue for 3 days and I now seem to be crazy [p]
Thank you very much for your advance help.
Cheers,
What i did to do this is that I make a new view controller which has webView in it. A property URLstring which get set when the OpenURL method starts. You have to implement delegate methods of webView if you need. The code that I am using is
in WebViewCOntroller.h
#interface WebViewController : UIViewController <UIWebViewDelegate>{
IBOutlet UIWebView *webView;
UIView *activityView;
}
#property (nonatomic, retain) NSString *buyProductLink;
#end
in WebViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
webView.scalesPageToFit = YES;
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:self.buyProductLink]];
[webView loadRequest:request];
[request release];
}
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
return YES;
}
- (void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[activityView removeFromSuperview];
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
[activityView removeFromSuperview];
[activityView release]; activityView = nil;
}
In openURL method use
WebViewController *webViewVC = [[WebViewController alloc] initWithNibName:#"WebViewController" bundle:nil];
webViewVC.buyProductLink = [NSString stringWithFormat:#"%#",result];
[self.navigationController pushViewController:webViewVC animated:YES];
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.
I've using shouldStartLoadWithRequest very successfully in one of my programs, but the whole project was a proof of concept and scruffy and I'm starting afresh with a new project.
However shouldStartLoadWithReqest is no longer being invoked for me but I can't see where the important difference between the two projects is (however one difference is the first is using .nibs, in the 2nd I'm not using them).
To get things started I'm using a controller with the UIWebView as its view:
#interface IMSRootController : UIViewController <UIWebViewDelegate> {
UIWebView* webView;
}
(webView is declared as a #property and #synthesized)
- (void)loadView {
[super loadView];
webView = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = webView;
[webView release]; }
- (void)viewDidLoad {
[super viewDidLoad];
[[self navigationController] setNavigationBarHidden:YES animated:NO];
[self displayPage]; }
-(void) displayPage { ... [webView loadHTMLString:self.htmlString baseURL:baseURL]; }
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
...
What's wrong?
Thanks
Your object is not being set as a delegate of the UIWebView object, hence you will not receive any delegate messages. At some point, either in loadView or even displayPage (but before the call to loadHTMLString:baseURL:), do:
webView.delegate = self;