My UIAlertView won't dismiss from MasterViewController of UISplitViewController - ios

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

Related

UIAlert error, whose view is not in the window hierarchy

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.

UIAlertView' was deprecated in iOS 9.0

I have tried several ways to use UIAlertController,instead of UIAlertView, but I cannot make the alert go. Thanks in advance for any further suggestions. I am a newbie.
UIAlertView' was deprecated in iOS 9.0: UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead
Here is my code :
import MessageUI
class SecondViewController: UIViewController,MFMailComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sendmail(sender: UIButton) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self // Extremely important to set the --mailComposeDelegate-- property, NOT the --delegate-- property
mailComposerVC.setToRecipients(["blabla#gmail.com"])
mailComposerVC.setSubject("App Feedback")
mailComposerVC.setMessageBody("Feature request or bug report?", isHTML: false)
return mailComposerVC
}
func showSendMailErrorAlert() {
let sendMailErrorAlert = UIAlertView(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", delegate: self, cancelButtonTitle: "OK")
sendMailErrorAlert.show()
}
// MARK: MFMailComposeViewControllerDelegate Method
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
}
use UIAlertController
Here a example:
//Create the AlertController
let actionSheetController: UIAlertController = UIAlertController(title: "Alert", message: "Swiftly Now! Choose an option!", preferredStyle: .Alert)
//Create and add the Cancel action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
//Do some stuff
}
actionSheetController.addAction(cancelAction)
//Create and an option action
let nextAction: UIAlertAction = UIAlertAction(title: "Next", style: .Default) { action -> Void in
//Do some other stuff
}
actionSheetController.addAction(nextAction)
//Add a text field
actionSheetController.addTextFieldWithConfigurationHandler { textField -> Void in
//TextField configuration
textField.textColor = UIColor.blueColor()
}
//Present the AlertController
self.presentViewController(actionSheetController, animated: true, completion: nil)
Try something like this...
let sendMailErrorAlert = UIAlertController(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", preferredStyle: .Alert)
self.presentViewController(sendMailErrorAlert, animated: true, completion: nil)
let alertController = UIAlertController(title: "Could Not Send Email
", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", preferredStyle: .Alert)
Use UIAlertController
After initializing add actions to alertcontroller.
UIAlertCOntroller is subclass of UIViewController. So you can use self.presentViewController method show alert on current controller.
            
 

Go to previous controller in navigation stack (Swift)

I am trying to popViewController to the previous View Controller in the navigation stack after an alertView. As of now, my program will not run the popViewController method, since the alertView is in the way, and brings up the error:
UINavigationController 0x17670900 while an existing transition or presentation is occurring; the navigation stack will not be updated.
How do I go about running the popViewController method after the user clicks OK from the alertView? Do I have to set a delegate which detects when the used clicks OK?
Here is my code:
//alertView after Picture saved
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
self.presentViewController(alertView, animated: true, completion: nil)
//go to previous controller using popViewController, doesnt work, brings up error message
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
You need to pop the view controller when user presses the Ok button from AlertView.
let alertView = UIAlertController(title: "Success!", message: "Record Saved to Database", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "Ok", style: .Default) { (action) in
// pop here
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
}
alertView.addAction(OKAction)
self.present(alertView, animated: true, completion: nil)
You can put the "popViewControllerAction" inside an alert action like this.
func alertMethod() {
var okAlertController = UIAlertController(title: NSLocalizedString("Your title", comment: ""), message: "Your message", preferredStyle:
UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: NSLocalizedString("Ok", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action - navController.popViewControllerAnimated(true)
}
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: UIAlertActionStyle.Default) { (UIAlertAction) -> Void in
// your action
}
}
saveAlertController.addAction(okAction)
saveAlertController.addAction(cancelAction)
self.presentViewController(okAlertController, animated: true, completion: nil)
}
That should work, in that case the method gets called after the user presses a button...

Make a class comprises of the functions like UIAlertView, UIActivityIndicator and call them back in various viewControllers

This is my current code:
import UIKit
class classViewController: UIViewController {
// The function i want to call in other view controllers..
func alertView(title: String, message: String) {
var alert:UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
}
In the other view controller, where I've made an IBAction to perform this alertView, I have done this:
#IBAction func button(sender: AnyObject) {
classViewController().alertView("title", message: "message")
}
When I run the app, after tapping the button I get this error, but no alertView:
Warning: Attempt to present on
whose view is not in the
window hierarchy!
Right. If you want to make a global class that displays alerts, you need to pass in a reference to the current view controller, and use that instead of "self" in calls like presentViewController.
Your class should probably not be a subclass of UIViewController, since it looks like you're never displaying it to the screen.
I created a Utils class that is a subclass of NSObject.
It has a method showAlertOnVC that looks like this:
class func showAlertOnVC(targetVC: UIViewController?, var title: String, var message: String)
{
title = NSLocalizedString(title, comment: "")
message = NSLocalizedString(message, comment: "")
if let targetVC = targetVC
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okButton = UIAlertAction(
title:"OK",
style: UIAlertActionStyle.Default,
handler:
{
(alert: UIAlertAction!) in
})
alert.addAction(okButton)
targetVC.presentViewController(alert, animated: true, completion: nil)
}
else
{
println("attempting to display alert to nil view controller.")
println("Alert title = \(title)")
println("Alert message = \(message)")
}
}

iOS: How to present UIAlertController in iCloud Singleton? (Swift)

I'm creating a Singleton to manage my iCloud setup and configuration.
As part of the iCloud Design Guide the document states:
https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html
Listing 1-4 Inviting the user to use iCloud
if (currentiCloudToken && firstLaunchWithiCloudAvailable) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Choose Storage Option"
message: #"Should documents be stored in iCloud and
available on all your devices?"
delegate: self
cancelButtonTitle: #"Local Only"
otherButtonTitles: #"Use iCloud", nil];
[alert show];
}
I've converted this to a UIAlertController in Swift but how can I run self.presentViewController(alert, animated: true, completion: nil) from my singleton?
Obviously my singleton does not have a member named 'presentViewController'
Is there anyway to do this or do I need to setup a Post Notification, present the Alert somewhere else in my program and then save/retrieve the user's selection?
1) Add custom protocol delegate to your singleton, and this delegate will return UIViewController instance
protocol TestSingletonDelegate : NSObjectProtocol {
func responderViewControllerForTestSingleton(singleton: TestSingleton)->UIViewController
}
And in your class:
let delegate: TestSingletonDelegate
func presentAlertView() {
let alertView = UIAlertView();
if (self.delegate.respondsToSelector("responderViewControllerForTestSingleton:")) {
let viewController = self.delegate.responderViewControllerForTestSingleton(TestSingleton())
viewController.presentViewController(alertView, animated: YES, completion: nil)
}
}
2) Add instance var to your singleton class, and story UIViewController variable there
I had the same issue, I solved it in my case by simply returning the alertController to the singleton and then presenting it there.
In the AlertView Class I have the below code for a simple alert that can take the title and message as input and display's only one OK button to dismiss the alert:
func alert(#alertTitle: String, alertMessage: String) -> UIAlertController {
var alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .Alert)
var okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(okButton)
return alertController
}
Note that in the above method I am not presenting the alert controller to the view rather just returning it to whom ever is calling the method.
Then in the class where I called the method I am doing the below code:
** Just a note that the class where I am calling the alert is a ViewController in Objective-C. I'll provide swift code below as well**
// Creating an instance of the AlertView class and initializing it
AlertView *testAlert = [[AlertView alloc] init];
/* Creating a UIAlertController object and then calling the method I created in the AlertView class. This way the returned UIAlertController will be assigned to this UIAlertController
*/
UIAlertController *alertController = [testAlert alertWithAlertTitle:#"Genius!" alertMessage:#"Pure Genius"];
// Finally presenting the alert controller
[self presentViewController:alertController animated:true completion:nil];
NOTE: that I've found that you have to do this outside of ViewDidLoad. It doesn't work in ViewDidLoad and gives the below error:
Attempt to present <UIAlertController: 0x1555118f0> on <ViewController: 0x155509790> whose view is not in the window hierarchy!
Instead you can do this in viewDidAppear method.
Now Swift Version of ViewController:
// Created a function to show the alert
func showAlert() {
// Creating an instance of the AlertView class and initializing it
var testAlert : AlertView = AlertView()
/* Creating a UIAlertController object and then calling the method I created in the AlertView class. This way the returned UIAlertController will be assigned to this UIAlertController
*/
var alertController : UIAlertController = testAlert.alert(alertTitle: "Genius", alertMessage: "Pure Genius")
// Finally presenting the alert controller
self.presentViewController(alertController, animated: true, completion: nil)
}
One more thing if you are trying to show this alert in a Singleton outside of the ViewController then you can retrieve the top view controller as below and then present the alert controller to it:
Objective - C:
UIViewController *topViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[topViewController presentViewController:alertController animated:true completion:nil];
Swift:
if let topViewController = UIApplication.sharedApplication().keyWindow?.rootViewController? {
topViewController.presentViewController(alertController, animated: true, completion: nil)
}
class SharedDataSingleton {
init(){
//println("Hellow World")
}
var sample = "Hellow word"
func showAlertView(title alerTitle:String ,message alertMessage:String, preferredStyle style:UIAlertControllerStyle, okLabel: String, cancelLabel: String, targetViewController: UIViewController,okHandler: ((UIAlertAction!) -> Void)!, cancelHandler: ((UIAlertAction!) -> Void)!){
let alertController = UIAlertController(title: alerTitle, message: alertMessage, preferredStyle: style)
let okAction = UIAlertAction(title: okLabel, style: .Default, handler: okHandler)
let cancelAction = UIAlertAction(title: cancelLabel, style: .Default,handler: cancelHandler)
// Add Actions
alertController.addAction(okAction)
alertController.addAction(cancelAction)
// Present Alert Controller
targetViewController.presentViewController(alertController, animated: true, completion: nil)
}
}
let sharedDataSingletonInstance = SharedDataSingleton()
> Access the values like below
sharedDataSingletonInstance.showAlertView(title: "Sample",
message: "Sample",
preferredStyle: UIAlertControllerStyle.Alert,
okLabel: "Ok",
cancelLabel: "Cancel",
targetViewController: self,
okHandler: { (action) -> Void in
println("The user is not okay.")
},
cancelHandler: { (action) -> Void in
println("The user is not okay.")
})
}
> Global Variables can be also accessed anywhere in our project
sharedDataSingletonInstance.sample

Resources