[英]Display an alert using storyboard and custom UITabBarController
我正在處理使用 UITabBarController 的問題。 我有一個使用故事板的小項目(XCode 13,IOS 15 作為基本系統)。 我創建了一個 TabBarController,但后來我發現我無法以編程方式有效地管理它。 閱讀各種文檔后,我發現我可以使用 storyboard 中的兩個場景並以編程方式創建標簽欄。 所以我在SceneDelegate.swift
中做了這個:
let queryViewControllerTab = storyBoard.instantiateViewController(withIdentifier: "QueryViewController")
let settingsViewControllerTab = storyBoard.instantiateViewController(withIdentifier: "SettingsViewController")
let starredViewControllerTab = storyBoard.instantiateViewController(withIdentifier: "StarredViewController")
starredViewControllerTab.tabBarItem.title = "Starred"
starredViewControllerTab.tabBarItem.image = UIImage(systemName: "star")
// TODO: Discover why first two views keep reading image I setup previously in storyboard
let tabBarController = UITabBarController()
tabBarController.viewControllers = [queryViewControllerTab, settingsViewControllerTab, starredViewControllerTab]
tabBarController.selectedViewController = settingsViewControllerTab
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()
這完美地工作,我可以很容易地設置一個條件是否userDefaults
沒有設置,直接加載設置。
在我的 class SettingsViewController
我想添加一個動作,在按下按鈕時,你會收到一個警報:
@IBAction func saveButtonPressed(_ sender: UIButton) {
// keychain.set(tokenInput.text ?? "", forKey: keychainKey)
let alert = UIAlertController(title: "My Alert", message: "This is an alert.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"),
style: .default, handler: { _ in
NSLog("The \"OK\" alert occured.")
}))
tabBarController.present(alert, animated: true, completion: nil)
}
但這會使應用程序崩潰, unrecognized selector sent to instance 0x7f82f9705c30'
我試圖調試問題,我明白我不能以這種方式發出警報,因為視圖實際上是 tabBar 而不是我的場景。 但在這里我卡住了。 我試圖在StarredViewController
中實現UITabBarControllerDelegate
,但我無法讓它工作。
extension StarredViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
print("did select tab bar item!")
}
}
我開始認為我使用SceneDelegate
和AppDelegate
的主要設置是錯誤的。 我發現的大多數以前的教程或線程似乎都無法編譯,因為使用了已棄用的版本。
這是一種從任何呈現的視圖 Controller 呈現警報的方法。
添加一些擴展:
import UIKit
extension UIViewController {
var customVisibleViewController: UIViewController? {
if let navigationController = self as? UINavigationController {
return navigationController.topViewController?.customVisibleViewController
} else if let tabBarController = self as? UITabBarController {
return tabBarController.selectedViewController?.customVisibleViewController
} else if let presentedViewController = presentedViewController {
return presentedViewController.customVisibleViewController
} else if self is UIAlertController {
return nil
} else {
return self
}
}
}
extension UIApplication {
/// The top most view controller
static var topMostViewController: UIViewController? {
return UIApplication.shared.keyWindow?.rootViewController?.customVisibleViewController
}
}
現在您可以通過這種方式顯示警報:
let alert = UIAlertController(title: "My Alert", message: "This is an alert.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"),
style: .default, handler: { _ in
NSLog("The \"OK\" alert occured.")
}))
UIApplication.topMostViewController?.present(alert, animated: true, completion: nil)
這是觸發警報的代碼。 使用 addAction,您可以添加可能的答案。
do {
try //some method call or something else
} catch {
let alert = UIAlertController(title: "There was an error while saving!", message: "Please try again", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "I understand", style: .cancel, handler: nil))
}
您可以在此處找到更多信息: 如何顯示警報
我解決了這個問題。 實際上,我所有的假設和問題都是錯誤的。
TL; DR storyboard 已損壞或損壞,當我從其中刪除標簽欄以以編程方式進行制作時。
這里是長版。 在進入這個麻煩之前,我有一個 storyboard 有兩個視圖和一個標簽欄 controller。 它工作得很好。 有一次,我決定在應用程序啟動期間做出選擇,如果缺少默認值,請立即加載設置視圖。 我發現,要做到這一點,我必須將標簽欄向下移動到場景委托並將其從情節提要中刪除。 我做到了,所以 storyboard 顯示給沒有鏈接的視圖,我從場景委托實例化了選項卡欄。
奇怪的是,正在渲染的標簽欄仍然顯示之前在 storyboard 上設置的一些屬性,即使該組件已被刪除。
然后,你就知道問題所在了。 我的推理沒有任何意義。 UITabBarController
不能顯示任何警報。 警報只能在UIViewController上UIViewController
。 因此,繼續嘗試從標簽欄發出警報是沒有意義的。 這種錯誤的理解也導致我進行了錯誤的研究,報告了各種類似的問題(可能具有誤導性)。
我終於做了一個反測試。 使用 storyboard 創建了一個全新的項目。 在 storyboard 上創建了兩個視圖,並在場景委托上定義了一個標簽欄 controller。 它按預期工作。 我將每個視圖鏈接到特定的UIViewController
。 在視圖上創建了一個按鈕,添加了IBAction
並且它起作用了。 然后,我在IBAction
中創建了警報,這一次,工作正常。 我以相同的代碼結束,唯一不同的是我沒有從 storyboard 中創建和刪除標簽欄。
我知道 storyboard 可能會損壞,而且我可能做到了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.