I'm using this swift code to display an alert dialog from a UIViewController
import UIKit
class TestViewController: UIViewController {
#IBAction func onTestClick(sender: UIButton) {
let alertController = UIAlertController(title: "title", message: "message", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
}
When the alert is shown from a view with a dark (e.g. black) background, it briefly "flickers" (appears white and then instantly change to a color slightly darker than white).
This doesn't seem to happen on other apps and the system OS.
What's the problem here?
I was able to reproduce what you are saying and I don't think you are actually doing something wrong. If you turn slow animations on the simulator (cmd + t) you will see the alert controller being positioned in the center of the screen in a fade animation. When the animation is in progress the alert controller has a white background (and this is Apple's code, it's fine) and when the animation finishes the alert controller has a transparent background which will change according to the colour of the view behind it. You don't notice anything when the view is white because white + white = white! :)
I hope that helps.
Related
Yes, I know. You can't change the appearance of a UIAlertController. I don't want to change the background of the UIAlertController itself, I want to change the tint of the view's background. You know how it's like a transparent black color? I want to change that color to clear. How would I do this?
For swift 3 UIAlertController change background color.
let alert = UIAlertController(title: "validate",message: "Check the process", preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alert.addAction(dismissAction)
self.present(alert, animated: true, completion: nil)
// change the background color
let subview = (alert.view.subviews.first?.subviews.first?.subviews.first!)! as UIView
subview.layer.cornerRadius = 1
subview.backgroundColor = UIColor(red: (195/255.0), green: (68/255.0), blue: (122/255.0), alpha: 1.0)
No you cannot change the transparent background color. That does not belong to part of UIAlertController variable that you can control.
You will have to fix it by presenting a new view controller with a transparent background and a faked alert-controller-like UI element.
To further approve you does not have control for the alert controller, create another view with frame origin on 0,0 and then add to your alert controller's view. It will show on the top left corner of your pop up window, not the window of your window
You can change the background colour as follows:
let alert = UIAlertController(title: "TITLE", message: "My message", preferredStyle: .alert)
if let subview = alert.view.subviews.first?.subviews.first?.subviews.first {
subview.backgroundColor = .red
}
alert.view.tintColor = UIColor.black
Try this..
[alert.view setBackgroundColor:[UIColor whiteColor]];
Try changing whiteColor to whatever colour u wish.
To fix the corner extra color, add corner radius and run.
Hope this helps!
You can create CustomAlertController, set your color in method viewWillAppear and show this controller instead of default UIAlertController. It's bad but working solution.
final class CustomAlertController: UIAlertController {
//MARK: - Lifecycle
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.superview?.backgroundColor = yourColor
}
}
I am using Swift 3, Xcode 8.2.
I have an application where the user launches the iPhone camera and I give them a popup with instructions on how to take a good picture. I want there to be a way to create pages within the UIAlertController. I did a quick sketch of what I want to achieve.
Code wise, I am not sure what to do:
func displayInstructions() {
let insController = UIAlertController(title: "Instructions", message: "Step 1: Do this.", preferredStyle: .alert)
let actionDone = UIAlertAction(title: "OK", style: .cancel) { (action:UIAlertAction) in
//This is called when the user presses the cancel button.
print("You've pressed the done button");
}
//Add the buttons
errorController.addAction(actionDone)
// Some way to addSubviews here??
let pageViewController: UIPageViewController
insController.addSubview(pageViewController)
//Present the instruction controller
self.present(insController, animated: true, completion: nil)
}
Any help would be greatly appreciated. Thank you!
There is a property on UIAlertController, not advertised in public API but that seem usable without trouble going through the app store review. So, using KVC, you can set the contentViewController of the alert controller.
let pageViewController: UIPageViewController
// configure pageViewController...
insController.setValue(pageViewController, forKey: "contentViewController")
You can also set the size of the contentViewController by setting preferredContentSize.height on it
pageViewController.preferredContentSize.height = 180
This is what the result looks like with an empty page view controller
I am developing an iOS app, using Swift, and am having two issues with the UIAlertController being quite slow!
1 - Slow and jittery to appear
I have set up a UITableViewController, and when I tap a cell, it fires the following code:
let alertController = UIAlertController(title: "Enter Exam Grade", message: nil, preferredStyle:UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler({(textField: UITextField) in
textField.placeholder = "Earned"
textField.keyboardType = .NumberPad
})
alertController.addTextFieldWithConfigurationHandler({(textField: UITextField) in
textField.placeholder = "Out of"
textField.keyboardType = .NumberPad
})
alertController.addAction(UIAlertAction(title: "Save", style: UIAlertActionStyle.Default, handler: {
(alert: UIAlertAction) in
if let gradeTextField = alertController.textFields!.first as UITextField? {
if let outOfTextField = alertController.textFields!.last as UITextField? {
if (gradeTextField.text != "" && outOfTextField.text != "") {
print(gradeTextField.text)
print(outOfTextField.text)
}
}
}
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
When I navigate to the view, and tap the cell for the first time, I get a jittery and slow load of the alert, as you can see in the GIF below. Interestingly, subsequent taps load generally smoothly and quickly.
EDIT: The GIF has a framerate a little too slow, so I have attached some stills taken from a slowed down video of it:
a) First tap of "Grade Exam", the alert begins to appear in centre of the screen, but then shifts up (in a jolt) to the correct position).
b) Subsequent taps, the alert appears in the correct upper position from the beginning.
2 - Keyboard slow to dismiss when Alert dismisses
I have seen this issue all around StackOverflow, with no real satisfactory solutions. When you tap the Cancel button, the Alert will dismiss quickly, but then the keyboard takes a long time to dismiss also. This should be instantaneous, as the hanging keyboard leaves a bad impression with users.
The launching of your keyboard seems to be "normal" from the gif files you have provided. However assuming if it is slow, maybe you could try this if it does load faster.
Just to mention I've not tried this code and typing off from here.
For slow display of keyboard.
textField.placeholder = "Out of"
textField.keyboardType = .NumberPad
textField.becomeFirstResponder()
For slow hiding of keyboard.
alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: {
(alert: UIAlertAction) in
self.view.endEditing(true)
}))
I have been having some trouble making UIAlerts work. I have looked at a couple SO questions that seem to solve this issue yet I still have a problem. The alert view seems to not be presented. Here is my code:
var inputTextField: UITextField?
let actionSheetController: UIAlertController = UIAlertController(title: "Create a password", message: "", preferredStyle: .Alert)
let save: UIAlertAction = UIAlertAction(title: "Save", style: .Default) { action -> Void in
if !(inputTextField?.text=="password"){
println(inputTextField?.text)
}else{
println("You have a really bad password")
}
}
actionSheetController.addAction(save)
actionSheetController.addTextFieldWithConfigurationHandler { textField -> Void in
inputTextField = textField
}
self.presentViewController(actionSheetController, animated: true, completion: nil)
Here is the error:
Attempt to present <UIAlertController: 0x7fa7016305e0> on <PassProtect.ViewController: 0x7fa701576600> whose view is not in the window hierarchy!
Does anybody know why this is not being presented?
Any help or advice is greatly appreciated!
It's to do with the fact that when you make the call to present the UIAlertController, self.view is not on screen. If you are writing this code in the viewDidLoad() section, this won't work as self.view is still off screen.
You can make this call once self.view is available, for example in viewDidAppear() or from any sort of UI action like clicking a button. Basically, anything that will occur before viewDidDisappear().
There is a similar question with similar information if you want to read it and also here for a more generalised case, i.e. trying to present any sort of view controller which isn't in the view hierarchy.
I want to use an UIButton to trigger a UIAlertController... in Swift
So in this example I have an "Agree" button below some text, and I want the user to click Agree and have a pop-up alert with 2 options confirming/canceling the agreement. How would I go about connecting the UIButton and the UIAlertController. Also if the user cancels, I want the alert to dismiss and remain on the current VC. If the user agrees, I want it to segue to another view controller.
I fairly new to Swift, so if the answer could be detailed that would be extremely appreciated!
You need to add an IBAction (Control drag from your UIButton on your XIB/Storyboard, to the viewController implementation to link the button to the method). Inside the method that you link to the action you need to present the viewController, similar to the below:
func showAlert(sender: UIButton!)
{
var alert = UIAlertController(title: "Title", message: "Some Message", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Agree", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}