UIAlert error, whose view is not in the window hierarchy - ios

I am working on my network connectivity,
I put checking reachability code in viewDidLoad, so that I notify User by alerting if there is not network.
Here is my code for this,
class ViewController: UIViewController {
var reachability : Reachability?
override func viewDidLoad() {
super.viewDidLoad()
if reachability?.isReachable() == true
{
print("reachable")
}else{
let myAlert = UIAlertController(title: "No network", message:
"Your network is not working", preferredStyle:
UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Ok", style:
UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion:
nil)
}
but If I try on my simulator or cellphone,
it shows error message that
2015-11-08 16:43:52.173 PracticeReachability[5494:2661290] Warning: Attempt to present on whose view is not in the window hierarchy!
I tried put
var myAlert = UIAlertController()
and
var myAlert :UIAlertController!
both doesn't make it work.
Question
My other Alerts work fine in same ViewController.
Why only this is not working?
And How can I make it work?

I don't think the view controller's view has been added to the screen yet in viewDidLoad. Try moving your code to viewDidAppear.

Related

How do I display an alert popup from another Class that is not a UIViewController?

I have the following Swift 3 code in a separate swift file in another class.
class Login{
func showAlert(message :String){
let alertController2 = UIAlertController(title: "Error", message: "A error occured when checking credentials, try again later.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController2.addAction(defaultAction)
self.present(alertController2, animated: true, completion: nil)
}
}
But I get a red error:
Use of unresolved identifier 'UIAlertController'
How can I create a popup informing the user that something went wrong?
First you need to import UIKit in order to make UIAlertController visible to your class.
This code will obtain the current view controller even if it's a modal.
func topViewController() -> UIViewController? {
guard var topViewController = UIApplication.shared.keyWindow?.rootViewController else { return nil }
while topViewController.presentedViewController != nil {
topViewController = topViewController.presentedViewController!
}
return topViewController
}
So you can now obtain the controller and present the alert on it:
topViewController()?.present(alertController2, animated: true, completion: nil)
Firstly, you need:
import UIKit
But your larger problem is that the present() method you're trying to use is a method of UIViewController objects, and also it only works on View Controllers whose view is already a part of the view hierarchy.
So I think you need to refactor your code a bit, and decide which view controller should launch your alert.
import Foundation
import UIKit
class Utility: NSObject{
func showAlert(_ VC : UIViewController, andMessage message: String , handler :#escaping(UIAlertAction) -> Void){
let alert = UIAlertController(title: "Error", message: message , preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style:UIAlertActionStyle.default, handler: handler))
VC.present(alert, animated: true, completion: nil)
}
}
Try this, this will work.

Swift UIAlertController disable return key without UITextField

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)
}

UIAlertController not working

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Initialize Alert View
let alertController = UIAlertController(title: "No Internet connection", message: "Please Connect to Internet", preferredStyle: .Alert)
let EXITAction = UIAlertAction(title: "EXIT", style: .Destructive) {(action) in
//...
exit(0)
}
alertController.addAction(EXITAction)
self.presentViewController(alertController, animated: true) {
// ...
}
}
I'm trying to use this for onLoad if use click then exit.
but nothing happen. Please help
(I am quite new in programming)
You have to move your code to present the UIAlertController to the viewDidAppear method.
If you put code that modifies the user interface in the viewDidLoad, it won't be applied to the views because the view controller is still loading.
Just declare a function like follows and you can call it in your viewDidAppear() method as alert("Message String").
func alert(info:String) {
let popUp = UIAlertController(title: "Title", message: info, preferredStyle: UIAlertControllerStyle.Alert)
popUp.addAction(UIAlertAction(title: "OK!", style: UIAlertActionStyle.Default, handler: {alertAction in
popUp.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(popUp, animated: true, completion: nil)
}

ViewController in other file

I'm a novice with Swift 2. I tried to create a UIAlertController in another file.
This is my code :
class my_view_error: UIViewController {
func my_error(my_title: String, my_message: String) {
let alertController = UIAlertController(title: my_title, message: my_message, preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in }
alertController.addAction(OKAction)
self.presentViewController(alertController, animated: true) {}
}
}
I'm receiving a compile time error:
Warning: Attempt to present on whose view is not in the window hierarchy!
My question is, is it possible to create a ViewController in a file other than ViewController.swift?
You created a UIViewController subclass called my_view_error. The UIViewController method presentViewController expects self (a my_view_error) to be on the screen at the time the method is called.
Your my_error function is perfectly fine, but it should be moved to a view controller that is actually on the screen. There is no need to create a UIViewController just to present a UIAlertController. In fact, UIAlertController is a UIViewController, and does not need help from a custom view controller.
Just like with any view controller, the view controller that is presenting the alert must be on the screen in order to perform the presentation.
Each view controller may have its own .swift file. There is no need to create one for a UIAlertController, however.
Heres a version of the function that uses rootViewController on UIApplication to get the currently on-screen view controller, and then uses that to present your alert:
func my_error(my_title: String, my_message: String) {
let alertController = UIAlertController(title: my_title, message: my_message, preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in }
alertController.addAction(OKAction)
// Uses UIApplication.sharedApplication().keyWindow!.rootViewController! instead of self
UIApplication.sharedApplication().keyWindow!.rootViewController!.presentViewController(alertController, animated: true) {}
}

My UIAlertView won't dismiss from MasterViewController of UISplitViewController

I have the following code in my MasterViewController:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(false);
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if((appDelegate.firstTime) != nil){
self.displayFirstTimeAlert()
}
}
It dutifully displays the alert:
func displayFirstTimeAlert(){
let message = "Please go to settings and set your preferred zipcode."
let alertView = UIAlertView(title: "Welcome", message: message, delegate: nil, cancelButtonTitle: "Dismiss")
alertView.show()
}
However when I touch Dismiss nothing happens? What is going on?
I don't know why the code you have above is not working, as I tested it and it does in fact dismiss. However, you shouldn't really be using UIAlertView any longer since it is deprecated... UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead
So try presenting the alert this way...
func displayFirstTimeAlert(){
let message = "Please go to settings and set your preferred zipcode."
var alert = UIAlertController(title: "Welcome", message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}

Resources