【问题标题】:How UIViewControllers created - by alloc/init vs. performSegueWithIdentifierUIViewControllers 如何创建 - 通过 alloc/init 与 performSegueWithIdentifier
【发布时间】:2015-07-11 14:33:04
【问题描述】:

我的 iOS 8 项目使用 Storyboard,其中我有一个 UINavigationController,根为 UIViewController;我们称之为 A。我还有另一个UIViewController,通过Segue 连接到这个根控制器;我们称之为 B。相当标准的配置。

现在,AUITableViewController 的子类,在表中我有一个 URL 列表。应用用户点击表格单元格,URL 被提取并传递给 BBUIViewController 的子类,其中包含 WKWebView

现在,由于 BUINavigationController 的堆栈中,用户可以在 B 中点击返回按钮,返回到表网址 (A)。然后用户可以点击另一个单元格来加载另一个 URL。

因为我需要将一些数据(URL)传递给B,所以我使用performSegueWithIdentifier 调用它,并在对应的prepareForSegue 中将URL 分配给一个B 中的属性。

这一切都很好。我的问题反映了我在 iOS 和 Objective-C 方面仍处于不成熟状态。

第一个问题,当B通过performSegueWithIdentifier/prepareForSegue组合创建时,当用户点击返回按钮时,这个控制器是否被操作系统释放?换句话说,不再有这个子类UIViewController 的实例在四处飘荡?

如果是,那么如果用户点击表格单元格以查看另一个 URL,那么创建它的新实例可能是安全的。换句话说,重复调用performSegueWithIdentifier,在B的属性中分配新选择的URL等等。安全吗?

或者,如果它没有被自动释放,那么重复调用performSegueWithIdentifier 等等只会继续创建越来越多的B实例吗?

而且,无论哪种情况,当 B 首次创建时,捕获对它的引用并继续重复使用它是否有意义?换句话说,在调用 performSegueWithIdentifier 之前,检查是否已经存在对 B 的引用,如果存在,则使用对 B 的引用执行 pushViewController强>?

所以基本问题归结为:在UIViewController 需要多次可见的情况下——通过用户操作——是否每次需要时都新创建一个实例?如果是,那么这是否也意味着每个实例在不再需要时也在内部被释放?因此我不需要担心内部结构?

或者,如果我每次都继续使用performSegueWithIdentifier,我是否只是创建了一堆控制器的新实例,因此浪费且效率低下,而我可以捕获对第一个新实例的引用并保持重新- 使用它?

我尝试在调试器中逐步完成此过程并跟踪引用,但我不确定我是否看到了我应该看到的内容,因此我正在询问更多知识渊博的开发人员。

感谢您阅读这个长长的问题,并花时间回答它。

【问题讨论】:

    标签: objective-c uiviewcontroller ios8 uinavigationcontroller


    【解决方案1】:

    首先,当您推送视图和弹出视图时,如果您没有在其他任何地方保留该视图控制器,那么它将被完全释放,并且如果您调用 performSegueWithIdentifier 来创建此视图多少次并不重要没有保留它或管理它参考不够好。 但是,在这种情况下,我会使用一次创建您的“B”视图控制器

     self.bController = [self.storyboard instantiateViewControllerWithIdentifier:@"BController"];
    

    然后你使用 self.bController 调用 pushViewController,函数看起来像这样..

    - (void)presentURL:(NSString*)url
    {
        if ( self.bController == nil ) {
            self.bController = [self.storyboard instantiateViewControllerWithIdentifier:@"BController"];
        }
    
        [self.bController setURL:url];
    
        [viewController.navigationController pushViewController:self.bController animated:YES];
    }
    

    并在设置 URL 时使用以下代码刷新 WKWebView

    -(void)setUrlString:(NSString *)urlString {
        // set url string
        _urlString = urlString;
    
        // clear
        [self.webView loadHTMLString:@"" baseURL:nil];
    
        // load url with string
        if( _urlString != nil ) {
            // get address for hosting view
            NSURL* url = [NSURL URLWithString:_urlString];
            NSURLRequest* urlRequest = [NSURLRequest requestWithURL:url];
            [self.webView loadRequest:urlRequest];
        }
    }
    

    它会比 prepareForSegue 简单一些,但是,再次重复调用 performSegueWithIdentifier,在 B 的属性中分配新选择的 URL,等等。只要你不保留其他任何地方,它是完全安全的。但是性能明智的做法可能比保留一个 B viewController 实例并多次显示它要贵一些,因为它必须读取并启动视图控制器和 WKWebView 实例,因此可以说它有点膨胀..

    【讨论】:

    • 很好的答案 - 谢谢。因此,您确实确认只要没有明确保留对控制器的引用,它就会被释放。那是我真正不确定的。您提供的示例代码反映了我已经拥有的很多内容,因此也很好地确认了那里。非常感谢!你是唯一一个回答了我的问题的人,假设我没有听到任何其他内容或有很大不同,我会将其标记为你已回答。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-08-05
    • 2012-01-23
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2011-07-22
    相关资源
    最近更新 更多