ฉันติดตามกระทู้นี้เพื่อลบล้าง-preferredStatusBarStyleแต่ไม่ได้เรียก มีตัวเลือกใดบ้างที่ฉันสามารถเปลี่ยนเพื่อเปิดใช้งานได้ (ฉันใช้ XIB ในโครงการของฉัน)
ฉันติดตามกระทู้นี้เพื่อลบล้าง-preferredStatusBarStyleแต่ไม่ได้เรียก มีตัวเลือกใดบ้างที่ฉันสามารถเปลี่ยนเพื่อเปิดใช้งานได้ (ฉันใช้ XIB ในโครงการของฉัน)
คำตอบ:
ฉันมีปัญหาเดียวกันและคิดว่ามันเกิดขึ้นเพราะฉันไม่ได้ตั้งค่าตัวควบคุมรูทวิวในหน้าต่างแอปพลิเคชันของฉัน
สิ่งUIViewControllerที่ฉันนำpreferredStatusBarStyleมาใช้นั้นถูกใช้ใน a UITabBarControllerซึ่งควบคุมลักษณะที่ปรากฏของมุมมองบนหน้าจอ
เมื่อฉันตั้งค่าตัวควบคุมรูทมุมมองให้ชี้ไปที่สิ่งนี้UITabBarControllerแถบสถานะเปลี่ยนเริ่มทำงานได้อย่างถูกต้องตามที่คาดไว้ (และเรียกpreferredStatusBarStyleวิธีการ)
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
... // other view controller loading/setup code
self.window.rootViewController = rootTabBarController;
[self.window makeKeyAndVisible];
return YES;
}
หรือคุณสามารถเรียกวิธีการใดวิธีการหนึ่งต่อไปนี้ตามความเหมาะสมในแต่ละตัวควบคุมมุมมองของคุณขึ้นอยู่กับสีพื้นหลังของมันแทนที่จะต้องใช้setNeedsStatusBarAppearanceUpdate:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
หรือ
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
โปรดทราบว่าคุณยังจะต้องตั้งUIViewControllerBasedStatusBarAppearanceไปNOในไฟล์ plist ถ้าคุณใช้วิธีนี้
setNeedsStatusBarAppearanceUpdate- ความสงสัยของฉันได้รับการยืนยันเมื่อฉันทำการเปลี่ยนแปลงนี้
สำหรับทุกคนที่ใช้ UINavigationController:
UINavigationControllerไม่ไปข้างหน้าบนpreferredStatusBarStyleสายไปยังตัวควบคุมมุมมองของเด็ก แต่จะจัดการสถานะของตัวเอง - ตามที่ควรมันจะวาดที่ด้านบนของหน้าจอที่แถบสถานะอยู่และควรรับผิดชอบ ดังนั้นการใช้งานpreferredStatusBarStyleใน VC ของคุณภายในตัวควบคุมการนำทางจะไม่ทำอะไรเลย - จะไม่มีการเรียกใช้
เคล็ดลับคือสิ่งที่UINavigationControllerใช้ในการตัดสินใจว่าจะกลับมาหรือUIStatusBarStyleDefault มันฐานนี้ในตัวของมันUIStatusBarStyleLightContent UINavigationBar.barStyleค่าเริ่มต้น ( UIBarStyleDefault) ส่งผลให้UIStatusBarStyleDefaultแถบสถานะส่วนหน้ามืด และUIBarStyleBlackจะให้UIStatusBarStyleLightContentแถบสถานะ
TL; DR:
หากคุณต้องการUIStatusBarStyleLightContentในUINavigationControllerการใช้งาน:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
preferredStatusBarStyleในความเป็นจริงจะถูกเรียกบนตัวควบคุมมุมมองลูกถ้าคุณซ่อนแถบนำทาง (ตั้งค่าnavigationBarHiddenเป็นYES) ตามความเหมาะสม
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]
navigationBarHiddenพร้อมจะYESจริงจะได้preferredStatusBarStyleเรียกและเตือนให้กับผู้ที่อาจจะสะดุดกับเรื่องนี้: มันทำงานร่วมกับnavigationBarHiddenแต่ไม่ได้มีnavigationBar.hidden!
ดังนั้นฉันจริงเพิ่มหมวดหมู่เพื่อ UINavigationController แต่ใช้วิธีการ:
-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;
และส่งคืน UIViewController ที่มองเห็นในปัจจุบัน ที่ช่วยให้ตัวควบคุมมุมมองที่มองเห็นในปัจจุบันตั้งค่าสไตล์ / ทัศนวิสัยที่ต้องการได้
นี่เป็นข้อมูลโค้ดที่สมบูรณ์สำหรับมัน:
ในสวิฟต์:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
ในวัตถุประสงค์ -C:
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
และสำหรับการวัดที่ดีนี่คือวิธีการใช้งานใน UIViewController:
ในสวิฟท์
override public func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
override func prefersStatusBarHidden() -> Bool {
return false
}
ในวัตถุประสงค์ -C
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // your own style
}
- (BOOL)prefersStatusBarHidden {
return NO; // your own visibility code
}
สุดท้ายให้แน่ใจว่า plist ของแอปไม่ไม่ได้ "ดูตัวควบคุมตามแถบสถานะลักษณะ" ชุดที่จะไม่มี อาจลบบรรทัดนั้นหรือตั้งค่าเป็นใช่ (ซึ่งฉันเชื่อว่าเป็นค่าเริ่มต้นสำหรับ iOS 7 ตอนนี้)
return self.topViewController;งานสำหรับฉัน แต่return self.visibleViewController;- ไม่ใช่
superในวิธีนี้และคุณต้องการเปลี่ยนพฤติกรรมของคอนโทรลเลอร์ทั้งหมดประเภทนี้
สำหรับทุกคนที่ยังคงดิ้นรนอยู่กับสิ่งนี้ส่วนขยายที่ง่ายและรวดเร็วนี้ควรแก้ไขปัญหาให้คุณ
extension UINavigationController {
override open var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
app ของฉันใช้ทั้งสาม: UINavigationController, UISplitViewController, UITabBarControllerจึงทั้งหมดเหล่านี้ดูเหมือนจะใช้ควบคุมแถบสถานะและจะทำให้preferedStatusBarStyleไม่ได้รับการเรียกร้องให้เด็กของพวกเขา ในการลบล้างพฤติกรรมนี้คุณสามารถสร้างส่วนขยายได้เหมือนกับคำตอบที่เหลือ นี่คือส่วนขยายสำหรับทั้งสามใน Swift 4 หวังว่า Apple จะมีความชัดเจนมากขึ้นเกี่ยวกับเนื้อหาประเภทนี้
extension UINavigationController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
extension UISplitViewController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
แก้ไข: อัปเดตสำหรับการเปลี่ยนแปลง Swift 4.2 API
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
extension UISplitViewController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
ไทสันUINavigationControllerคำตอบคือถูกต้องสำหรับการเปลี่ยนสีแถบสถานะในสีขาว
หากใครต้องการที่จะบรรลุผลเดียวกันโดยการเขียนรหัสAppDelegateจากนั้นใช้รหัสด้านล่างและเขียนมันภายในAppDelegate's didFinishLaunchingWithOptionsวิธี
และไม่ลืมที่จะตั้งค่าUIViewControllerBasedStatusBarAppearanceไปYESในแฟ้ม .plist อื่นเปลี่ยนแปลงจะไม่ได้สะท้อนให้เห็นถึง
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// status bar appearance code
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
return YES;
}
เมื่อวันที่ UINavigationController ที่preferredStatusBarStyleไม่ได้เรียกว่าเพราะเป็นที่ต้องการtopViewController selfดังนั้นเพื่อให้ได้รับการpreferredStatusBarStyleเรียกว่าใน UINavigationController childViewControllerForStatusBarStyleคุณจำเป็นต้องเปลี่ยนมัน
แทนที่ UINavigationController ของคุณในคลาสของคุณ:
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
หากต้องการทำเพื่อ UINavigationController ทั้งหมดคุณสามารถแทนที่ในส่วนขยาย (คำเตือน: มีผลกับ UIDocumentPickerViewController, UIImagePickerController ฯลฯ ) แต่คุณไม่ควรทำตามเอกสารของ Swift :
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
open override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
นอกเหนือจากคำตอบของ Serenn หากคุณแสดงตัวควบคุมมุมมองด้วยmodalPresentationStyle(ตัวอย่าง.overCurrentContext) คุณควรเรียกสิ่งนี้ในตัวควบคุมมุมมองที่นำเสนอใหม่:
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
อย่าลืมที่จะแทนที่preferredStatusBarStyleในตัวควบคุมมุมมองที่นำเสนอ
นอกเหนือจากคำตอบของฮิปโป: ถ้าคุณใช้ UINavigationController มันอาจจะเป็นการดีกว่าถ้าคุณเพิ่มหมวดหมู่:
// UINavigationController+StatusBarStyle.h:
@interface UINavigationController (StatusBarStyle)
@end
// UINavigationController+StatusBarStyle.m:
@implementation UINavigationController (StatusBarStyle)
- (UIStatusBarStyle)preferredStatusBarStyle
{
//also you may add any fancy condition-based code here
return UIStatusBarStyleLightContent;
}
@end
ทางออกนั้นน่าจะดีกว่าการเปลี่ยนไปใช้พฤติกรรมที่เลิกใช้เร็ว ๆ นี้
preferredStatusBarStyleและใช้ตรรกะเฉพาะของ UINavigationController ตอนนี้ตรรกะนี้ขึ้นอยู่กับnavigationBar.barStyleแต่ฉันสามารถดูการตรวจสอบเพิ่มเติมที่เพิ่มเข้ามา (เช่นการUISearchDisplayControllerย้ายเพื่อซ่อนโหมด navbar) ด้วยการแทนที่ตรรกะเริ่มต้นคุณจะไม่สามารถใช้งานฟังก์ชั่นทั้งหมดนี้และปล่อยให้ตัวเองเปิดสำหรับช่วงเวลาที่น่ารำคาญในอนาคต ดูคำตอบของฉันด้านบนสำหรับวิธีที่ถูกต้องในการทำเช่นนี้ในขณะที่ยังสนับสนุนพฤติกรรมของตัวควบคุม nav ในตัว
ดังที่กล่าวไว้ในคำตอบที่เลือกสาเหตุที่แท้จริงคือการตรวจสอบวัตถุตัวควบคุมมุมมองหน้าต่างของคุณ
childForStatusBarStyle ใช้ส่วนขยายต่อไปนี้มันจัดการสถานการณ์ข้างต้นทั้งหมด -
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return selectedViewController?.childForStatusBarStyle ?? selectedViewController
}
}
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return topViewController?.childForStatusBarStyle ?? topViewController
}
}
extension AppRootViewController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return children.first { $0.childForStatusBarStyle != nil }?.childForStatusBarStyle?.preferredStatusBarStyle ?? .default
}
}
UIViewControllerBasedStatusBarAppearanceรหัสinfo.plistตามจริงโดยค่าเริ่มต้นในกรณีที่คุณแสดงโฟลว์ใหม่แบบค่อยเป็นค่อยไปมันจะแยกออกจากโฟลว์ลักษณะแถบสถานะที่มีอยู่ ดังนั้นสมมติว่าคุณกำลังนำเสนอNewFlowUIViewControllerและจากนั้นเพิ่มการนำทางใหม่หรือตัวควบคุม tabBarNewFlowUIViewControllerจากนั้นเพิ่มส่วนขยายNewFlowUIViewControllerเช่นกันเพื่อจัดการลักษณะแถบสถานะของตัวควบคุมเพิ่มเติม
ในกรณีที่คุณตั้งmodalPresentationStyleนอกเหนือจากfullScreenการนำเสนอ modally คุณต้องตั้งค่าmodalPresentationCapturesStatusBarAppearanceเป็นจริงเพื่อให้ตัวควบคุมมุมมองที่นำเสนอต้องได้รับการควบคุมลักษณะที่ปรากฏของแถบสถานะ
UINavigationController เป็นคลาสย่อยของ UIViewController (ใครจะรู้🙃)!
ดังนั้นเมื่อแสดงตัวควบคุมมุมมองที่ฝังอยู่ในตัวควบคุมทิศทางคุณไม่ได้นำเสนอตัวควบคุมมุมมองที่ฝังอยู่จริงๆ คุณกำลังนำเสนอตัวควบคุมการนำทาง! UINavigationControllerเป็นคลาสย่อยของUIViewControllerสืบทอดpreferredStatusBarStyleและchildForStatusBarStyleคุณสามารถตั้งค่าได้ตามต้องการ
วิธีใดวิธีหนึ่งต่อไปนี้ควรใช้งานได้:
info.plistเพิ่มคุณสมบัติต่อไปนี้:
UIUserInterfaceStyle(aka. "รูปแบบส่วนต่อประสานผู้ใช้")แทนที่preferredStatusBarStyleภายในUINavigationController
preferredStatusBarStyle( doc ) - สไตล์แถบสถานะที่ต้องการสำหรับคอนโทรลเลอร์มุมมองซับคลาสหรือขยาย UINavigationController
class MyNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
.lightContent
}
}
หรือ
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
.lightContent
}
}แทนที่childForStatusBarStyleภายในUINavigationController
childForStatusBarStyle( doc ) - เรียกใช้เมื่อระบบต้องการตัวควบคุมมุมมองเพื่อใช้ในการกำหนดรูปแบบแถบสถานะ"ถ้าตัวควบคุมมุมมองคอนเทนเนอร์ของคุณได้รับลักษณะแถบสถานะจากหนึ่งในตัวควบคุมมุมมองลูกของมัน, [แทนที่คุณสมบัตินี้] และส่งกลับตัวควบคุมมุมมองลูกนั้นถ้าคุณกลับศูนย์หรือไม่แทนที่วิธีนี้สไตล์แถบสถานะสำหรับตนเอง หากค่าส่งคืนจากเมธอดนี้เปลี่ยนแปลงให้เรียกเมธอด setNeedsStatusBarAppearanceUpdate ()
ซับคลาสหรือขยาย UINavigationController
class MyNavigationController: UINavigationController {
override var childForStatusBarStyle: UIViewController? {
topViewController
}
}
หรือ
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
topViewController
}
}คุณสามารถส่งคืนตัวควบคุมมุมมองใด ๆ ที่คุณต้องการด้านบน ฉันขอแนะนำอย่างใดอย่างหนึ่งต่อไปนี้:
topViewController(จากUINavigationController) ( doc ) - ตัวควบคุมมุมมองที่ด้านบนสุดของการนำทางสแต็กvisibleViewController(จากUINavigationController) ( doc ) - ตัวควบคุมมุมมองที่เกี่ยวข้องกับมุมมองที่มองเห็นได้ในปัจจุบันในส่วนต่อประสานการนำทาง (คำแนะนำ: สิ่งนี้อาจรวมถึง "ตัวควบคุมมุมมองที่นำเสนอแบบ Modally ด้านบนของตัวควบคุมทิศทาง")หมายเหตุ: หากคุณตัดสินใจที่จะคลาสย่อย UINavigationControllerอย่าลืมใช้คลาสนั้นกับตัวควบคุม nav ของคุณผ่านตัวตรวจสอบตัวตนใน IB
PS รหัสของฉันใช้ไวยากรณ์ของ Swift 5.1
คำตอบของ @ serenn ข้างต้นยังคงเป็นคำตอบที่ยอดเยี่ยมสำหรับกรณีของ UINavigationControllers อย่างไรก็ตามสำหรับรวดเร็ว 3 ฟังก์ชั่น childViewController varsจะถูกเปลี่ยนให้ ดังนั้นUINavigationControllerรหัสส่วนขยายควรเป็น:
override open var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
override open var childViewControllerForStatusBarHidden: UIViewController? {
return topViewController
}
และจากนั้นในตัวควบคุมมุมมองที่ควรกำหนดรูปแบบแถบสถานะ:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
หาก viewController ของคุณอยู่ภายใต้ UINavigationController
คลาสย่อย UINavigationController และเพิ่ม
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
preferredStatusBarStyleจะเรียกViewController
UIStatusBarStyle ใน iOS 7
แถบสถานะใน iOS 7 นั้นโปร่งใสมองเห็นด้านหลัง
รูปแบบของแถบสถานะอ้างถึงลักษณะที่ปรากฏของเนื้อหา ใน iOS 7 เนื้อหาแถบสถานะจะมืด ( UIStatusBarStyleDefault) หรือเบา ( UIStatusBarStyleLightContent) ทั้งสองUIStatusBarStyleBlackTranslucentและUIStatusBarStyleBlackOpaqueเลิกใช้แล้วใน iOS 7.0 ใช้UIStatusBarStyleLightContentแทน
วิธีการเปลี่ยน UIStatusBarStyle
หากด้านล่างแถบสถานะเป็นแถบนำทางสไตล์ของแถบสถานะจะถูกปรับให้ตรงกับสไตล์ของแถบนำทาง ( UINavigationBar.barStyle):
โดยเฉพาะถ้าสไตล์แถบนำทางเป็น UIBarStyleDefault สไตล์แถบสถานะจะUIStatusBarStyleDefault; หากรูปแบบแถบนำทางคือUIBarStyleBlackรูปแบบแถบสถานะจะเป็นUIStatusBarStyleLightContentสไตล์แถบสถานะจะเป็น
หากไม่มีแถบนำทางใต้แถบสถานะคุณสามารถควบคุมและเปลี่ยนลักษณะของแถบสถานะได้โดยตัวควบคุมมุมมองแต่ละรายการในขณะที่แอปทำงาน
- [UIViewController preferredStatusBarStyle]เป็นวิธีการใหม่ที่เพิ่มเข้ามาใน iOS 7 มันสามารถถูกแทนที่เพื่อส่งคืนสไตล์แถบสถานะที่ต้องการ:
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
หากสไตล์แถบสถานะควรถูกควบคุมโดยตัวควบคุมมุมมองลูกแทนที่จะเป็นตัวเองให้แทนที่ -[UIViewController childViewControllerForStatusBarStyle]เพื่อกลับไปที่ตัวควบคุมมุมมองที่เด็ก
หากคุณต้องการเลิกใช้ลักษณะการทำงานนี้และตั้งค่าสไตล์ของแถบสถานะโดยใช้-[UIApplication statusBarStyle]วิธีการให้เพิ่มUIViewControllerBasedStatusBarAppearanceรหัสลงในInfo.plistไฟล์ของแอพและระบุค่า NO
หากใครก็ตามกำลังใช้ Navigation Controller และต้องการให้ตัวควบคุมการนำทางทั้งหมดมีสไตล์สีดำคุณสามารถเขียนส่วนขยายไปยัง UINavigationController เช่นนี้ใน Swift 3 และจะใช้กับตัวควบคุมทิศทางทั้งหมด (แทนที่จะกำหนดให้กับคอนโทรลเลอร์หนึ่งตัวที่ เวลา).
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barStyle = UIBarStyle.black
}
}
ใน Swift สำหรับ UIViewController ชนิดใดก็ได้:
ในAppDelegateชุดของคุณ:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window!.rootViewController = myRootController
return true
}
myRootControllerสามารถชนิดใดUIViewControllerเช่นหรือUITabBarControllerUINavigationController
จากนั้นให้แทนที่คอนโทรลเลอร์รูทนี้ดังนี้
class RootController: UIViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
สิ่งนี้จะเปลี่ยนลักษณะที่ปรากฏของแถบสถานะในแอปทั้งหมดของคุณเนื่องจากตัวควบคุมรูทเป็นผู้รับผิดชอบ แต่เพียงผู้เดียวสำหรับลักษณะที่ปรากฏของแถบสถานะ
อย่าลืมตั้งค่าคุณสมบัติView controller-based status bar appearanceเป็น YES ของคุณInfo.plistเพื่อทำงานนี้ (ซึ่งเป็นค่าเริ่มต้น)
โซลูชัน Swift 3 iOS 10:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
คำตอบส่วนใหญ่ไม่รวมถึงการใช้childViewControllerForStatusBarStyleวิธีการที่UINavigationControllerดี จากประสบการณ์ของฉันคุณควรจัดการกับกรณีเช่นเมื่อมีการนำเสนอตัวควบคุมมุมมองแบบโปร่งใสบนตัวควบคุมการนำทาง ในกรณีเหล่านี้คุณควรผ่านการควบคุมไปยังตัวควบคุม modal ( visibleViewController) แต่ไม่ใช่เมื่อมันหายไป
override var childViewControllerForStatusBarStyle: UIViewController? {
var childViewController = visibleViewController
if let controller = childViewController, controller.isBeingDismissed {
childViewController = topViewController
}
return childViewController?.childViewControllerForStatusBarStyle ?? childViewController
}
ในกรณีของฉันฉันได้นำเสนอ View / Navigation Controller โดยไม่ตั้งใจUIModalPresentationStyle.overFullScreenซึ่งทำให้preferredStatusBarStyleไม่ถูกเรียก หลังจากเปลี่ยนกลับเป็นUIModalPresentationStyle.fullScreenทุกอย่างทำงานได้
ในฐานะที่เป็น iOS 13.4 preferredStatusBarStyleวิธีการในUINavigationControllerจะไม่เรียกหมวดหมู่การใช้คำสั่ง swizzling นั้นเป็นตัวเลือกเดียวโดยไม่จำเป็นต้องใช้คลาสย่อย
ตัวอย่าง:
ส่วนหัวของหมวดหมู่:
@interface UINavigationController (StatusBarStyle)
+ (void)setUseLightStatusBarStyle;
@end
การดำเนินงาน:
#import "UINavigationController+StatusBarStyle.h"
#import <objc/runtime.h>
@implementation UINavigationController (StatusBarStyle)
void (^swizzle)(Class, SEL, SEL) = ^(Class c, SEL orig, SEL new){
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
};
+ (void)setUseLightStatusBarStyle {
swizzle(self.class, @selector(preferredStatusBarStyle), @selector(_light_preferredStatusBarStyle));
}
- (UIStatusBarStyle)_light_preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
@end
การใช้งานใน AppDelegate.h:
#import "UINavigationController+StatusBarStyle.h"
[UINavigationController setUseLightStatusBarStyle];
นี่คือวิธีของฉันสำหรับการแก้ปัญหานี้
กำหนดโปรโตคอลที่เรียกว่าAGViewControllerAppearance AGViewControllerAppearance
AGViewControllerAppearance.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
กำหนดหมวดหมู่บนUIViewControllerชื่อUpgradeอัพเกรด
UIViewController + Upgrade.h
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
UIViewController + Upgrade.m
#import "UIViewController+Upgrade.h"
#import <objc/runtime.h>
#import "AGViewControllerAppearance.h" // This is the appearance protocol
@implementation UIViewController (Upgrade)
+ (void)load
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wselector"
Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
#pragma clang diagnostic pop
Method upgradedViewWillAppear = class_getInstanceMethod(self, @selector(upgradedViewWillAppear:));
method_exchangeImplementations(viewWillAppear, upgradedViewWillAppear);
}
#pragma mark - Implementation
- (void)upgradedViewWillAppear:(BOOL)animated
{
//
// Call the original message (it may be a little confusing that we're
// calling the 'same' method, but we're actually calling the original one :) )
//
[self upgradedViewWillAppear:animated];
//
// Implementation
//
if ([self conformsToProtocol:@protocol(AGViewControllerAppearance)])
{
UIViewController <AGViewControllerAppearance> *viewControllerConformingToAppearance =
(UIViewController <AGViewControllerAppearance> *)self;
//
// Status bar
//
if ([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)])
{
BOOL shouldAnimate = YES;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(animatesStatusBarVisibility)])
{
shouldAnimate = [viewControllerConformingToAppearance animatesStatusBarVisibility];
}
[[UIApplication sharedApplication] setStatusBarStyle:[viewControllerConformingToAppearance preferredStatusBarStyle]
animated:shouldAnimate];
}
if ([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)])
{
UIStatusBarAnimation animation = UIStatusBarAnimationSlide;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(prefferedStatusBarAnimation)])
{
animation = [viewControllerConformingToAppearance prefferedStatusBarAnimation];
}
[[UIApplication sharedApplication] setStatusBarHidden:(! [viewControllerConformingToAppearance showsStatusBar])
withAnimation:animation];
}
}
}
@end
ตอนนี้ได้เวลาบอกว่าคุณกำลังดูคอนโทรลเลอร์กำลังใช้งานAGViewControllerAppearanceโปรโตคอล
ตัวอย่าง:
@interface XYSampleViewController () <AGViewControllerAppearance>
... the rest of the interface
@end
แน่นอนคุณสามารถใช้ส่วนที่เหลือของวิธีการ ( showsStatusBar , animatesStatusBarVisibility , prefferedStatusBarAnimation ) จากโปรโตคอลและUIViewController + Upgradeจะทำการปรับแต่งที่เหมาะสมตามค่าที่ให้ไว้
หากมีคนพบปัญหานี้กับ UISearchController เพียงสร้างคลาสย่อยใหม่ของ UISearchController แล้วเพิ่มรหัสด้านล่างลงในคลาสนั้น:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
โปรดทราบว่าเมื่อใช้ self.navigationController.navigationBar.barStyle = UIBarStyleBlack;โซลูชัน
อย่าลืมไปที่ plist ของคุณและตั้งค่า "ดูแถบสถานะตามตัวควบคุม" เป็น YES ถ้าไม่ใช่มันจะไม่ทำงาน
ตั้งแต่ Xcode 11.4, การเอาชนะ preferredStatusBarStyleคุณสมบัติในส่วนขยาย UINavigationController จะไม่ทำงานอีกต่อไปเนื่องจากจะไม่ถูกเรียกใช้
การตั้งค่าbarStyleของnavigationBarเป็น.blackทำงานได้จริง แต่สิ่งนี้จะเพิ่มผลข้างเคียงที่ไม่พึงประสงค์หากคุณเพิ่ม subviews ไปที่แถบนำทางซึ่งอาจมีลักษณะที่แตกต่างกันสำหรับโหมดแสงและสีเข้ม เนื่องจากการตั้งค่าเป็นbarStyleสีดำuserInterfaceStyleมุมมองที่ฝังอยู่ในแถบนำทางจะมีอยู่เสมอuserInterfaceStyle.darkโดยไม่คำนึงถึงuserInterfaceStyleแอพ
ทางออกที่เหมาะสมที่ฉันเกิดขึ้นคือการเพิ่มคลาสย่อยUINavigationControllerและแทนที่ที่preferredStatusBarStyleนั่น หากคุณใช้ UINavigationController ที่กำหนดเองนี้สำหรับมุมมองทั้งหมดของคุณคุณจะอยู่ในด้านการบันทึก
NavigationController หรือ TabBarController เป็นสิ่งที่ต้องการจัดเตรียมสไตล์ นี่คือวิธีที่ฉันแก้ไข: https://stackoverflow.com/a/39072526/242769