ViewController 加载两次

Posted

技术标签:

【中文标题】ViewController 加载两次【英文标题】:ViewController loading twice 【发布时间】:2016-12-27 15:44:11 【问题描述】:

我正在使用目标 C 和 swift 3 的组合。

在我的 mainView(目标 C)中,我有以下内容

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:[NSBundle mainBundle]];
    CourseViewController *courseView = (CourseViewController*)[storyboard instantiateViewControllerWithIdentifier:@"courseView"];
    [self.navigationController pushViewController:courseView animated:YES];

在我的故事板中,我的 mainView 将显示一个导航控制器,它是 swift 3 视图的 rootView。

在 swift 3 视图控制器中,我有以下内容,并且 loadView 和 viewDidLoad 被调用了两次

override func loadView() 
    webView = WKWebView()

    //If you want to implement the delegate
    webView?.navigationDelegate = self

    view = webView


override func viewDidLoad() 
    super.viewDidLoad()
    let temp: CGRect = UIScreen.main.bounds
    screenSize = temp
    let url = URL(string: kcourseURL)
    let req = URLRequest(url: url!)
    webView.allowsBackForwardNavigationGestures = true
    webView.load(req)
    //webView.frame = CGRect(x:0, y:navBarHeight, width:Int(screenSize.width), height:Int(screenSize.height))

    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)

    self.setBarButton()



关于为什么它被调用两次的任何建议?

另外,我试图关闭此视图以返回主视图,但如果我在 swift 3 视图上使用导航控制器,它不会被调用。我试过以下。我是否需要使用 segue unwind 来返回主视图?

        self.dismiss(animated: true, completion: nil)

    _ = self.navigationController?.popToRootViewController(animated: true)

【问题讨论】:

在使用 Storyboard 时,为什么要显式实例化视图控制器? 你在Storyboard 的两个viewControllers 之间设置了一个segue 吗? 我在故事板的 2 个视图之间设置了 segue。课程视图有一个导航控制器作为根视图。我明确地实例化视图,因为我在目标 c 中这样做,不知道当我对 Swift 实现执行目标 c 时它会如何变化。如果我不实例化它,则不会仅通过情节提要设置调用视图。 【参考方案1】:

如果您在应用程序导航控制器中使用,那么如果您使用 Segue 进行导航,我需要在此处清除一件事,那么在 的帮助下无需再次调用相同的视图>code 在这里只选择一个进程。导航将取决于您想要哪种类型,例如推送、显示、模态呈现和弹出框呈现。

之后只需要使用一行来返回视图或返回根视图:-

 self.dismiss(animated: true, completion: nil)

_ = self.navigationController?.popViewController(animated: true)

用于返回 Rootview

_ = self.navigationController?.popToRootViewController(animated: true)

对于导航,一个故事板到另一个故事板:-

Objective-C

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
SecondViewController *second = (SecondViewController *)[storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
[self.navigationController pushViewController:second animated:YES];

斯威夫特 3

let storyboard = UIStoryboard(name: "Customer", bundle: nil)
let secondVC =   storyboard.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC
self.navigationController!.pushViewController(secondVC, animated: true)

并尝试使用 Segue

首先需要获取storyBoard 引用,然后添加storyBoardname,然后在Referenced Id 中添加ViewController 的StoryBoard ID。

并确认您的目标控制器的Storyboard ID

最后使用数据segue标识符执行Segue:-

 let segueIdentifier = "fourthView"

 //MARK: - Navigation
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if segue.identifier == segueIdentifier 
          let controller = segue.destination as! FourthVC
          //Passing Values here
          controller.promoViewModel =  promotionModel[0]
        
    

输出将如下图所示,无需做任何额外的事情:-

【讨论】:

我正在使用 segue,在 Perform segue 中,我调用以下 UIStoryboard storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:[NSBundle mainBundle]]; CourseViewController *courseView = (CourseViewController)[storyboard instantiateViewControllerWithIdentifier:@"courseView"]; [self.navigationController pushViewController:courseView 动画:YES]; 我已经尝试了所有这 3 种方法,但它不会关闭并返回根视图。如果我不使用导航视图作为根视图,那么这些都可以工作,但是我会丢失所有按钮的导航栏 您在同一个故事板或另一个故事板中执行segue?如果您在这里执行从一个故事板到另一个故事的转场,我将更新我的答案。 谢谢。看起来我唯一需要的是 [self performSegueWithIdentifier:@"training" sender:self];然后故事板中的一个segue称为训练。我在 prepareForSegue 中添加了另一个调用,它再次触发了视图。感谢您的帮助!【参考方案2】:

检查您是否在哪里调用了loadView() 方法,因为您的代码并非全部发布,如果是:

你不应该直接打电话给loadView(),根据苹果的doc

你不应该直接调用这个方法。视图控制器在其视图属性被请求但当前为 nil 时调用此方法。此方法加载或创建视图并将其分配给视图属性。

如果视图控制器具有关联的 nib 文件,则此方法从 nib 文件加载视图。如果 nibName 属性返回非 nil 值,则视图控制器具有关联的 nib 文件,如果视图控制器是从情节提要中实例化的,如果您使用 init(nibName:bundle:) 方法显式为其分配了一个 nib 文件,则会发生这种情况,或者如果 ios 在应用程序包中找到一个名称基于视图控制器的类名的 nib 文件。如果视图控制器没有关联的 nib 文件,则此方法将创建一个普通的 UIView 对象。

如果子类不使用 nib,则应在此处创建自定义视图层次结构。永远不应该直接调用。

无论你为 Xib 加载视图还是自己创建视图,viewDidLoad 总是会在视图加载完成后被调用。

把你的代码放在下面:

webView = WKWebView()

//If you want to implement the delegate
webView?.navigationDelegate = self

view = webView

loadView()viewDidLoad(),并删除loadView()方法。


编辑 - 1

我写了一个演示来测试你的混合项目,我发现它不是因为loadView(),我尝试使用perform segue并使用navigationController push,没有工作,所以我的答案不适合你,我我发现为什么混合演示中有问题,奇怪。

【讨论】:

我看不到问题中loadView() 的调用位置。 我没有调用 loadView,它是自动调用的。但在我的实现中,loadView 和 viewdidload 被触发了两次,所以我的视图加载了两次。

以上是关于ViewController 加载两次的主要内容,如果未能解决你的问题,请参考以下文章

ViewController 关闭 swift ios

动态呈现 ViewController

如何找到推送了哪个 viewController?

为啥返回 ViewController 时 tableView Cell 会被选中?

单击单元格时,Viewcontroller 出现两次

如何从自定义 UITableViewCell 获取值到 ViewController?