OGeek|极客世界-中国程序员成长平台

标题: objective-c - Objective C - iOS - 在 webViewDidFinishLoad 执行过程中调用 Dealloc [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 11:09
标题: objective-c - Objective C - iOS - 在 webViewDidFinishLoad 执行过程中调用 Dealloc

我在 ios 中遇到内存管理问题。问题是当我将具有 webView 的 viewController 推送到导航堆栈时,当我在加载 webview 之前单击返回时,我收到了 exec_bad_access。

在“A 类”中,我创建了一个 NewViewController,然后将它推送到导航堆栈,然后释放它。所以在这里,我在发布它时放弃了我的所有权。

A类:

-(void)onButtonClick{
    NewViewController* viewController = [[NewViewController alloc] init];
    [self.navigationController pushViewController: viewController........];
    [viewController release];
}

B 类中有一个 webView 和一个计时器,并实现了 UIWebViewDelegate。所以,在这里,当 webView shouldStartLoad 我开始计时。然后当它完成加载时,我使它无效。

B类:
@interface NewViewController : UIViewController <UIWebViewDelegate>
    NSTimer* timer
    ......
@property(nonatomic, retain) IBOutlet UIWebView* webView;
@end

@implementation
-(void)viewDidLoad{
   [super viewDidLoad];
   [webView loadRequest:someRequest];
}
.....
.....
-(void)dealloc{
  [self makeTimerNil];
  [self.webView stoploading];
  self.webView.delegate = nil;
  [self.webView release];
  self.webView = nil;
  .....
  [super dealloc];
}

-(void)resetTimer{
    [self makeTimerNil];
    //timer will retain target - self
    timer = [NSTimer scheduledTimerWithTimeInterval:kNetworkTimeOut target:self selectorselector(networkTimedOut) userInfo:nil repeats:NO];
}

-(void)makeTimerNil{
    if([timer isValid]){
        [timer invalidate];
        timer = nil;
    }
}

-(BOOL)webViewUIWebView *)webView shouldStartLoadWithRequestNSURLRequest *)request navigationTypeUIWebViewNavigationType)navigationType{
    [self resetTimer];
    ......
    return YES;
}

-(void)webViewDidFinishLoadUIWebView *)webView{
    //NO Exception. Can access self
    [self anotherMethod];
    //timer releases retained target -self
    [self makeTimerNil];
    //Exception self has been deallocated
    [self anotherMethod];
}
@end

但问题是当 webView 正在加载时,如果我单击导航栏上的后退按钮,newViewController 会被释放,这很好。但这发生在 webViewDidFinishLoad 的执行过程中。为什么在执行 webViewDidFinishLoad 的过程中会调用 dealloc?它们不是在同一个线程(主 - UI 线程)上运行吗?

关于如何解决问题的任何想法?



Best Answer-推荐答案


你的问题绝对是计时器。根据 NSTimer 文档,事件计时器在其目标对象上保持保留。因此,当计时器处于事件状态时,您的 Controller 无法解除分配。这本身就是您架构中的一个错误,因为来自您的 -dealloc方法很明显,您希望在计时器处于事件状态时释放 View Controller 。但是在 webview 的情况下,它导致了另一个问题。具体来说,在你的 -webViewDidFinishLoad: 中间您取消计时器的方法。这会导致它释放它的目标,因为它是你的 View Controller 的唯一所有者, View Controller 立即释放。

关于objective-c - Objective C - iOS - 在 webViewDidFinishLoad 执行过程中调用 Dealloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9068820/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://sqlite.in/) Powered by Discuz! X3.4