我正在使用 UITabBarController 處理一個問題。我有一個使用故事板(XCode 13,IOS 15 作為基本系統)的小專案。我創建了一個 TabBarController,但后來發現我無法以編程方式有效地管理它。閱讀各種檔案后,我發現我可以使用故事板中的兩個場景并以編程方式創建標簽欄。所以我在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未設定,直接加載設定。
在我的課堂上,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 而不是我的場景。但在這里我卡住了。我試圖實作UITabBarControllerDelegate, in StarredViewController,但我無法讓它作業。
extension StarredViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
print("did select tab bar item!")
}
}
我開始思考我的主要的設定與SceneDelegate和AppDelegate是錯誤的。我發現的大多數以前的教程或執行緒似乎都無法編譯,因為使用了不推薦使用的版本。
uj5u.com熱心網友回復:
這是一種從任何呈現的視圖控制器呈現警報的方法。
添加一些擴展:
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)
uj5u.com熱心網友回復:
這是觸發警報的代碼。使用 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))
}
您可以在此處找到更多資訊: 如何顯示警報
要訪問根控制器,您可以使用以下代碼:
let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController
uj5u.com熱心網友回復:
我解決了這個問題。實際上,我所有的假設和問題都是錯誤的。
TL; DR 當我從中洗掉標簽欄以編程方式制作時,故事板已損壞或損壞。
這里是長版。在遇到這個麻煩之前,我有一個帶有兩個視圖和一個標簽欄控制器的故事板。它作業得很好。有一次,我決定在應用程式啟動期間做出選擇,如果缺少默認值,立即加載設定視圖。我發現,要做到這一點,我必須將選項卡欄向下移動到場景委托并將其從故事板中洗掉。我做到了,所以故事板向沒有鏈接的視圖顯示,我從場景委托實體化了標簽欄。
奇怪的是,即使該組件已被洗掉,正在渲染的標簽欄仍然顯示先前在故事板上設定的一些屬性。
那么,你就知道問題所在了。我的推理沒有任何意義。將UITabBarController不能顯示任何警報。警報只能顯示在一個UIViewController。因此,繼續嘗試從選項卡欄中發出警報是毫無意義的。這種錯誤的理解也導致我進行了錯誤的研究,報告了各種類似的問題(可能具有誤導性)。
我終于做了一個反測驗。用故事板創建了一個全新的專案。在情節提要上創建了兩個視圖,并在場景委托上定義了一個標簽欄控制器。它按預期作業。我將每個視圖鏈接到一個特定的UIViewController. 在視圖上創建了一個按鈕,添加了IBAction并且它起作用了。然后,我在 中創建了警報IBAction,這次完全正常。我以相同的代碼結束,唯一不同的是我沒有從故事板中創建和洗掉標簽欄。
我知道故事板可能會損壞,而且可能我做到了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/362380.html
