I have this piece of code where I present the alert :
func arraysize() -> [Int]? {
let title = "Your file is empty"
let message = "Please refer to the instructions"
let okText = "OK"
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okayButton = UIAlertAction(title: okText, style: UIAlertActionStyle.Cancel, handler: nil)
alert.addAction(okayButton)
do{
....
if array?.isEmpty == true{
print("the array is empty")
presentViewController(alert, animated: true, completion: nil)
}
}
catch let error {
print(error)
}
return array
}
However my alert doesn't show. It used to show and although I haven't changed any code it stopped working for me. Can somebody help me understand what I am doing wrong?
P.S. I am also getting this warning :
[16632:713433] Warning: Attempt to present UIAlertController whose view is not in the window hierarchy!
Could this be it?
As #rmaddy explained in the comments, my problem was that I was trying to show an alert from the controller that never appears on the actual screen. I fixed this by calling this method from a controller that appears on the screen and it worked.
Related
I have a screen with a collection view, and a plus sign bar button item. When the plus sign is pressed, an alert window pops up, where the user can add information to the list. Upon hitting OK, I am trying to refresh the collection view, but I'm doing something wrong.
The print statement "passed guard" is achieved, and I can get the information they entered. Just can't refresh the view to reflect this without leaving and coming back. Any guidance? I've run into this a few times actually, so I'm clearly missing something. Thanks very much in advance.
#objc func newButtonPressed() {
let alert = UIAlertController(title: "Add", message: "", preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "Name"
}
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
var name = ""
guard let textFields = alert.textFields else { return }
guard let navController = self.parent as? UINavigationController else { return }
guard let settingsVC = navController.topViewController as? SettingsVC else { return }
print("passed guard") // success
DispatchQueue.main.async {
settingsVC.collectionView.reloadData()
settingsVC.view.backgroundColor = .red
// For testing purposes, explicitly using main thread and setting to red
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
May be you need to alter the collection dataSource
guard let textFields = alert.textFields else { return }
settingsVC.arr.append(textFields.first!.text!) // arr is collection dataSource
settingsVC.collectionView.reloadData()
Alright, I've looked up a lot of documentation on how the UIAlertController's work and I have a rather unique scenario. My application is being designed to work with a HID Bluetooth scanner. When I use:
preferredStyle: UIAlertControllerStyle.Alert
After I generate an alert that the item I have scanned is incorrect. Cool, alert is happening, problem is if I scan again ( which emulates keyboard input ), the return key is being sent to the alert and the alert is running the dismiss action.
If I use:
preferredStyle: UIAlertControllerStyle.ActionSheet
Then the alert is staying where it should be and ignoring scans while the alert window is up just how I want it.
So my question is, how do I capture the return key and prevent the Alert from calling the dismiss action? I'm a bit new with swift and I have a feeling the answer is simple, but I've tried half a dozen things that just isn't working.
If there is a setting to prevent all user input to the alert window or anything solution, I'm all for any method. I just rather not use the ActionSheet, and prefer to use the iOS alerts instead of creating my own screen. If this is not possible, I'm sure I can build my own 'alerts' window.
Code, that I'm calling from a simple Alerts class I made.
import UIKit
class Alerts {
var controller: UIViewController
var message: String
var title: String
init?(title: String, message: String, controller: UIViewController){
if title.isEmpty || message.isEmpty {
return nil
}
self.title = title
self.message = message
self.controller = controller
}
func save_alert(input_field:UITextField, callable: (Bool)->Void ){
let action = UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default) {
UIAlertAction in
callable(false)
input_field.enabled = true
input_field.becomeFirstResponder()
print("DISMISS CALLED")
}
let alert = UIAlertController(title: self.title,message:self.message,preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(action)
self.controller.presentViewController(alert,animated:true, completion: nil)
}
}
Try something like this.
func save_alert(input_field:UITextField, callable: (Bool)->Void ){
let action = UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default) {
UIAlertAction in
callable(false)
input_field.enabled = true
input_field.becomeFirstResponder()
print("DISMISS CALLED")
showAlert()
}
showAlert()
}
func showAlert() {
let alert = UIAlertController(title: self.title,message:self.message,preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(action)
self.controller.presentViewController(alert,animated:true, completion: nil)
}
I have got the below piece of code :
let title = "You are not connected to DropBox"
let message = "Please go back to the main page and try to log in again"
let okText = "OK"
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okayButton = UIAlertAction(title: okText, style: UIAlertActionStyle.Cancel, handler: nil)
alert.addAction(okayButton)
if dbRestClient == nil{
print("please refresh me")
presentViewController(alert, animated: true, completion: nil)
}`
However my alert doesn't show up. I am calling this alert from a View Controller that actually shows on the page so its not the case where my VC is working behind the scene. Please let me know what I am doing wrong here.
Use self.presentViewController(alert, animated: true, completion: nil) instead.
Should work after adding self.
I want the button to go to the QaController if the word Hello is typed otherwise I want the alert to appear and then go back to the home screen (viewController) but it doesn't seem to work
#IBAction func submitButton(sender: AnyObject) {
if TextField.text.containsString("Hello"){
let secondViewController:QaController = QaController()
self.presentViewController(secondViewController, animated: true, completion: nil)
} else {
let alertController = UIAlertController(title: "Thank You!", message:
"We appreciate your feedback!", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
let homeViewController:ViewController = ViewController()
self.presentViewController(homeViewController, animated: true, completion: nil)
}
}
The code works fine without the IF statements so I'm not sure whats wrong :/
What goes wrong is when I click Submit, when I put "Hello" in it shows a black screen with no error message, instead of displaying the correct view
Thanks in advance!
I think you are comparing your string with lower case, May be your text field value is "hello" not equal to "Hello". So please compare like
if(TextField.text!.caseInsensitiveCompare("Hello") == NSComparisonResult.OrderedSame)
{
// do your stuff
}
else{
print(TextField.text)
}
Hope it will help you.
In my app I display tow alert views. The second alert view should pop up if the first has been closed. Now I check if an alert view is displayed like this:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! ViewController
if viewController.view.window != nil {
}
else {
let alertView = UIAlertController(title: NSLocalizedString("IAP", comment: "comment"), message: NSLocalizedString("IAP1", comment: "comment"), preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Ok", style: .Cancel, handler: nil))
viewController.presentViewController(alertView, animated: true, completion: nil)
}
I send the 2nd alert view if the first isn't displayed anymore. But if the first view is still displayed the 2nd alert view doesn't pops up anymore. So my question is if there's a waiting line for alert views and how can I solve this problem?
You should define a handler for the first action and present the 2nd alertView within the handler.
So instead of
UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
you should do
UIAlertAction(title: "Ok", style: .Cancel) { (action) -> Void in
// Present the other alertView
}
If you are using a navigation controller, the general way to see if an alert is already displayed is to check the presentedViewController property.
if let _ = navigationController.presentedViewController {
print("is already presenting \(navigationController.presentedViewController)")
} else {
navigationController.presentViewController(alert, animated:true, completion:nil)
}
For a fast patch in any UIViewController : (Xcode 8.3.1 & Swift 3.1)
func blabla() {
if presentedViewController != nil {
delay(0.5, closure: {
self.blabla()
})
return
}
// other alert code here
}
Simple way to check in Swift
var isAlertViewPresenting: Bool {
get {
if self.presentedViewController is UIAlertController {
return true
}
return false
}
}