简体   繁体   中英

Objective C - iOS - UIWebView getting retained in ARC but Delegate methods are not being called

I am having an issue with ARC. It is not retaining the webview. The scenario is I have to send a webview from one viewcontroller to another one. The reason is when the user searches for something I want to take him to a new screen with some other options. (I have to use the same webview)

Here is the sample code: I have a ViewController1 which has a webview (I added it in the xib.) I am loading say google in it and once the user searches for something and when its done loading I have to take him to a new view controller and show the same webview in the new viewcontroller.

//ViewController1
@interface ViewController1 : UIViewController <UIWebViewDelegate>
    @property (nonatomic, retain) UIWebView* testWebView;
@end

@implementation ViewController1
@synthesize testWebView;
- (void)viewDidLoad
{
    [super viewDidLoad];
    testWebView = [[UIWebView alloc]init];
    testWebView.delegate = self;
    [testWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.com"]]];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    NSString *html = [testWebView stringByEvaluatingJavaScriptFromString: 
                      @"document.body.innerHTML"];
    if ([self.testWebView.request.url.absoluteString     rangeOfString:@"output=search"].location != NSNotFound) {
        ViewController2* newViewController = [[ViewController2 alloc] init];
        [newViewController setTestWebView:self.testWebView];
        [self.navigationController setViewControllers:[NSArray arrayWithObject:newViewController] animated:NO];
    }
}
- (void)dealloc{
    [self.testWebView stopLoading];
    self.testWebView.delegate = nil;
    self.testWebView = nil;
}

In the second view controller I am loading stackoverflow.com after a delay of 10 secs. The problem is it is loading stackoverflow fine, but it is not calling any of the delegate methods. Why?

@interface ViewController2 : UIViewController <UIWebViewDelegate>
    @property (nonatomic, retain) UIWebView* testWebView;
@end

@implementation ViewController2
@synthesize testWebView;
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.testWebView.delegate = self;
    [self.view addSubview:testWebView];
    [self performSelector:@selector(loadDifferentPage) withObject:nil afterDelay:10];
}

-(void)loadDifferentPage{
    [self.testWebView loadRequest:[NSURLRequest requestWithURL:[NSURL     URLWithString:@"http://www.stackoverflow.com/"]]];
}

-(void)webViewDidStartLoad:(UIWebView *)webView{
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

-(void)webViewDidFinishLoad:(UIWebView *)webView{
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSLog(@"%s", __PRETTY_FUNCTION__);
    return YES;
}

ViewController2 is retaining the webview but the delegate methods are not being called. Why?

Thanks Sai

ViewController1 delloc method was causing the issue:

If I uncomment out self.textWebView.delegate = nil it works fine. The reason is first we are setting the webview for newViewController and later in dealloc of ViewController1 we are setting its delegate to nil.

- (void)dealloc{
    [self.testWebView stopLoading];
    if(self.testWebView.delegate == self)
        self.testWebView.delegate = nil;
    self.testWebView = nil;
}

First thing I noticed is you're not specifying the instance variable name when synthesizing a property. That's just asking for collisions. Here's an example of how that should look:

@interface ViewController1 : UIViewController <UIWebViewDelegate>
    @property (nonatomic, strong) IBOutlet UIWebView* testWebView;
@end


@implementation ViewController1

@synthesize testWebView=_testWebView;

Also, I noticed in ViewController1 you used IBOutlet so everything is probably wired up in Interface Builder. Try making sure that you set the delegate property in Interface Bulider because you don't set it in the implementation. That would be why you're not receiving any messages.

ViewController2 looks like you set the delegate in code. The problem is, you DON'T have IBOutlet in front of the property. Normally this would mean that you simply setup the WebView in code, but in your example you do not ever create a new instance of a UIWebView control and assign it to self.testWebView. This means that if it does display on the page, it's because Interface Builder was used to create it. You couldn't set the delegate in code without using IBOutlet in front of the testWebView declaration so that's probably why it's not working in exmaple two.

@interface ViewController2 : UIViewController <UIWebViewDelegate>
    @property (nonatomic, strong) UIWebView* testWebView; // Mising IBOutlet
@end

@implementation ViewController2
@synthesize testWebView;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // missing any code that would create the webview [[UIWebView alloc] init]
    self.testWebView.delegate = self; // You set the delegate in code here
    [self.view addSubview:testWebView];
    [self performSelector:@selector(loadDifferentPage) withObject:nil afterDelay:10];
}

Hope this helps, I'd have to see your full implementation to get more specific than this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM