更改根视图控制器将 IBOutlet 设为 nil

Posted

技术标签:

【中文标题】更改根视图控制器将 IBOutlet 设为 nil【英文标题】:Changing Root view controllers gives IBOutlet as nil 【发布时间】:2018-11-12 15:14:01 【问题描述】:

我必须根据登录状态更改我的根视图控制器。

我更改了我的 AppDelegate 文件并创建了一个扩展 UINavigationController 的 MainNavigationController 类。

**问题:- ** 加载定义的根类时,它会将所有出口变量都设为 nil。

代码

 class PostalViewController: UIViewController 

        @IBOutlet weak var btn_currentLocation: UIButton!
        @IBOutlet weak var btn_viewAccount: UIButton!
        @IBOutlet weak var in_postCode: UITextField!

        let locManager = CLLocationManager()

        override func viewDidLoad() 
            super.viewDidLoad()

// Here it gives a nil on btn_currentLocation

            btn_currentLocation.layer.cornerRadius = 15.0
            btn_currentLocation.layer.masksToBounds = true

            btn_currentLocation.setButtonGradient(colorOne: UIColor(named: "lightBlue")!, colorTwo: UIColor(named: "gradient2")!)

            btn_viewAccount.layer.cornerRadius = 15.0
            btn_viewAccount.layer.masksToBounds = true

            // Add search button in post code text field
            let searchButton = UIButton(type: .custom)
            searchButton.setImage(UIImage(named: "iconSearch"), for: .normal)
            searchButton.frame = CGRect(x: CGFloat(in_postCode.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
            searchButton.addTarget(self, action: #selector(self.actionSearch), for: .touchUpInside)
            in_postCode.rightView = searchButton
            in_postCode.rightViewMode = .always

        

AppDelegate.swift(仅限特定函数)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        // Override point for customization after application launch.

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.makeKeyAndVisible()
        window?.rootViewController = MainNavigationController() 
        return true
    

MainNavigationController.swift

class MainNavigationController : UINavigationController

    var isLogin : Bool?

    override func viewDidLoad() 
        super.viewDidLoad()
        view.backgroundColor = .white

        isLogin = UserDefaults.standard.bool(forKey: "isLogin")
        print("IsLogin --->", isLogin!)

        if (isLogin != nil && isLogin!)

            perform(#selector(postalController), with: nil, afterDelay: 0.01)

        else

            perform(#selector(showHomeContoller), with: nil, afterDelay: 0.01)
        

    

    @objc func showHomeContoller () 

        let homepageController = HomePageViewController()
        present(homepageController, animated: true, completion: nil)
    

    @objc func postalController () 

        let postalController = PostalViewController()
        viewControllers = [postalController]
    

编辑

我在下面添加了一个屏幕截图,我必须在主页和邮政之间切换我的根视图

【问题讨论】:

你在使用故事板吗? @RobertDresler 是的。我正在使用故事板 好的,看看我的回答 你可以添加你的故事板的照片吗? @RobertDresler 是的。 【参考方案1】:

我想你只想在用户登录时显示 PostalViewController。如果用户未登录,您只想显示 HomePageViewController。首先从应用委托中删除这些行,你不需要这个:

window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = MainNavigationController() 

现在删除整个导航控制器类。您将不需要它,因为您将在 HomePageViewController 中完成所有这些操作。现在在 HomePageViewController swift 文件中添加这个到 viewDidLoad()

isLogin = UserDefaults.standard.bool(forKey: "isLogin")
    print("IsLogin --->", isLogin!)

if isLogin != nil 
    performSegue(withIdentifier: "segueToPostal", sender: self)

最后设置从 HomePageViewController 到 PostalViewController

并将其标识符设置为 segueToPostal

如果您不想让用户从 Postal 视图控制器导航回来,您可以将 PostalViewController 嵌入到新的 NavigationController 中。然后只需从 HomePageViewController 设置 segue 到这个 NavigationController 并设置标识符。

【讨论】:

是的,我尝试过同样的方法,但仍然无法正常工作,它给出了相同的运行时错误 感谢您的努力,最初我已经实现了这个,但这里的问题是在邮政屏幕上,它给了我主页的后退按钮。如果我执行 segue as present,则不会显示进一步的后退导航。 @NikhilSawant 不要像现在一样执行 segue,试试我写的: performSegue(withIdentifier: "segueToPostal", sender: self) 并按照我的描述设置 segue 是的,我已经尝试过您提到的相同方式。问题出在邮政屏幕上,它再次向主页提供返回按钮,我不想这样做。 感谢罗伯特的宝贵时间。我们已经解决了。我只是应用您的方法并在邮政屏幕上隐藏了后退按钮。非常感谢。【参考方案2】:

当视图控制器使用 nib 文件初始化时设置 IBOulet。 所以你需要使用下面的 init 方法创建视图控制器

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)

例如,如果您配置 IBOultets 的 xib 文件的名称与控制器名称相同,则可以执行下一步:

let postalController = PostalViewController(nibName: "PostalViewController", bundle: nil) 

在这里,您将拥有带有初始化 IBOutlets 的控制器。

要使用故事板,您应该从故事板中初始化它们。 尝试通过以下方式初始化控制器:

let sb = UIStoryboard(name: "MainStoryboard", bundle: nil) 
let vc = sb.instantiateViewController(withIdentifier: "PostalViewController") 

您应该在您的故事板中为控制器设置故事板 ID,如下面的屏幕所示。

storyboard id

您还可以在此处找到有关如何从情节提要正确初始化视图控制器的更多信息

What is a StoryBoard ID and how can i use this?

【讨论】:

感谢您的回复,但结果仍然相同。我在 MainNavigationController 中替换了 对不起,我没有注意到你使用故事板,尝试用下一个代码创建 PostalViewController let sb = UIStoryboard(name: "MainStoryboard", bundle: nil) let vc = sb.instantiateViewController( withIdentifier: "PostalViewController") 如果你为控制器设置了故事板 ID。 让我试试。谢谢 请查看我编辑的帖子,我添加了更多信息。 @NikhilSawant 并且您是否使用 id 从故事板创建视图控制器,我在上面的评论中是如何做的?

以上是关于更改根视图控制器将 IBOutlet 设为 nil的主要内容,如果未能解决你的问题,请参考以下文章

ScrollView 中的 IBOutlet 产生 nil

Swift - 带有 xib 文件的自定义视图,IBOutlet 为 nil

iOS 8.4 - iboutlet 未填充到以编程方式创建的视图控制器中

Nil 同时展开可选的 IBOutlet 值

在 iOS 11 模拟器上运行测试时,视图控制器中的所有 IOutlet 属性均为“nil”

无法将连接器从 IBOutlet 链接到视图控制器