preferredStatusBarStyle이 호출되지 않았습니다.


257

나는 다음에 이 스레드 오버라이드 (override)를 -preferredStatusBarStyle있지만 호출되지 않습니다. 활성화하기 위해 변경할 수있는 옵션이 있습니까? (프로젝트에서 XIB를 사용하고 있습니다.)


어떤 상황에서 호출되지 않습니다 : 시뮬레이터? 기기에서?
bneely

@bneely 둘 다.
trgoofi

iOS 7 시뮬레이터, iOS 7 기기를 사용하고 있고 기본 SDK가 7.0입니까?
bneely

@bneely iOS SDK 7.0이 프로젝트 이름 아래에 표시됩니다. 기본 SDK가 7.0이라는 의미입니까?
trgoofi

빌드 설정에서 "Base SDK"는 값이 설정되는 위치입니다. 프로젝트가 7.0으로 설정된 것처럼 들립니다.
무릎을 꿇고

답변:


117

가능한 근본 원인

나는 같은 문제가 있었고 응용 프로그램 창에서 루트보기 컨트롤러를 설정하지 않았기 때문에 문제가 발생했다는 것을 알았습니다.

UIViewController내가 구현했다있는이 preferredStatusBarStyleA의 사용 UITabBarController화면에 표시되는 뷰의 모양을 제어하는.

루트보기 컨트롤러가 this를 가리 키도록 설정하면 UITabBarController상태 표시 줄 변경이 예상대로 올바르게 작동하기 시작했습니다 ( preferredStatusBarStyle메소드가 호출되었습니다).

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ... // other view controller loading/setup code

    self.window.rootViewController = rootTabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}

대체 방법 (iOS 9에서 더 이상 사용되지 않음)

또는 사용하지 않고 배경색에 따라 각 뷰 컨트롤러에서 다음 방법 중 하나를 적절하게 호출 할 수 있습니다 setNeedsStatusBarAppearanceUpdate.

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

또는

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];

당신은 또한 설정해야합니다 것을 참고 UIViewControllerBasedStatusBarAppearanceNO이 방법을 사용하는 경우 PLIST 파일에.


2
루트보기 컨트롤러를 설정하지 않고 당신과 같은 문제가 있습니다. 도대체 어떻게 찾았 어?
trgoofi

1
나는 프레임 워크의 어떤 것이 알림을받지 못하고 있다고 의심했다 setNeedsStatusBarAppearanceUpdate.이 변경을했을 때 내 의심이 확인되었다.
AbdullahC

2
앱에서 발견 한 관련 문제는 childViewControllerForStatusBarStyle 및 childViewControllerForStatusBarHidden을 재정의하지 않고 전체 화면 하위보기 컨트롤러가있는보기 컨트롤러였습니다. 고유 한 뷰 컨트롤러 계층이있는 경우 상태 표시 줄 스타일을 결정하는 데 사용할 뷰 컨트롤러를 시스템에 알리려면 이러한 방법을 제공해야합니다.
Jon Steinmetz

rootviewcontroller를 설정해도 아무런 변화가 없습니다. Jon의 의견을 다루어야합니다. setneedsstatusbarappearanceUpdate를 호출 할 때주의하십시오. 부모님에게 전화해서 일해야합니다.
doozMen

1
@Hippo 당신은 천재입니다! rootviewcontroller를 설정하지 않았기 때문에 어떻게 찾았습니까?
ViruMax

1019

UINavigationController를 사용하는 사람 :

UINavigationController에 전달하지 않는 preferredStatusBarStyle자식보기 컨트롤러 호출. 대신 자체 상태를 관리합니다. 상태 표시 줄이있는 화면의 맨 위에 표시되므로 책임을 져야합니다. 따라서 preferredStatusBarStyle내비게이션 컨트롤러 내에서 VC를 구현할 때는 아무 것도하지 않으며 호출되지 않습니다.

트릭은 또는에 UINavigationController대해 무엇을 반환할지 결정 하는 데 사용됩니다 . 이것에 기초합니다 . 기본값 ( )은 어두운 전경 상태 표시 줄이됩니다. 그리고 상태 표시 줄 을 제공 합니다.UIStatusBarStyleDefaultUIStatusBarStyleLightContentUINavigationBar.barStyleUIBarStyleDefaultUIStatusBarStyleDefaultUIBarStyleBlackUIStatusBarStyleLightContent

TL; DR :

당신이 원하는 경우, UIStatusBarStyleLightContentA의 UINavigationController사용 :

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;

59
좋은! 참고 preferredStatusBarStyle당신은 (설정 탐색 모음 숨길 경우 사실 의지가 아이 뷰 컨트롤러에 호출되는 navigationBarHidden에를 YES) 정확히 적절하게.
Patrick Pijnappel

25
이 답변에 감사드립니다. 모든 네비게이션 바에 대해 barStyle을 설정하려면[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]
Thomas Desert

15
완벽한 답변. SO에 대한 다른 답변은 UINavigationController를 고려하지 않았습니다. 키보드에 머리를 두드리는 2 시간.
Ryan Alford

10
그 나타내는 @Patrick 했네 navigationBarHidden세트합니다 YES실제로 것 preferredStatusBarStyle이라고,이에 비틀 수있는 것들에 대한 경고 :이 작동 navigationBarHidden하지만,하지와 navigationBar.hidden!
jcaron

4
이 작업을 수행하려면 Info.plist에서 "컨트롤러 기반 상태 표시 줄보기"가 YES로 설정되어 있어야합니다.
Code Baller

99

그래서 실제로 UINavigationController에 카테고리를 추가했지만 메소드를 사용했습니다.

-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;

그리고 현재 보이는 UIViewController를 반환하도록했습니다. 이를 통해 현재 보이는 뷰 컨트롤러가 선호하는 스타일 / 가시성을 설정할 수 있습니다.

여기에 대한 전체 코드 스 니펫이 있습니다.

스위프트에서 :

extension UINavigationController {

    public override func childViewControllerForStatusBarHidden() -> UIViewController? {
        return self.topViewController
    }

    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return self.topViewController
    }
}

Objective-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
}

Objective-C에서

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent; // your own style
}

- (BOOL)prefersStatusBarHidden {
    return NO; // your own visibility code
}

마지막으로, 확인하십시오 앱을 plist는 않습니다 NOT NO에 "보기 컨트롤러 기반 상태 표시 줄 모양"세트가 있습니다. 해당 줄을 삭제하거나 YES로 설정하십시오 (iOS 7의 현재 기본값이라고 생각합니까?)


return self.topViewController;나를 위해 작동하는 것처럼 보이지만 return self.visibleViewController;– 아닙니다
k06a

visibleViewController는 현재 표시된 모달 컨트롤러를 닫을 때 반환 할 수 있습니다. 부머입니다. topViewController를 사용하십시오.
벤 싱클레어

1
@ d.lebedev는 괜찮지 만 여기에 해당되는 문제는 없다고 생각합니다. 당신은 호출 할 필요는 없습니다 super이 방법 당신은 실제로이 유형의 모든 컨트롤러의 동작을 변경 하시겠습니까
에디션 '

1
이것은 iOS 9.3에서 작동하지 않습니다. 나는 이것이 문제
vikingosegundo

2
이것은 잘못되어 iOS 13.4에서 중단됩니다. Swift에서 객관적인 C 클래스를 확장하는 것은 객관적인 C 범주를 통해 구현되기 때문입니다. Objective C 범주를 통한 메소드 재정의는 권장되지 않으며 중단 될 수 있습니다. 참조 stackoverflow.com/a/38274660/2438634
마크 Etcheverry

79

여전히이 문제로 어려움을 겪고있는 사람들에게는이 간단한 확장 기능이 문제를 해결해야합니다.

extension UINavigationController {
    override open var childForStatusBarStyle: UIViewController? {
        return self.topViewController
    }
}

10
당신은 메달을받을 자격이 있습니다.
nikans

2
대단히 감사합니다. 성공하지 않고 visibleViewController를 대신 반환했습니다.
Fábio Salata

1
이것은 금입니다. 탭 표시 줄에 내비게이션 컨트롤러가 포함되어 있으며 파일에 방금 던졌습니다. 이제 원하는 위치에서 상태 표시 줄 모양을 변경할 수 있습니다.
Vahid Amiri

2
이것은 잘못되어 iOS 13.4에서 중단됩니다. Swift에서 객관적인 C 클래스를 확장하는 것은 객관적인 C 범주를 통해 구현되기 때문입니다. Objective C 범주를 통한 메소드 재정의는 권장되지 않으며 중단 될 수 있습니다. 참조 stackoverflow.com/a/38274660/2438634
마크 Etcheverry

1
@MarcEtcheverry이 특정 인스턴스는 틀리지 않았습니다. 문제는 UINavigationController와 같은 다른 객체 / 프로토콜의 서브 클래스가 동적 디스패치에서 충돌 할 사전 구현이 없었기 때문입니다. 실제 서브 클래스 내에 기본값이나 구현이 없었기 때문에 이것이 불필요한 의존성을 생성하지 않고 앱 전체에서이를 구현하는 가장 깨끗한 방법 인 이유입니다. 불행히도 13.4는이 동작을 변경 한 것으로 보입니다. 나는 그들이 수년간 존재하지 않았던 점검 또는 구현을 지금 막 뒤에서 추측하고 있습니다 .........
TheCodingArt

20

내 응용 프로그램은 세 가지 사용 : UINavigationController, UISplitViewController, UITabBarController,, 따라서 이러한 모든 상태 표시 줄을 통해 제어 할 것 같고 원인이됩니다 preferedStatusBarStyle자신의 아이들을 위해 호출 할 수 없습니다 수 있습니다. 이 동작을 무시하려면 나머지 답변에서 언급 한 것처럼 확장을 만들 수 있습니다. 다음은 Swift 4의 세 가지 기능 모두에 대한 확장 기능입니다.

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
    }
}

1
이것이 작동하는 유일한 솔루션입니다. SO에 대한 모든 답변은 NavigationController가있는 응용 프로그램에서는 작동하지 않는 표준 솔루션을 가리 킵니다. 감사합니다!!!
Houman

재정의에 확장을 사용하는 것은 잘못입니다. 안전하지 않습니다. 더 간단한 여러 가지 솔루션이 있습니다. 대신 서브 클래스를 사용하십시오.
술탄

2
이것은 잘못되어 iOS 13.4에서 중단됩니다. Swift에서 객관적인 C 클래스를 확장하는 것은 객관적인 C 범주를 통해 구현되기 때문입니다. Objective C 범주를 통한 메소드 재정의는 권장되지 않으며 중단 될 수 있습니다. 참조 stackoverflow.com/a/38274660/2438634
마크 Etcheverry

1
@MarcEtcheverry이 특정 인스턴스는 틀리지 않았습니다. 문제는 UINavigationController와 같은 다른 객체 / 프로토콜의 서브 클래스가 동적 디스패치에서 충돌 할 사전 구현이 없었기 때문입니다. 실제 서브 클래스 내에 기본값이나 구현이 없었기 때문에 이것이 불필요한 의존성을 생성하지 않고 앱 전체에서이를 구현하는 가장 깨끗한 방법 인 이유입니다. 불행히도 13.4는이 동작을 변경 한 것으로 보입니다. 나는 그들이 수년간 존재하지 않았던 점검 또는 구현을 지금 막 뒤에서 추측하고 있습니다 .........
TheCodingArt

15

Tyson의 답변은에서 상태 표시 줄 색상을 흰색으로 변경하기에 적합 UINavigationController합니다.

누구나 코드를 작성하여 동일한 결과를 얻으려면 AppDelegate아래 코드를 사용하고 AppDelegate's didFinishLaunchingWithOptions메소드 안에 작성하십시오 .

그리고 .plist 파일에서 를 설정하는 UIViewControllerBasedStatusBarAppearance것을 잊지 마십시오 YES. 그렇지 않으면 변경 사항이 반영되지 않습니다.

암호

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // status bar appearance code
     [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];

     return YES;
}

14

UINavigationController에서이 ( preferredStatusBarStyletopViewController) 선호 되므로 호출되지 않습니다 self. 따라서 preferredStatusBarStyleUINavigationController에서 호출하려면을 변경해야합니다 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
    }
}

11

당신이보기 컨트롤러를 제시하는 경우 serenn의 대답 또한, modalPresentationStyle(예를 들어 .overCurrentContext), 당신은 또한 새로 발표 뷰 컨트롤러에이를 호출해야합니다 :

presentedViewController.modalPresentationCapturesStatusBarAppearance = true

preferredStatusBarStyle제시된 뷰 컨트롤러에서를 재정의하는 것을 잊지 마십시오 .


9

Hippo의 답변에 추가 : 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

이 솔루션은 곧 사용되지 않을 예정인 행동으로 전환하는 것보다 낫습니다.


이 작업을 수행하지 마십시오. 현재는 작동하지만 향후 동작이 중단 될 수 있습니다. navBar 스타일을 변경하기 만하면됩니다-내 답변을보십시오 stackoverflow.com/a/19513714/505457
Tyson

2
카테고리가 아닌 서브 클래스를 사용해야합니다.
shuiyouren

2 타이슨 : 미래의 행동을 어기는 이유는 무엇입니까? preferredStatusBarStyle : 상태 표시 줄 스타일을 설정하기 위해 Apple이 선호하는 방법입니다.
Artem Abramov

2shuiyouren : 카테고리를 사용하고 원하는 모든 장소에 카테고리를 포함시킬 수 있다면 서브 클래 싱으로 복잡성을 증가시켜야하는 이유는 무엇입니까? 어쨌든, 그것은 구현이 아니라 아키텍처의 문제입니다.
Artem Abramov

2
@ArtemAbramov UINavigationController는 이미 preferredStatusBarStyleUINavigationController 특정 로직을 구현 하고 수행하기 때문입니다. 현재이 논리는 기본 navigationBar.barStyle이지만 추가 검사가 추가되는 것을 볼 수 있습니다 (예 : UISearchDisplayController탐색 표시 줄 모드 숨기기로 이동). 기본 로직을 재정의함으로써이 모든 기능을 잃어 버리고 장래에 성가신 'wtf'순간을 위해 자신을 열어 둡니다. 내장 내비게이션 컨트롤러 동작을 계속 지원하면서이를 수행하는 올바른 방법은 위의 답변을 참조하십시오.
타이슨

9

스위프트 4.2 이상

선택된 답변 에서 언급했듯이 근본 원인은 창 루트보기 컨트롤러 객체를 확인하는 것입니다.

흐름 구조의 가능한 경우

  • 사용자 지정 UIViewController 개체는 창 루트 뷰 컨트롤러입니다.

    창 루트보기 컨트롤러는 UIViewController 개체이며 응용 프로그램 흐름에 따라 탐색 컨트롤러 또는 tabController를 추가하거나 제거합니다.

    이러한 유형의 흐름은 일반적으로 앱에 탭이없는 탐색 스택에 사전 로그인 흐름이 있고 탭이있는 로그인 후 흐름이 있고 모든 탭에 탐색 컨트롤러가 더있는 경우에 사용됩니다.

  • TabBarController 객체는 윈도우 루트 뷰 컨트롤러입니다.

    이것은 윈도우 루트 뷰 컨트롤러가 tabBarController 인 흐름입니다.

  • NavigationController 객체는 윈도우 루트 뷰 컨트롤러입니다.

    이것은 윈도우 루트 뷰 컨트롤러가 navigationController 인 흐름입니다.

    기존 탐색 컨트롤러에 탭 표시 줄 컨트롤러 또는 새 탐색 컨트롤러를 추가 할 가능성이 있는지 확실하지 않습니다. 그러나 이러한 경우 상태 표시 줄 스타일 컨트롤을 다음 컨테이너로 전달해야합니다. 그래서 UINavigationController 확장에 동일한 검사를 추가하여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따라서을 제시하고 에 새 탐색 또는 tabBar 컨트롤러를 NewFlowUIViewController추가 한 다음 확장 기능을 추가 NewFlowUIViewController하여 추가보기 컨트롤러의 상태 표시 줄 스타일을 관리 한다고 가정합니다 .

  • 혹시 설정 modalPresentationStyle 이외의 fullScreen모달로 표시하는 동안, 당신은 설정해야 modalPresentationCapturesStatusBarAppearance이되게 뷰 컨트롤러 상태 표시 줄 모양의 통제를 받아야하므로 true로.


훌륭한 답변!
Amin Benarieb

3
이것은 잘못되어 iOS 13.4에서 중단됩니다. Swift에서 객관적인 C 클래스를 확장하는 것은 객관적인 C 범주를 통해 구현되기 때문입니다. Objective C 범주를 통한 메소드 재정의는 권장되지 않으며 중단 될 수 있습니다. 참조 stackoverflow.com/a/38274660/2438634
마크 Etcheverry

@MarcEtcheverry이 특정 인스턴스는 틀리지 않았습니다. 문제는 UINavigationController와 같은 다른 객체 / 프로토콜의 서브 클래스가 동적 디스패치에서 충돌 할 사전 구현이 없었기 때문입니다. 실제 서브 클래스 내에 기본값이나 구현이 없었기 때문에 이것이 불필요한 의존성을 생성하지 않고 앱 전체에서이를 구현하는 가장 깨끗한 방법 인 이유입니다. 불행히도 13.4는이 동작을 변경 한 것으로 보입니다. 나는 그들이 수년간 존재하지 않았던 점검 또는 구현을 지금 막 뒤에서 추측하고 있습니다 .........
TheCodingArt

8

iOS 13 솔루션

UINavigationControllerUIViewController(🙃을 알고있는) 의 하위 클래스입니다 !

따라서 내비게이션 컨트롤러에 내장 된 뷰 컨트롤러를 제시 할 때는 실제로 내장 뷰 컨트롤러를 제시하지 않습니다. 네비게이션 컨트롤러를 소개합니다! UINavigationController의 하위 클래스 인을 (를 UIViewController) 상속 preferredStatusBarStyle하며 childForStatusBarStyle원하는대로 설정할 수 있습니다.

다음 방법 중 하나가 작동해야합니다.

  1. 다크 모드를 완전히 해제
    • 당신의에서 info.plist, 다음과 같은 속성을 추가 :
      • 키- UIUserInterfaceStyle(일명 "사용자 인터페이스 스타일")
      • 가치-빛
  2. preferredStatusBarStyle내에서 재정의UINavigationController

    • preferredStatusBarStyle( doc )-보기 컨트롤러의 기본 상태 표시 줄 스타일
    • 서브 클래스 또는 확장 UINavigationController

      class MyNavigationController: UINavigationController {
          override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }

      또는

      extension UINavigationController {
          open override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }
  3. childForStatusBarStyle내에서 재정의UINavigationController

    • childForStatusBarStyle( doc )-시스템에 상태 표시 줄 스타일을 결정하기 위해 뷰 컨트롤러가 필요할 때 호출됩니다.
    • Apple의 문서에 따르면

      "컨테이너 뷰 컨트롤러가 하위 뷰 컨트롤러 중 하나에서 상태 표시 줄 스타일을 파생하는 경우 [이 특성을 대체하고 해당 하위 뷰 컨트롤러를 리턴하십시오. nil을 리턴하거나이 메소드를 대체하지 않으면 self의 상태 표시 줄 스타일이 사용됩니다. 이 메소드의 리턴 값이 변경되면 setNeedsStatusBarAppearanceUpdate () 메소드를 호출하십시오. "

    • 다시 말해, 여기서 솔루션 3을 구현하지 않으면 시스템은 위의 솔루션 2로 대체됩니다.
    • 서브 클래스 또는 확장 UINavigationController

      class MyNavigationController: UINavigationController {
          override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }

      또는

      extension UINavigationController {    
          open override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }
    • 위에서 원하는 모든보기 컨트롤러를 반환 할 수 있습니다. 다음 중 하나를 권장합니다.

      • topViewController(of UINavigationController) ( doc )-탐색 스택 맨 위에있는보기 컨트롤러
      • visibleViewController(of UINavigationController) ( doc )-탐색 인터페이스에서 현재 보이는보기와 연관된보기 컨트롤러 (힌트 : "탐색 컨트롤러 자체 위에 모달로 표시된보기 컨트롤러"가 포함될 수 있음)

참고 : 하위 클래스를 결정하려는 경우 UINavigationControllerIB의 ID 관리자를 통해 해당 클래스를 탐색 컨트롤러에 적용해야합니다.

추신 : 내 코드는 스위프트 5.1 구문을 사용


화면 회전 후 상태 표시 줄이 검게 표시됩니다. 왜 그런지 알아? 이것은 iPad Pro 시뮬레이터에서만 발생합니다.
Pedro Paulo Amorim

@PedroPauloAmorim, 더 많은 정보를 제공 할 수 있습니까? 탑 뷰 컨트롤러는 어떻게 표시됩니까 (모달, 전체 화면, 쇼)? 내비게이션 컨트롤러 안에 중첩되어 있습니까? 텍스트가 검게 변합니까? 무엇을 이루려고 노력하고 있습니까?
Andrew Kirna

전체 앱에서 조명 상태 표시 줄을 설정했습니다. 그것은 두 번의 회전으로 빛을 얻습니다. iPad Pro 시뮬레이터에서 일어나고 있습니다. 뷰가 전체 화면으로 표시되고 탐색 컨트롤러 내에 중첩되지 않습니다. 텍스트 만 어두워집니다.
Pedro Paulo Amorim

처음에는 표시 등 상태 표시 줄을 어떻게 설정합니까?
Andrew Kirna

3
확장을 통한 재정의는 실제 재정의가 아닙니다. 안전하지 않은 언어 오용입니다. 매우 쉽게 깨질 수 있습니다.
술탄

7

위 의 @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
}

2
이것은 잘못되어 iOS 13.4에서 중단됩니다. Swift에서 객관적인 C 클래스를 확장하는 것은 객관적인 C 범주를 통해 구현되기 때문입니다. Objective C 범주를 통한 메소드 재정의는 권장되지 않으며 중단 될 수 있습니다. 참조 stackoverflow.com/a/38274660/2438634
마크 Etcheverry

@MarcEtcheverry이 특정 인스턴스는 틀리지 않았습니다. 문제는 UINavigationController와 같은 다른 객체 / 프로토콜의 서브 클래스가 동적 디스패치에서 충돌 할 사전 구현이 없었기 때문입니다. 실제 서브 클래스 내에 기본값이나 구현이 없었기 때문에 이것이 불필요한 의존성을 생성하지 않고 앱 전체에서이를 구현하는 가장 깨끗한 방법 인 이유입니다. 불행히도 13.4는이 동작을 변경 한 것으로 보입니다. 나는 그들이 수년간 존재하지 않았던 점검 또는 구현을 지금 막 뒤에서 추측하고 있습니다 .........
TheCodingArt


4

iOS 7의 UIStatusBarStyle

iOS 7의 상태 표시 줄은 투명합니다.

상태 표시 줄의 스타일은 해당 내용의 모양을 나타냅니다. iOS 7에서 상태 표시 줄 내용은 어둡 UIStatusBarStyleDefault거나 ( UIStatusBarStyleLightContent) 밝습니다 ( )입니다. 모두 UIStatusBarStyleBlackTranslucentUIStatusBarStyleBlackOpaque아이폰 OS 7.0에서 사용되지 않습니다. UIStatusBarStyleLightContent대신 사용하십시오 .

변경하는 방법 UIStatusBarStyle

상태 표시 줄 아래에 탐색 표시 줄이 있으면 탐색 표시 줄 스타일 ( UINavigationBar.barStyle) 과 일치하도록 상태 표시 줄 스타일이 조정됩니다 .

특히, 탐색 막대 스타일이 UIBarStyleDefault 인 경우 상태 막대 스타일은 UIStatusBarStyleDefault; 탐색 모음 스타일이 UIBarStyleBlack인 경우 상태 표시 줄 스타일은입니다 UIStatusBarStyleLightContent.

상태 표시 줄 아래에 탐색 표시 줄이없는 경우 앱이 실행되는 동안 개별보기 컨트롤러에서 상태 표시 줄 스타일을 제어하고 변경할 수 있습니다.

- [UIViewController preferredStatusBarStyle]선호 상태 표시 줄 스타일을 반환하도록 재정의 할 수 있습니다 아이폰 OS 7에 추가 된 새로운 방법입니다 :

- (UIStatusBarStyle)preferredStatusBarStyle
  {
      return UIStatusBarStyleLightContent;
  }

상태 표시 줄 스타일을 자체가 아닌 하위 뷰 컨트롤러로 제어해야하는 경우 해당 하위 뷰 컨트롤러 -[UIViewController childViewControllerForStatusBarStyle]를 반환하도록 재정의 합니다.

이 동작을 선택하지 않고 -[UIApplication statusBarStyle]메소드 를 사용하여 상태 표시 줄 스타일을 설정하려면 UIViewControllerBasedStatusBarAppearanceInfo.plist파일에 키를 추가하고 NO 값을 지정하십시오.


3

누구나 내비게이션 컨트롤러를 사용하고 있고 모든 내비게이션 컨트롤러가 블랙 스타일을 갖기를 원한다면 Swift 3에서 이와 같이 UINavigationController에 확장을 작성하면 모든 내비게이션 컨트롤러에 적용됩니다. 시각).

extension UINavigationController {

    override open func viewDidLoad() {
        super.viewDidLoad()

        self.navigationBar.barStyle = UIBarStyle.black
    }

}

1
그러나 내 탐색 표시 줄이 숨겨져 있으면 어떻게합니까?
Slavcho

1
탐색을 숨기고 상태 표시 줄을 볼 수 있어야하기 때문입니다.
Slavcho

1

모든 종류의 UIViewController에 대해 Swift에서 :

당신의 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(기본값).


@ swift3에서는 어떻게됩니까?
항공기

1

스위프트 3 iOS 10 솔루션 :

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
 }

1

대부분의 답변에는에 대한 올바른 구현 childViewControllerForStatusBarStyle방법이 포함되어 있지 않습니다 UINavigationController. 내 경험에 따르면 투명보기 컨트롤러가 탐색 컨트롤러 위에 표시되는 경우와 같은 경우를 처리해야합니다. 이 경우 제어를 모달 컨트롤러 ( visibleViewController)로 전달해야 하지만 사라질 때는 안됩니다.

override var childViewControllerForStatusBarStyle: UIViewController? {
  var childViewController = visibleViewController
  if let controller = childViewController, controller.isBeingDismissed {
    childViewController = topViewController
  }
  return childViewController?.childViewControllerForStatusBarStyle ?? childViewController
}

1

내 경우에는, 내가 실수로보기 / 네비게이션 컨트롤러되게 한 UIModalPresentationStyle.overFullScreen원인 preferredStatusBarStyle이라고하지를. 로 다시 전환하면 UIModalPresentationStyle.fullScreen모든 것이 작동합니다.


1

iOS 13.4의 경우 범주 의 preferredStatusBarStyle메소드 UINavigationController가 호출되지 않으며 하위 클래스를 사용할 필요가없는 스위 즐링이 유일한 옵션 인 것 같습니다.

예:

카테고리 헤더 :

@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];

0

이 문제를 해결하는 방법은 다음과 같습니다.

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 는 제공된 값을 기반으로 적절한 사용자 정의를 수행합니다.


0

누군가 UISearchController 에이 문제가 발생하면. UISearchController의 새 하위 클래스를 만든 다음 해당 클래스에 아래 코드를 추가하십시오.

override func preferredStatusBarStyle() -> UIStatusBarStyle {
    return .LightContent
}

0

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;솔루션 을 사용할 때

plist로 이동하여 "컨트롤러 기반 상태 표시 줄보기"를 YES로 설정하십시오. NO이면 작동하지 않습니다.


프로젝트 plist에서 UIViewControllerBasedStatusBarAppearance를 YES로 설정하면 모든 것이 달라졌습니다. 나는 그것을 잊었다.
filo

0

Xcode 11.4부터는 preferredStatusBarStyle UINavigationController 확장에서 속성을 더 이상 호출되지 않으므로 작동하지 않습니다.

설정 barStyle의를 navigationBar.black실제로 작동하지만 당신은 빛과 어둠 모드에 대해 서로 다른 모습을 가질 수있는 내비게이션 바에 하위 뷰를 추가하는 경우이 원치 않는 부작용을 추가합니다. barStyle를 검은 색 으로 설정하면 userInterfaceStylenavigationBar에 포함 된보기는 항상 앱과 userInterfaceStyle.dark관계없이 userInterfaceStyle표시됩니다.

내가 생각해 낸 올바른 해결책은 하위 클래스를 추가 UINavigationController하고 재정의하는 preferredStatusBarStyle것입니다. 모든 뷰에이 사용자 정의 UINavigationController를 사용하면 저장 측에있게됩니다.


-1

NavigationController 또는 TabBarController는 스타일을 제공해야합니다. 여기에 내가 해결 한 방법이 있습니다 : https : //.com/a/39072526/242769


이 질문이 다른 질문의 사본이라고 생각되면 중복하여 투표하십시오.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.