【问题标题】:Swift Disable Navigation Controller buttons Until viewDidLoad is completedSwift 禁用导航控制器按钮直到 viewDidLoad 完成
【发布时间】:2020-07-20 16:28:27
【问题描述】:

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

但当前用户可以在 viewDidLoad 中的数据未完全加载到手机时单击 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")
}

这就是我在主故事板中的内容:

这是我的家庭故事板:

【问题讨论】:

    标签: swift navigation uinavigationcontroller uinavigationbar viewdidload


    【解决方案1】:

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

    我认为您的“问题”是因为func1(), 2 或 3 正在调用网络服务,这些服务通常在任意工作线程中运行。因此,func1 在获取所有数据之前返回,因此viewDidLoad 对您来说返回太早。

    由于您永远不应该在主线程中运行网络调用(Firestore 调用也不会这样做),因此您需要做一些额外的工作,例如:

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

    【讨论】:

    • 你是对的!所以这就是我所做的。在 viewDidLoad 我输入了UIApplication.shared.beginIgnoringInteractionEvents(),然后一旦函数成功,我就结束了忽略:UIApplication.shared.endIgnoringInteractionEvents()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2013-12-24
    • 2018-06-01
    相关资源
    最近更新 更多