I have a share sheet/extension that, for some reason, is not fading the status bar (even though it fades the rest of the screen). I have included an image to demonstrate the issue. I simply want the entire screen to fade, including the status bar. In the past, I've had a similar issue with UIAlertControllers not fading the status bar.
i think its better to tweak it only necessary UIViewControllers (when needed) by using,
override var preferredStatusBarStyle: UIStatusBarStyle {
return UIStatusBarStyle.default //dark content
}
or on the parenting UINavigationController, to avoid above bugs you have experienced.
Are you presenting a UIAlertController with animated: set to true? I'm not able to reproduce this issue using the buo.showShareSheet() method:
let buo = BranchUniversalObject(canonicalIdentifier: "referrer/\(UUID().uuidString)")
buo.title = "Test"
buo.contentDescription = "Test"
let lp: BranchLinkProperties = BranchLinkProperties()
lp.feature = "referral"
lp.addControlParam("user_id", withValue: UUID().uuidString)
buo.showShareSheet(with: lp, andShareText: instructionString, from: self) { (params, success) in
}
Since I was seeing this as an app-wide issue, I started looking in my AppDelegate instead of the individual view controllers. I found a function, setStatusBarBackgroundColor(color: UIColor.white), called on app launch that appeared to be the cause.
func setStatusBarBackgroundColor(color: UIColor) {
guard let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else { return }
statusBar.backgroundColor = color
}
Frankly, I'm not sure why I had written this, but removing it appears to solve the issue entirely.
Related
I am building an app for iOS13. I want to change the text color of status bar according to the color scheme which user can select. It seems the text color of status bar cannot be changed directly, so I try to change the statusBarStyle instead.
First I try:
var myStatusBarStyle = UIStatusBarStyle.default { didSet { setNeedsStatusBarAppearanceUpdate() } }
override var preferredStatusBarStyle : UIStatusBarStyle { return myStatusBarStyle; }
But it did not work.
Then I try:
UIApplication.shared.statusBarStyle = myStatusBarStyle;
It does do the job! But Xcode gives a warnning: " 'statusBarStyle' was deprecated in iOS 13.0: Use the statusBarManager property of the window scene insted."
so, in sceneWillEnterForeground(_ scene: UIScene) I try:
guard let ws = (scene as? UIWindowScene) else { return }
if let t = ws.statusBarManager { print(t.statusBarStyle) }
Unfortunately, t.statusBarStyle is readonly.
Now, how can I do?
ps: I have no Navigation Bar or Tab Bar in the Main.storyboard.
in iOS 13, we are not allowed to do that but there are always escape roots..
I used
self.navigationController?.navigationBar.barStyle = .black
To make status bar black and it works
You can use various options instead of black as you like (.default , .blackTranslucent , .blackOpaque) in place of .black
Before I start I would to apologise if this question is duplicated as I seen plenty of question but I can't find out what I need.
I want to create a global Status, navigation, toolbar bar style and, if possible, the bottom part of the view on iPhones X onwards from my app delegate only so I don't have to set it form each Viewcontroller.
So far I have:
extension UIApplication {
var statusBarView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
and a function called inside the didFinishLaunchingWithOptions method
private func setupNavigationBarStyle(){
UIApplication.shared.statusBarView!.backgroundColor = UIColor.AppColors.statusBar
UIApplication.shared.statusBarStyle = .lightContent
UINavigationBar.appearance().barTintColor = .brown
UINavigationBar.appearance().tintColor = .green
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.yellow]
UINavigationBar.appearance().isTranslucent = false
}
I attach a dummy design for my view controller using the storyboard
and the final result is
Despite not being the best design I have 3 questions.
UIApplication.shared.statusBarStyle = .lightContent is deprecated and it shows a warning and I don't want that.
How can I change the color for the bottom for iPhone X onwards (currently in red and and where the Horizontal line is).
Can I change statusBarStyle for another not defined and change the text color in my status bar Purple?
I hope it will help you
UIApplication.shared.statusBarStyle = .lightContent is deprecated and it shows a warning and I don't want that.
Go to Project -> Target, Set Status Bar Style to Light
How can I change the color for the bottom for iPhone X onwards (currently in red and and where the Horizontal line is).
it is not possible to modify the color, and you shouldn’t worry about it, since it’s out of your control and guaranteed to be visible.For Info(https://medium.freecodecamp.org/reverse-engineering-the-iphone-x-home-indicator-color-a4c112f84d34).
Can I change statusBarStyle for another not defined and change the text color in my status bar Purple?
func setStatusBarBackgroundColor(color: UIColor) {
guard let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else { return }
statusBar.backgroundColor = color
}
//Use self.setStatusBarBackgroundColor(color: .purple)
Thanks
I'm trying to do a design a XLPagerTabStrip control where the overall theme changes as the tabs change.
The following is what's getting called when a tab changes
changeCurrentIndexProgressive = { [weak self] (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in
guard changeCurrentIndex == true else { return }
oldCell?.label.textColor = .black
newCell?.label.textColor = UIColor.red
//Change the navigation bar's color
self?.navigationController?.navigationBar.barTintColor = UIColor.red
//Attempting to change the selected bar color
self?.settings.style.selectedBarBackgroundColor = UIColor.green
}
Changing the navigation controllers color works, but I can't get the the selected bar (or any thing under the settings object) to change from within here?
Is it possible to change the settings once the view has been loaded?
Code Check
if you check the code Code Search for selectedBarBackgroundColor then you find this 3 interesting search results:
BaseButtonBarPagerTabStripViewController#viewDidLoad
buttonBarView.selectedBar.backgroundColor = settings.style.selectedBarBackgroundColor
BarPagerTabStripViewController#viewDidLoad
barView.selectedBar.backgroundColor = settings.style.selectedBarBackgroundColor ?? barView.selectedBar.backgroundColor
ButtonBarPagerTabStripViewController#viewDidLoad
buttonBarView.selectedBar.backgroundColor = settings.style.selectedBarBackgroundColor
that means that you need to set the BackgroundColor before an viewDidLoad.
Issue
see also the answer of this issue: XLPagerTabStrip Issue #137:
Actually this isnot a issue. Settings should be configured before viewDidLoad is called. Could you please document it in the readme?
workaround
buttonBarView is a public var maybe you can set it additional to the settings direct this property: buttonBarView.selectedBar.backgroundColor
I use a UISplitViewController with preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay and I was looking for a way to dismiss master view controller. My master contains a table view and I'd like to close it whenever I select a cell. Surprisingly UISplitViewController doesn't seem to offer a method for that (but I do see Apple Mail doing that we you select an email in portrait mode).
I found the following workaround reported here: Hiding the master view controller with UISplitViewController in iOS8 (look at phatmann answer). This works but it also creates a weird animation when it's dismissed, there's an underlying gray outlined view which is not animated together with my master's view. The problem has been reported also here: iOS Swift 2 UISplitViewController opens detail screen on master's place when on iPad/ iPhone 6+
The problem occurs only when I dismiss master with this workaround, not when I tap on the secondary so I guess UISplitViewController is not following the regular dismiss flow when you just call sendAction on the button.
I used the following code to address this problem. There might be a better way to match on the specific view that is causing the issue. That said, this code was in an app approved by Apple in April of this year. What the code does is look for a specific view of a certain type, and if found, then it makes it hidden until the animation is complete. Its somewhat future proof, since if it does't detect the special view, it does nothing. I also added some comments for adopters on where you might want to make changes.
func closePrimaryIfOpen(finalClosure fc: (() -> Void)? = nil) {
guard let
primaryNavController = viewControllers[0] as? MySpecialNavSubclass,
primaryVC = primaryNavController.topViewController as? MySpecialCalss
else { fatalError("NO Special Class?") }
// no "official" way to know if its open or not.
// The view could keep track of didAppear and willDisappear, but those are not reliable
let isOpen = primaryVC.view.frame.origin.x >= -10 // -10 because could be some slight offset when presented
if isOpen {
func findChromeViewInView(theView: UIView) -> UIView? {
var foundChrome = false
var view: UIView! = theView
var popView: UIView!
repeat {
// Mirror may bring in a lot of overhead, could use NSStringFromClass
// Also, don't match on the full class name! For sure Apple won't like that!
//print("View: ", Mirror(reflecting: view).subjectType, " frame: \(view.frame)")
if Mirror(reflecting: view).description.containsString("Popover") { // _UIPopoverView
for v in view.subviews {
//print("SV: ", Mirror(reflecting: v).subjectType, " frame: \(v.frame)")
if Mirror(reflecting: v).description.containsString("Chrome") {
foundChrome = true
popView = v
//popView.hidden = true
break
}
}
if foundChrome { break }
}
view = view.superview
} while view != nil
return popView
}
// Note: leave it as optional - Apple changes things and we don't find the view, things still work!
let chromeView = findChromeViewInView(self.view)
UIView.animateWithDuration(0.250, animations: {
chromeView?.hidden = true
self.preferredDisplayMode = .PrimaryHidden
}, completion: { Bool in
self.preferredDisplayMode = .PrimaryOverlay
chromeView?.hidden = false
if let finalClosure = fc {
finalClosure()
}
//print("SLIDER CLOSED DONE!!!")
} )
}
}
I've been working on a set of iOS action extensions I seem to be having a problem with the way that the UINavigationBar is being displayed in the app if it is controlled by a UINavigationController.
The problem, in short is that the navigation bar gets shifted up when you rotate from portrait, to landscape, and back to portrait again. The problem is exacerbated if you rotate all the way around. I wish I could provide images, but I cannot given the rules of StackOverflow.
Regardless, this was tested using a only slightly modified Action App Extension (modified to lower target OS, silence a warning about the NSExtensionActiviationRule, etc), both with a UINavigationBar embedded in a UINavigationController and not embedded, just as a view in the ActionViewController. When not in an UINavigationController, the rotations look as expected, but retains a white patch around the status bar (and the navigation bar is slightly wider in the landscape orientation), but when put into a UINavigationController, the bar button items are shifted up.
This was tested pretty thoroughly in 8.2, and even now running the slightly modified app, it looks as one would expect. Does anyone know exactly going on here? Why does the button get shifted up when I use a UINavigationController in 8.3 and not 8.2? I can't seem to find any documentation on a change in 8.3 that would affect it, and no documentation that UINavigationController shouldn't be used in an Action Extension, etc. Any help would be greatly appreciated.
Here is the code, if you are interested, for the ViewController. Its not particularly enlightening, as it's basically what Apple gives you:
import UIKit
import MobileCoreServices
class ActionViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Get the item[s] we're handling from the extension context.
// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
var imageFound = false
for item: AnyObject in self.extensionContext!.inputItems {
let inputItem = item as! NSExtensionItem
for provider: AnyObject in inputItem.attachments! {
let itemProvider = provider as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
// This is an image. We'll load it, then place it in our image view.
weak var weakImageView = self.imageView
itemProvider.loadItemForTypeIdentifier(kUTTypeImage as String, options: nil, completionHandler: { (url, error) in
let imageURL = url as! NSURL?;
if imageURL != nil {
NSOperationQueue.mainQueue().addOperationWithBlock {
if let imageView = weakImageView {
let image = UIImage(contentsOfFile: imageURL!.path!);
imageView.image = image;
}
}
}
})
imageFound = true
break
}
}
if (imageFound) {
// We only handle one image, so stop looking for more.
break
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func done() {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
self.extensionContext!.completeRequestReturningItems(self.extensionContext!.inputItems, completionHandler: nil)
}
}
Thanks in advance!