ios - Presenting a view controller without changing the status bar color, like UIAlertController -


when performing network operations, present modal view controller (similar mbprogresshud view controller) prevent user interaction , indicate progress.

the view controller has modalpresentationstyle = .custom , animated using transitioning delegate , custom presentation controller. beyond animating transitions have no custom actions driving presentation.

the problem have whenever view controller presented, turns status bar color black. override preferredstatusbarstyle make return .lightcontent view controller presented on view controller .default , don't want change there either. basically, want have same behavior uialertcontroller.

screenshot showing presented view controller causing dark status bar content

i have tried configuring presentation controller move presented view controller out of status bar space:

private class seuiprogresscontrollerpresentationcontroller: uipresentationcontroller {      override func shouldpresentinfullscreen() -> bool {         return false     }      private override func frameofpresentedviewincontainerview() -> cgrect {         return super.frameofpresentedviewincontainerview().insetby(dx: 40, dy: 100)     }      ... } 

these settings move top of presented controller out of status bar status bar still affected. there property missing stop view controller updating status bar style?

update

it looks has been fixed in ios 10. default behavior ignore status bar rules presented view controller unless either presented view controller has modalpresentationcapturesstatusbarappearance == true or use 1 of several built-in presentation controllers extend status bar space (not .custom).

basically, behavior custom has changed default opt-out rather forced opt-in.


for ios 9.x , lower

after digging, internal logic setting application's status bar color looks this:

var viewcontroller = window.rootviewcontroller!  while let presentedviewcontroller = viewcontroller.valueforkey("_presentedstatusbarviewcontroller") as? uiviewcontroller {     viewcontroller = presentedviewcontroller }  while let childviewcontroller = viewcontroller.childviewcontrollerforstatusbarstyle() {     viewcontroller = childviewcontroller }  let style = viewcontroller.preferredstatusbarstyle() 

the view controller's property _presentedstatusbarviewcontroller assigned during presentation based on value of presentation controller's private method _shouldchangestatusbarviewcontroller(). default implementation of method return true, _uialertcontrollerpresentationcontroller , handful of other presentation controllers returning false.

that means direct way not change status bar add method presentation controller:

private class seuiprogresscontrollerpresentationcontroller: uipresentationcontroller {      @objc func _shouldchangestatusbarviewcontroller() -> bool {         return false     }      ... } 

unfortunately, won't pass app store review.

instead, doing recreating logic applied presenting view controller in view controller:

public class seuiprogresscontroller: uiviewcontroller {      ...     public override func preferredstatusbarstyle() -> uistatusbarstyle {          guard var targetviewcontroller = presentingviewcontroller else {             return .lightcontent         }          while let parentviewcontroller = targetviewcontroller.parentviewcontroller {             targetviewcontroller = parentviewcontroller         }          while let childviewcontroller = targetviewcontroller.childviewcontrollerforstatusbarstyle() {             targetviewcontroller = childviewcontroller         }          return targetviewcontroller.preferredstatusbarstyle()     }      public override func prefersstatusbarhidden() -> bool {          guard var targetviewcontroller = presentingviewcontroller else {             return false         }          while let parentviewcontroller = targetviewcontroller.parentviewcontroller {             targetviewcontroller = parentviewcontroller         }          while let childviewcontroller = targetviewcontroller.childviewcontrollerforstatusbarhidden() {             targetviewcontroller = childviewcontroller         }          return targetviewcontroller.prefersstatusbarhidden()     } } 

Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

css - Make div keyboard-scrollable in jQuery Mobile? -

ruby on rails - Seeing duplicate requests handled with Unicorn -