Programing

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

lottogame 2020. 4. 7. 08:17
반응형

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


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


가능한 근본 원인

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

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 파일에.


UINavigationController를 사용하는 사람 :

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

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

TL; DR :

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

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;

그래서 실제로 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의 현재 기본값이라고 생각합니까?)


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

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

내 응용 프로그램은 세 가지 사용 : UINavigationController, UISplitViewController, UITabBarController,, 따라서 이러한 모든 상태 표시 줄을 통해 제어 할 것 같고 원인이됩니다 preferedStatusBarStyle자신의 아이들을 위해 호출 할 수 없습니다 수 있습니다. 이 동작을 재정의하려면 나머지 답변에서 언급 한 것처럼 확장을 만들 수 있습니다. 다음은 Swift 4의 세 가지 모두에 대한 확장입니다. Wish 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메소드 안에 작성하십시오 .

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

암호

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

     return YES;
}

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

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


UINavigationController에서이 ( preferredStatusBarStyletopViewController) 선호 되므로 호출되지 않습니다 self. 따라서 preferredStatusBarStyleUINavigationController에서 호출하려면을 변경해야합니다 childViewControllerForStatusBarStyle.

하나의 UINavigationController (내 권장 사항)에 대해 수행하려면 다음을 수행하십시오.

class MyRootNavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    override var childViewControllerForStatusBarStyle: UIViewController? {
        return nil
    }
}

모든 UINavigationController에 대해이를 수행하려면 (경고 : UIDocumentPickerViewController, UIImagePickerController 등에 영향을 미침) :

extension UINavigationController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return nil
    }
}

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

스위프트 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로.


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

presentedViewController.modalPresentationCapturesStatusBarAppearance = true

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


viewController가 UINavigationController에있는 경우

서브 클래스 UINavigationController 및 추가

override var preferredStatusBarStyle: UIStatusBarStyle {
    return topViewController?.preferredStatusBarStyle ?? .default
}

ViewController preferredStatusBarStyle가 호출됩니다.


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 값을 지정하십시오.


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

extension UINavigationController {

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

        self.navigationBar.barStyle = UIBarStyle.black
    }

}

모든 종류의 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(기본값).


스위프트 3 iOS 10 솔루션 :

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
 }

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

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

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

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로 설정하십시오. NO이면 작동하지 않습니다.


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


NavigationController 또는 TabBarController는 스타일을 제공해야합니다. 내가 해결 한 방법은 다음과 같습니다. https://stackoverflow.com/a/39072526/242769

참고 URL : https://stackoverflow.com/questions/19022210/preferredstatusbarstyle-isnt-called

반응형