ฉันติดตามกระทู้นี้เพื่อลบล้าง-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
เช่นหรือUITabBarController
UINavigationController
จากนั้นให้แทนที่คอนโทรลเลอร์รูทนี้ดังนี้
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