Swift 禁用导航控制器按钮直到 viewDidLoad 完成

Swift Disable Navigation Controller buttons Until viewDidLoad is completed

VC1 是我在项目中的主页,我可以从 VC1 转到 5 个不同的视图控制器。在 VC1 viewDidLoad 中,我正在从我的 Firestore 数据库下载数据,我需要将它们全部加载到 phone,然后才能允许用户与导航栏中的按钮进行交互。这是我的 VC1 的样子(底部 3 个按钮,顶部 2 个按钮):

但目前用户可以在 viewDidLoad 中的数据未完全加载到 phone 时单击 VC1 中的按钮并让它们从 VC1 转到 VC2(如果它们足够快,它们可以完成此操作).

除非 viewDidLoad 中的所有功能都已完成,否则如何防止用户与导航栏中的按钮进行交互?

override func viewDidLoad() {
    super.viewDidLoad()
func1()
func2()
func3()
}

不确定这是否相关,但在我的 AppDelegate 中,这是我定义 rootViewController 的方式:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

let storyboard = UIStoryboard(name: "Main", bundle: .main)
        window?.rootViewController = storyboard.instantiateViewController(withIdentifier: "TabBarController")
}

这就是我在主情节提要中的内容:

这是我的家庭故事板:

viewDidLoad 处于 运行ning 时,用户无法触摸任何按钮。或者更准确地说:当 viewDid...viewWill... 函数处于 运行 状态时,按钮不会对事件做出反应。这是因为所有这些方法都在主线程中执行,并且会阻止任何用户交互。

我假设您的“问题”是因为 func1(),2 或 3 正在调用网络服务,通常是在任意工作线程中 运行。因此,func1 returns 在所有数据被提取之前,因此 viewDidLoad returns 对你来说太早了。

因为你不应该 运行 主线程中的网络调用(Firestore 调用也不会这样做),你需要做一些额外的工作,例如:

  • viewDidLoad 中,禁用您不希望用户与之交互的所有按钮
  • 在 Firestore 处理程序中,检查是否已收到所有数据,然后再次启用按钮(在主线程中,您可能需要为此调用 DispatchQueue.main.async
  • 如果您有多个后台作业 运行ning 并且您需要等待所有作业,您可以使用 DispatchGroup