设置WebView代理后崩溃

3
我已经在ViewController的viewDidLoad方法中开发了webView。
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];

我在MyDelegate类的实例上设置了委托。

在MyDelegate类中:

#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

我的应用在加载时崩溃了。

如果我不加载HTML内容,只是URL(例如'google.com'),也会发生崩溃。

当我注释掉'webView.delegate = delegate;'时,就不会出现崩溃。

我知道我可以在ViewController.h中使用这个:

@interface ViewController : UIViewController<UIWebViewDelegate>

在viewDidLoad中添加如下代码:

webView.delegate = self;

但我需要使用其他类作为代理(而不是ViewController),但是WebView必须位于ViewController中。

我该如何做到这一点? 帮帮我!


对于其他类作为委托,您可以使用协议。 - Saurabh Jain
崩溃信息是什么? - Saurabh Jain
我没有收到任何消息。 应用程序停留在 'return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));' 这一行。 - Katya
我看到了 - 线程1 exc_bad_access (code=1 address=0x8) - Katya
控制台中有任何崩溃消息吗? - Larme
显示剩余3条评论
4个回答

1
让我指出根本原因。UIWebView委托属性是一个弱引用(在Swift源代码中为“unowned(unsafe)”),这意味着它的内存可以随时释放。
因此,要解决这个问题,您必须将一个引用作为类属性保存到控制器中。
以下是在Swift中成功测试的解决方案示例:
class MyUIViewController : UIViewController{
    let leftDelegate:MyWebViewDelegate = MyWebViewDelegate()
    ...
}

0
- (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

0
我发表了一个单独的答案,因为我认为有必要提供明确的Objective-C解决方案,因为OP可能会错过David GONZALEZ的答案,因为它是用Swift编写的,尽管他完全掌握了它。
问题在于当Web视图调用其委托时,该委托已被释放。因此,解决方案是将MyDelegate类型的属性添加到ViewController私有扩展声明中:
@interface ViewController ()
@property (nonatomic, strong) MyDelegate* webViewDelegate;
@end

然后将在-viewDidLoad中创建的MyDelegate实例存储在该属性中:

...
id <UIWebViewDelegate> delegate =[[MyDelegate alloc] init];
webView.delegate = delegate;
self. webViewDelegate = delegate;
...

0
在您的ViewController中,您可以实现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;

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接