Crash after setting WebView Delegate - ios

I have developed the webView in method viewDidLoad in ViewController
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
id <UIWebViewDelegate> delegate =[[MyDelegate alloc] init];
webView.delegate = delegate;
NSError *error;
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSString *htmlContent = [[NSString alloc] initWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:&error];
[webView loadHTMLString:htmlContent baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
[self.view addSubview:webView];
I set the delegate on instance of class MyDelegate.
In MyDelegate Class:
#import <UIKit/UIKit.h>
#interface MyDelegate : NSObject <UIWebViewDelegate>
#end
#import "MyDelegate.h"
#implementation MyDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
return YES;
}
#end
But app my crash during start the loasding.
If I not load html content, but url ('google.com' for example) crash happens.
When I comment this 'webView.delegate = delegate;' crash doesn't happens.
I know that I can use this in ViewController.h:
#interface ViewController : UIViewController<UIWebViewDelegate>
and this in viewDidLoad:
webView.delegate = self;
but I need use other class as delegate (not ViewController), but webview must be located in ViewController.
How I can make this?
Help me!

Let me point to the root cause.
UIWebView delegate attribute is a weak reference ("unowned(unsafe)" in Swift source code), which means its memory can be freed at any time.
So to solve this, you have to keep a reference into your controller as a class attribute.
Example of solution tested successfully in Swift:
class MyUIViewController : UIViewController{
let leftDelegate:MyWebViewDelegate = MyWebViewDelegate()
...
}

- (void)viewDidLoad {
[super viewDidLoad];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
id<UIWebView> delegate =(id)self;
webView.delegate = delegate;
NSError *error;
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSString *htmlContent= [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:&error];
[webView loadHTMLString:htmlContent baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
[self.view addSubview:webView];
}
MyDelegate.h
#import <UIKit/UIKit.h>
#protocol UIWebView <UIWebViewDelegate>
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
#end
#interface MyDelegate : NSObject
#end

In your ViewController itself you can implement UIWebViewDelegate.
-(void)viewDidLoad
{
[super viewDidLoad];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
webView.delegate = self;
NSError *error;
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSString *htmlContent= [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:&error];
[webView loadHTMLString:htmlContent baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
[self.view addSubview:webView];
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return YES;
}

I'm posting a separate answer because I think there's a need to provide explicit Objective-C solution, since OP might miss David GONZALEZ's answer because it's in Swift, although he absolutely nailed it.
The problem is that by the time web view calls its delegate, that delegate has been deallocated. So the solution would be to add property of MyDelegate type to ViewController private extension declaration:
#interface ViewController ()
#property (nonatomic, strong) MyDelegate* webViewDelegate;
#end
And then to store MyDelegate instance created in -viewDidLoadin that property:
...
id <UIWebViewDelegate> delegate =[[MyDelegate alloc] init];
webView.delegate = delegate;
self. webViewDelegate = delegate;
...

Related

UIWebview set delegate method in a class

How can i set the delegate method of a UIWebView in a class?
when i do it, the app carsh.
#interface MineWebViewHandle : NSObject<UIWebViewDelegate>
#end
//.m
#implementation MineWebViewHandle
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = [[request URL] absoluteString];
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
NSLog(#"did start load");
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(#"did finished ");
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"webview error:%#",[error localizedDescription]);
}
i use it:
self.m_pWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
MineWebViewHandle *handle = [[MineWebViewHandle alloc]init];
self.m_pWebView.delegate = handle;
self.m_pWebView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.m_pWebView];
how do i use it rightly?
Your delegate look like is create in viewDidLoad,and in the end of this it´s release (put to nil).
You need create a property called: MineWebViewHandle *handle.
in your viewController.h add:
#property (nonatomic,strong)MineWebViewHandle *handle;
and change in your code:
self.handle = [[MineWebViewHandle alloc]init];
self.m_pWebView.delegate = self. handle;
And it´s good idea your webView will have dimensions, change this:
self.m_pWebView = [[UIWebView alloc] initWithFrame:self.view.frame];
Webview is the UIView, Not a controler.
Please remove the NSObject and add the UIview
#interface MineWebViewHandle : UIView
#end

Issues initializing UIWebView inside ViewController

I want to initialize a UIWebview object inside of my WebViewController. I'm having a bit of trouble initializing it, and directing it to the URL that is sent to it from the previous ViewController.
In the viewDidLoad of my WebViewController, I attempt to initialize it with the following:
UIWebView *tempWebview = [[UIWebView alloc]initWithFrame:theFrame];
NSURL *url = [NSURL URLWithString:_itemURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
self.myWebView = tempWebview;
[tempWebview loadRequest:urlRequest];
_myWebView.delegate=self;
[WebViewController loadRequest:urlRequest];
However, this gives me errors stating:
use of undeclared identifier'theFrame', and no known class method for selector loadRequest.
Full code is below:
WebViewController.h:
#import <UIKit/UIKit.h>
#import "MatchCenterViewController.h"
#interface WebViewController : UIViewController
#property (strong, nonatomic) NSURL *itemURL;
#property (weak, nonatomic) IBOutlet UIWebView *myWebView;
#end
WebViewController.m:
#import "WebViewController.h"
#interface WebViewController ()
#end
#implementation WebViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIWebView *tempWebview = [[UIWebView alloc]initWithFrame:theFrame];
NSURL *url = [NSURL URLWithString:_itemURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
self.myWebView = tempWebview;
[tempWebview loadRequest:urlRequest];
_myWebView.delegate=self;
[WebViewController loadRequest:urlRequest];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
First you need to define that you are going to use the UIWebView Delegate in your .h file as:
#interface WebViewController : UIViewController <UIWebViewDelegate>
When you already have a webView defined in your Xib file, why are you creating another UIWebView and assigning it to the IBOutlet's webView? You could simply do:
self.myWebView.delegate = self; //Note that I have set the delegate first before calling LoadRequest
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.myWebView setScalesPageToFit:YES];
[self.myWebView loadRequest:request];

Debugging xcode phase?

I'm getting one error, Ive made a UIPageController for the web but I cant seem to find the problem with it, there is only one error, please help. code bellow - more code on demand.
#interface ContentViewController ()
#end
#implementation ContentViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[_webView loadHTMLString: _dataObject baseURL:[NSURL URLWithString:#"http://"]];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
[_webView loadHTMLString: _dataObject baseURL:[NSURL URLWithString:#"http://"]];
My "Error is above"
Please help
#import <UIKit/UIKit.h>
#interface ContentViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIView *webView;
#property (strong, nonatomic) id dataObject;
#end
Change the .h file to this:
#import <UIKit/UIKit.h>
#interface ContentViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#property (strong, nonatomic) id dataObject;
#end
Beside that if you want to load a webpage in UIWebView from a url then you can do like this:
self.webView.delegate = self;
self.webView.scalesPageToFit =YES; // This will fit the page within the screen
NSURL *Url = [NSURL URLWithString:#"http://facebook.com/xxx/xxx"];
NSURLRequest *req = [[NSURLRequest alloc] initWithURL:Url];
[self.webView loadRequest:req];
If you want to load a HTML file from document then do:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"Test" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL:nil];
Or if you just want to load a string then do:
NSString* htmlString = #"";
[webView loadHTMLString:htmlString baseURL:nil];
Hope this helps .. :)

ios : UIWebview and its delegate methods in same class not working

I want to open links of uiwebview in to the safari browser my code is working perfectly if I implement shouldStartLoadWithRequest method in viewController but when I implement shouldStartLoadWithRequest in same class and set UIWebView's delegate to self it doesn't work it get halt in between and shows assembly level code with error EXC_BAD_ACCESS(code=2, address=0x9) my files are as follows
//content of ShowView.h file
#import <UIKit/UIKit.h>
#interface ShowView : UIView <UIWebViewDelegate> {
}
- (void) showViewFunction;
#property (nonatomic, assign) UIViewController *mainViewContObj;
#end
//content of ShowView.m file is :
#import "ShowView.h"
#implementation ShowView
- (void) showViewFunction {
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
aWebView.autoresizesSubviews = YES;
aWebView.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[aWebView setDelegate:self];
NSString *urlAddress = #"http://localhost/test/index.php";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
aWebView.delegate = self;
[aWebView loadRequest:requestObj];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[[[self mainViewContObj] view] addSubview:aWebView];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"In shouldStartLoadWithRequest method");
if ([[[request URL] absoluteString] isEqual:#"http://localhost/test/index.php"])
return YES;
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
#end
// Content of ViewController.h
#import "ViewController.h"
#import "ShowView.h"
#interface mnetViewController ()
#end
#implementation mnetViewController
- (void)viewDidLoad {
[super viewDidLoad];
MNETMobAd *bannerObj = [[MNETMobAd alloc] init];
bannerObj.mainViewContObj = self;
[bannerObj showAd];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Some times html page shows but when I click on link it opens in same UIWebview window, and not even going into the shouldStartLoadWithRequest method, am I doing anything wrong?
Your code isn't clear, might need more info's, but from what i see, the ShowView class is never instanciated, so it shouldn't even show.
you should make something like this i guess :
//mnetViewController.m
#import "mnetViewController.h"
#import "ShowView.h"
#interface mnetViewController ()
#end
#implementation mnetViewController
- (void)viewDidLoad {
[super viewDidLoad];
ShowView* theShowView = [[ShowView alloc] initWithFrame:CGRectMake(insert the frame you want your webview to have)];
theShowView.autoresizesSubviews = YES;
[self.view addSubview:theShowView];
[theShowView release];
MNETMobAd *bannerObj = [[MNETMobAd alloc] init];
bannerObj.mainViewContObj = self;
[bannerObj showAd];
}
now for the ShowView class, try something like this :
//ShowView.h
#import <UIKit/UIKit.h>
#interface ShowView : UIView <UIWebViewDelegate> {
}
#end
//ShowView.m
#import "ShowView.h"
#implementation ShowView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
aWebView.scalesPageToFit = YES;
[aWebView setDelegate:self];
[self addSubview:aWebView];
NSString *urlAddress = #"http://localhost/test/index.php";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[aWebView loadRequest:requestObj];
[aWebView release];
}
return self;
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"In shouldStartLoadWithRequest method for URL : %#",[request [URL absolutString]]);
if ([[[request URL] absoluteString] isEqual:#"http://localhost/test/index.php"])
return YES;
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
This should work, i didn't try it, i'll comeback tomorrow to try it if necessary.

How to get HTML content of a website

In viewDidLoad, I'm using NSURLRequest and NSURLConnection:
NSURLRequest *site_request =
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSURLConnection *site_connection =
[[NSURLConnection alloc] initWithRequest:site_request delegate:self];
and then I use
-(void)connection:(NSURLConnection *)site_connection didReceiveData:(NSData *)data
{
site_response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
and I have the whole HTML in site_response.
I want to create an invisible UIWebView which will "open" the page from the NSURLRequest in order to use JavaScript to get content like this:
NSString *myText = [my_webView stringByEvaluatingJavaScriptFromString:
#"document.documentElement......"];
In my .h I have:
UIWebView *my_webview;
#property (nonatomic, retain) UIWebView *my_webview;
and in my .m I have:
#synthesize torrents_webview;
My viewDidLoad after NSURLRequest has
[my_webview loadRequest:site_request];
and I use
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//an alertview here
}
in order to be sure it works. But nothing happens. It doesn't give an alert view.
What am I doing wrong?
webViewDidFinishLoad: is a method of the UIWebView delegate. You are not setting the delegate anywhere in the code you have shown.
#interface YourClass : UIViewController <UIWebViewDelegate>
...
- (void)loadView
{
self.webView.delegate = self;
}
...
- (void)dealloc
{
self.webView.delegate = nil;
}
Also if you use NSURLRequest you're going to get the page again. But there's no need to use NSURLConnection, just go straight to loading the UIWebVIew using the NSURLRequest.
Or if you must use NSURLConnection then when the file has downloaded save it to disk and use LoadHTMLString to load the contents.
ViewController.h
#interface TopTorrents_ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource,UIWebViewDelegate>
{
UIWebView *torrents_webview;
}
#property (nonatomic, retain) UIWebView *torrents_webview;
ViewController.m
#synthesize torrents_webview;
- (void)viewDidLoad
{
torrents_webview.delegate = self;
NSURLRequest *site_request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.gr/"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
[torrents_webview loadRequest:site_request];
[super viewDidLoad];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *myText = [torrents_webview stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('body')[0]"];
UIAlertView *my_alert = [[UIAlertView alloc] initWithTitle:#"mytitle" message:myText delegate:nil cancelButtonTitle:#"my button" otherButtonTitles:nil,nil];
[my_alert show];
}
this is my updated code... thanks

Resources