ARC - UIWebView / UIViewController在内存中徘徊?

时间:2013-05-02 20:49:06

标签: iphone ios objective-c ios6 automatic-ref-counting

我的旧UIWebViews似乎在使用ARC时仍然存在,出于某种原因,即使在我的UIViewController出来之后它们仍然出现在OSX Safari的开发者工具中。

我正在分配一个转换到包含UIWebView的视图控制器,如下所示:

    //Create settings view/tabbar
    UITabBarController *tabController = [[NoRotateTabBarController alloc] init] ;

    StyleViewController *styleTab = [[StyleViewController alloc] initWithNibName:@"StyleViewController" bundle:nil];
    styleTab.tabBarItem.title = @"Style";
    styleTab.tabBarItem.image = [UIImage imageNamed:@"EyeIcon.png"];

    NSArray *tabsArray = @[styleTab];
    tabController.viewControllers = tabsArray;

    prevView = self.window.rootViewController;

    [UIView
        transitionWithView:self.window
        duration:0.5
        options:UIViewAnimationOptionTransitionFlipFromRight
        animations:^(void) {
            BOOL oldState = [UIView areAnimationsEnabled];
            [UIView setAnimationsEnabled:NO];
            self.window.rootViewController = tabController;
            [UIView setAnimationsEnabled:oldState];
        }
    completion:nil];

我是这样看的:

    [UIView
        transitionWithView:self.window
        duration:0.5
        options:UIViewAnimationOptionTransitionFlipFromLeft
        animations:^(void) {
            BOOL oldState = [UIView areAnimationsEnabled];
            [UIView setAnimationsEnabled:NO];
            self.window.rootViewController = prevView;
            [UIView setAnimationsEnabled:oldState];
        }
    completion:nil];

UIWebView(int StyleViewController)正是以这种方式创建的:

    @implementation StyleViewController
    UIWebView *webView;

    //viewDidLoad
    webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1)];
    webView.scalesPageToFit = NO;
    webView.scrollView.scrollEnabled = false;
    webView.multipleTouchEnabled = false;
    webView.alpha = 0;
    webView.backgroundColor = [UIColor clearColor];
    webView.opaque = false;

    @end

但是,我注意到当我在Safari中检查时,旧的UIWebViews似乎在堆叠,而旧的UIWebViews仍显示在菜单中。这是Safari的开发人员工具中的错误吗?有没有办法确保我的UIWebViews被释放?

3 个答案:

答案 0 :(得分:3)

问题是代表们。我正在使用WebViewJavascriptBridge,它与代表做了一些时髦的东西,所以我需要先摆脱它。在我的viewWillDisappear选择器中执行此操作会使其无法保留:

- (void) viewWillDisappear:(BOOL)animated { /* or dealloc */
    [super viewWillDisappear:animated];

    _bridge = nil;

    //UIWebView #1
    [webView removeFromSuperview];
    webView.delegate = nil; webView = nil;

    //UIWebView #2
    [textView removeFromSuperview];
    textView.delegate = nil; textView = nil;
}

感谢所有优秀的答案,无论如何!

答案 1 :(得分:1)

通常,当您遇到这种情况时,您会发现某些内容正在保留这些观点。将断点或日志消息添加到所有自定义子类的dealloc方法中,并查看是否有任何dealloc。如果是这样,其中一个是UIWebViews的所有者,那么你就得挖掘。

如果你只是陷入困境并且无处可去,那么复制你的应用程序(整个文件夹),并在上面的代码中删除所有复杂的类(逐个)并使用一个简单的UIViewController子类与日志消息dealloc。通过非常简单的类,你应该能够获得项目所以deallocs。他们开始逐个放回你的自定义类,直到dealloc停止。这应该可以帮助您缩小问题的范围。

您可能知道,阻止保留周期或使用强代理可能会导致问题。我注意到UIWebView明确声明如果你使用它,你应该将委托设置为nil,然后再处理它。 [NSURLConnection也保留了代表。]

答案 2 :(得分:0)

由于您在动画块中引用self.window.rootViewController,看起来您正在保留周期。

使用ARC,可以复制块,从而捕获块中使用的变量。因此,您需要创建一个__weak对self的引用,以便在块中使用。

像这样:

__weak SomeObjectClass *weakSelf = self;

SomeBlockType someBlock = ^{
    SomeObjectClass *strongSelf = weakSelf;
    if (strongSelf == nil)
    {
        // The original self doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
    }
    else
    {
        [strongSelf someMethod];
    }
};

请参阅“阻止”部分:ARC Best Practices