所有 IBOutlets 都是零

Posted

技术标签:

【中文标题】所有 IBOutlets 都是零【英文标题】:All IBOutlets are nil 【发布时间】:2015-04-25 13:24:21 【问题描述】:

您好,我正在使用以下代码初始化 viewController:

 var aboutUsViewController = self.storyboard?.instantiateViewControllerWithIdentifier("AboutUsViewController") as AboutUsViewController

在此之后,我转到aboutViewController。但是我在aboutViewController 上的所有IBOutlets 都是nil!为什么呢? 我正在使用 MMDrawer 库来获得侧边栏菜单。

 var aboutUsViewController = self.storyboard?.instantiateViewControllerWithIdentifier("AboutUsViewController") as AboutUsViewController


        var aboutUsNavController = UINavigationController(rootViewController: aboutUsViewController)

        var appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate

        appDelegate.centerContainer!.centerViewController = aboutUsNavController
        appDelegate.centerContainer!.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion: nil)

在侧边栏上,我选择了关于我们的菜单项,在创建 AboutViewController 并将其移动到左侧之后......问题是当我初始化我的控制器时,出口为零

我在使用 pageViewController 时也遇到了这样的问题:

class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate 


let pageTitles = ["Title 1", "Title 2", "Title 3", "Title 4"]
var images = ["long3","long4","long1","long2"]
var count = 0


var pageViewController : UIPageViewController!

override func viewDidLoad() 
    super.viewDidLoad()
    reset()
    // Do any additional setup after loading the view, typically from a nib.


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


func reset() 
    /* Getting the page View controller */
    pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as UIPageViewController
    self.pageViewController.dataSource = self

    let pageContentViewController = self.viewControllerAtIndex(0)
    self.pageViewController.setViewControllers([pageContentViewController!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)

    /* We are substracting 30 because we have a start again button whose height is 30*/
    self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height - 30)
    self.addChildViewController(pageViewController)
    self.view.addSubview(pageViewController.view)
    self.pageViewController.didMoveToParentViewController(self)




func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? 

    var index = (viewController as PageContentViewController).pageIndex!
    index++
    if (index >= self.images.count)
        return nil
    

    return self.viewControllerAtIndex(index)



func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? 
    var index = (viewController as PageContentViewController).pageIndex!

    if index<=0 
        return nil
    
    index--
    return self.viewControllerAtIndex(index)


func viewControllerAtIndex(index : Int) -> UIViewController? 
    if((self.pageTitles.count == 0) || (index >= self.pageTitles.count)) 
        return nil
    
    let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageContentViewController") as PageContentViewController

    pageContentViewController.imageName = self.images[index]
    pageContentViewController.titleText = self.pageTitles[index]
    pageContentViewController.pageIndex = index
    return pageContentViewController


func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int 
    return pageTitles.count


func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int 
    return 0
    





class PageContentViewController: UIPageViewController 


@IBOutlet var imageViewMain: UIImageView!

@IBOutlet var labelMain: UILabel!

var pageIndex: Int!
var titleText: String!
var imageName: String!


override func viewDidLoad() 
    super.viewDidLoad()

    self.imageViewMain.image = UIImage(named:imageName)
    self.labelMain.text = self.titleText
    self.labelMain.alpha = 0.1
    UIView.animateWithDuration(1.0, animations: ()-> Void in
        self.labelMain.alpha = 1.0
    )
    // Do any additional setup after loading the view.


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.



/*
// MARK: - Navigation



  // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    
    */


我遇到标签和图像出口为零的问题!!!我在使用 MMDrawer 库时遇到了同样的问题。同样的情况。我没有使用 segues !我想因为那个网点是零

【问题讨论】:

你已经扩展了这个来展示你如何使用aboutUsViewController(谢谢),但是你没有告诉我们你在那个仍然是@987654329的视图控制器上使用这个插座的地方@。 nil 是哪个网点?这个问题出现在哪里? 很抱歉回答迟了。问题出现在 aboutUSViewController 上。在主板上,我添加了标签并控制将它们拖到 aboutUSViewController 中。我在 viewdidload 中设置标签的值。但我有一个奇怪的错误,所有标签出口都是零 我找到了答案。我没有创建 UIViewController ,而是创建了 UIPageViewController 【参考方案1】:

我假设您在实例化场景后立即查看插座(如果使用 segue 并尝试使用 prepareForSegue 中的插座,您也会看到这种行为)。但是,直到您呈现/推送到该场景,加载视图并调用 viewDidLoad 之后,插座才会连接。

底线,在调用viewDidLoad 之前不要尝试使用出口(即不要在实例化场景后立即使用出口)。相反,将所需的数据传递给目标场景(例如 String 属性),然后目标的 viewDidLoad 应该填充出口。

例如,您可能在AboutUsViewController 中有一个属性:

var message: String!

当您实例化 AboutUsViewController 时,您将设置该属性:

let aboutUsViewController = self.storyboard?.instantiateViewControllerWithIdentifier("AboutUsViewController") as AboutUsViewController // use `as!` in Swift 1.2

aboutUsViewController.message = "some message"

presentViewController(aboutUsViewController, animated: true, completion: nil)

然后AboutUsViewControllerviewDidLoad 将使用该属性相应地填充插座:

override func viewDidLoad() 
    super.viewDidLoad()

    label1.text = message

但是您永远不会让原始视图控制器尝试设置/调整目标场景的出口。这是AboutUsViewController的责任。


只是为了确认一下,您的网点连接正确吗?下面显示了两种确认它们已正确连接的方法。

当您在 Interface Builder 中选择视图控制器然后查看连接检查器时,您是否看到您的插座连接在那里?在以下快照中,label1 已连接,但 label2 未连接:

或者当您查看您的代码并查看插座时,您是否在左边距看到实心点(表示插座已连接)或空点(表示插座未连接)?

【讨论】:

您好 Rob,我正在使用 MMDrawer 库来添加侧边栏!所以我根本没有使用 perform segue。我只是在创建视图控制器并将其移动到左侧......见上文,我编辑了我的问题 明白。 (我只提到 segues 是因为它们遇到了同样的问题,并且试图帮助偶然发现这个问题的未来读者。)我的观点是两个问题之一是可能的:要么您在加载视图之前使用插座(请记住,这不会在您实例化视图控制器时发生,而是稍后在实际呈现视图时发生)或者在 IB 中未正确连接出口。 Rob 我在使用 pageViewController 时遇到了同样的问题。【参考方案2】:

您可以在演示前使用此功能,ios9 及更高版本可用:

    aboutUsViewController.loadViewIfNeeded()

【讨论】:

【参考方案3】:

我找到了答案。我没有创建 UIViewController ,而是创建了 UIPageViewController !!!

【讨论】:

以上是关于所有 IBOutlets 都是零的主要内容,如果未能解决你的问题,请参考以下文章

IBOutlet 和 IBAction

公共与私人 IBOutlets

在swift中,为什么UIlabel是可选的?

使用 OCMock 检查 IBOutlet 连接

instantiateViewControllerWithIdentifier 之后的 IBOutlet nil

单个对象,多个 IBOutlets