How can I pass a controller to a function - ios

Hello I have a utility class in which I have declared AlertViewFunction like this
func displayAlertMessage(userMessage: String,//controller){
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated: true, completion: nil)
}
The problem is I can't use self here
self.presentViewController(myAlert, animated: true, completion: nil)
I want to pass a controller to this function so I can use like this
controller.presentViewController(myAlert, animated: true, completion: nil)
How Can I pass a controller from any ViewController. Lets say If I am in LoginViewController
Utility().displayAlertMessage(Message.INTERNETISNOTCONNECTED,//controller)

Utility().displayAlertMessage(Message.INTERNETISNOTCONNECTED, controller: self)
and
func displayAlertMessage(userMessage: String, controller: UIViewController)
{
controller?.presentViewController(myAlert, animated: true, completion: nil)
}

pass in the view controller as an argument to the function.
func displayAlertMessage(controller: UIViewController, title: String, message: String?) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(okAction)
controller.presentViewController(alert, animated: false, completion: nil)
}
Alternatively you can even return the alert to the caller of the function for further customization by saying:
func displayAlertMessage(title: String, message: String?) -> UIAlertController {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(okAction)
return alert
}
class controller: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let alert = displayAlertMessage("title", message: nil)
presentViewController(alert, animated: true, completion: nil)
}
}

Related

Add an alertcontroller in a global swift file? [duplicate]

This question already has answers here:
how to create an alert in a swift file model that works for various view controller
(2 answers)
Closed 4 years ago.
I am trying to create a alert box inside the swift file other than the UIViewController file. but I could not create it.
extension NetworkManager {
func showAlert(message: String,from:UIViewController, title: String = "") {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
from.present(alertController, animated: true, completion: nil)
}
}
the above code is for implementing alertcontroller but I don't know how to pass the view controller I need to present so need assistance.
extension UIViewController {
func showAlert(message: String, title: String = "") {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
}
and use like this
from.showAlert(message:"Your message", title: "Title")
Add a Utilities class in your project.
class Utilities {
static func showSimpleAlert(OnViewController vc: UIViewController, Message message: String) {
//Create alertController object with specific message
let alertController = UIAlertController(title: "App Name", message: message, preferredStyle: .alert)
//Add OK button to alert and dismiss it on action
let alertAction = UIAlertAction(title: "OK", style: .default) { (action) in
alertController.dismiss(animated: true, completion: nil)
}
alertController.addAction(alertAction)
//Show alert to user
vc.present(alertController, animated: true, completion: nil)
}
}
Usage:
Utilities.showSimpleAlert(OnViewController: self, Message: "Some message")
Here is the extension I made. It allows to show either Alert or Action sheet and allows multiple actions "from the box"
extension UIViewController {
func presentAlert(title: String?, message: String, actions: UIAlertAction..., animated: Bool = true) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
actions.forEach { alert.addAction($0) }
self.present(alert, animated: animated, completion: nil)
}
func presentActionSheet(title: String?, message: String, actions: UIAlertAction..., animated: Bool = true) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
actions.forEach { alert.addAction($0) }
self.present(alert, animated: animated, completion: nil)
}
}
Usage
let delete = UIAlertAction(title: "Delete", style: .destructive, handler: { _ in /* Your code here */})
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
presentAlert(title: .albumPreferencesDeleteAlertTitle, message: "Very important message", actions: delete, cancel)
This is the more generalise method to show alert on view controller
func showAlert(msg: String, inViewController vc: UIViewController, actions: [UIAlertAction]? = nil, type: UIAlertControllerStyle = .alert, title: String = kAppName) {
let alertType: UIAlertControllerStyle = .alert
let alertTitle = kAppName
let alertVC = UIAlertController(title: alertTitle, message: msg, preferredStyle: alertType)
if let actions = actions {
for action in actions {
alertVC.addAction(action)
}
} else {
let actionCancel = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertVC.addAction(actionCancel)
}
vc.present(alertVC, animated: true, completion: nil)
}
Usage
AppUtilities.showAlert(msg: "Test msg", inViewController: self) //for alert
AppUtilities.showAlert(msg: "Test msg", inViewController: self, actions: [okAction, cancelAction]) //for alert
AppUtilities.showAlert(msg: "Test Msg", inViewController: self, type: .actionSheet) //shows action sheet
You can add this function in extension or create a separate utility class as you want.

Swift: UIAlert in function - Use of unresolved identifier 'present'

I'm trying to limit the show of code so I just want to call function containing two strings to create a uialert faster with 1 line instead of 5/
The error I'm getting
Use of unresolved identifier 'present'
at the line
present(alert, animated: true, completion: nil)
// Controlling Alerts for Errors
func showAlert(titleString: String, messageString: String) {
// Alert to go to Settings
let alert = UIAlertController(title: titleString, message: messageString, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: { _ in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
In the comments, you explained that this is a stand-alone function. It should work if you make it an extension to UIViewController, for instance:
extension UIViewController {
public func showAlert(_ title:String, _ message:String) {
let alertVC = UIAlertController(
title: title,
message: message,
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style: .cancel,
handler: { action -> Void in
})
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
}
And to call it in a UIViewController:
showAlert(
"Could Not Send Email",
"Your device could not send e-mail. Please check e-mail configuration and try again."
)

swift3 call alert function from other swift.file

I am new of swift3. Now, I am finding a way to call alert function from other swift.file
Like this:
//MainView.swift
//Call function
AlertFun.ShowAlert(title: "Title", message: "message..." )
//Another page for storing functions
//Function.swift
public class AlertFun {
class func ShowAlert(title: String, message: String ) {
let alert = UIAlertController(title: tile, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
Problem in here...Cannot do this in this way....
self.present(alert, animated: true, completion: nil)
How can I implement it? Thanks.
Pass the viewController reference as a parameter to the showAlert function like:
//MainView.swift
//Call function
AlertFun.ShowAlert(title: "Title", message: "message...", in: self)
//Another page for storing functions
//Function.swift
public class AlertFun {
class func ShowAlert(title: String, message: String, in vc: UIViewController) {
let alert = UIAlertController(title: tile, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
vc.present(alert, animated: true, completion: nil)
}
}
Call Method for your controller
Utility.showAlertOnViewController(targetVC: self, title: "", message:"")
Your Class
class Utility: NSObject {
class func showAlertOnViewController(
targetVC: UIViewController,
title: String,
message: String)
{
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.present(alert, animated: true, completion: nil)
}
}
I found that none of the examples I've seen will work without getting the warning:
Attempt to present <UIAlertController: 0x7f82d8825400> on <app name> whose view is not in the window hierarchy!
The code that works for me is as follows. The function call is as before:
AlertFun.ShowAlert(title: "Title", message: "message...", in: self)
However, to make this work, the Function.swift file has to display the alert inside the DispatchQueue.main.async. So the Function.swift file should look like this:
public class AlertFun
{
class func ShowAlert(title: String, message: String, in vc: UIViewController)
{
DispatchQueue.main.async
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
vc.present(alert, animated: true, completion: nil)
}
}
}

How to open another view controller when OK is pressed in alert.addAction in iOS 9

I want to display a viewcontroller called InViewController, when the "OK" from the add.alertAction is pressed.
if ((user) != nil) {
let alert = UIAlertController(title: "Success", message: "Logged In", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
self.presentViewController(alert, animated: true){}
}
let alert = UIAlertController(title: "Success", message: "Logged In", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { (action) -> Void in
let viewControllerYouWantToPresent = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewControllerIdentifier")
self.presentViewController(viewControllerYouWantToPresent!, animated: true, completion: nil)
}
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
You can add a completionHandler to the UIAlertAction when you add it to do it what you want, like in the following way:
if ((user) != nil) {
let alert = UIAlertController(title: "Success", message: "Logged In", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "OK", style: .Default, handler: { _ -> Void in
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerA") as! ViewControllerA
self.presentViewController(nextViewController, animated: true, completion: nil)
})
alert.addAction(OKAction)
self.presentViewController(alert, animated: true){}
}
To set the StoryboardID you can use Interface Builder in the Identity Inspector, see the following picture:
I put everything in the above code referencing ViewControllerA, you have to set the name of your UIViewController according what you want.
EDIT:
You are pointing to a UIView or some other object on the StoryBoard. Press the yellow indicator on top of the other objects which is your UIViewController, like in the following picture:
I hope this help you.
Here's how you can do that ,
I'm just updating the good work of Victor Sigler
you follow his answer with this little update ..
private func alertUser( alertTitle title: String, alertMessage message: String )
{
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let actionTaken = UIAlertAction(title: "Success", style: .default) { (hand) in
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "IntroPage") as? StarterViewController
self.present(destinationVC!, animated: true, completion: nil)
}
alert.addAction(actionTaken)
self.present(alert, animated: true) {}
}

UIActionSheet crashes on iPad swift

I have the following button action in a toolbar:
#IBAction func share(sender: AnyObject) {
let modifiedURL1 = "http://www.declassifiedandratified.com/search.html?q=\(self.searchBar.text)"
let modifiedURL = modifiedURL1.stringByReplacingOccurrencesOfString(" ", withString: "%20", options: NSStringCompareOptions.LiteralSearch, range: nil)
let alert = UIAlertController(title: "Share", message: "Share your findings", preferredStyle: UIAlertControllerStyle.ActionSheet)
let twBtn = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default) { (alert) -> Void in
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter){
var twitterSheet:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
twitterSheet.setInitialText("Look what I found on Declassified and Ratified: \(modifiedURL)")
self.presentViewController(twitterSheet, animated: true, completion: nil)
} else {
var alert = UIAlertController(title: "Accounts", message: "Please login to a Twitter account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
let fbBtn = UIAlertAction(title: "Facebook", style: UIAlertActionStyle.Default) { (alert) -> Void in
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook){
var facebookSheet:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
facebookSheet.setInitialText("Look what I found on Declassified and Ratified: \(modifiedURL)")
self.presentViewController(facebookSheet, animated: true, completion: nil)
} else {
var alert = UIAlertController(title: "Accounts", message: "Please login to a Facebook account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
let safariBtn = UIAlertAction(title: "Open in Safari", style: UIAlertActionStyle.Default) { (alert) -> Void in
let URL = NSURL(string: modifiedURL)
UIApplication.sharedApplication().openURL(URL!)
}
let cancelButton = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (alert) -> Void in
println("Cancel Pressed")
}
let textBtn = UIAlertAction(title: "Message", style: UIAlertActionStyle.Default) { (alert) -> Void in
if (MFMessageComposeViewController.canSendText()) {
let controller = MFMessageComposeViewController()
controller.body = "Look what I found on Declassified and Ratified: \(modifiedURL)"
controller.messageComposeDelegate = self
self.presentViewController(controller, animated: true, completion: nil)
}
}
alert.addAction(twBtn)
alert.addAction(fbBtn)
alert.addAction(safariBtn)
alert.addAction(textBtn)
alert.addAction(cancelButton)
self.presentViewController(alert, animated: true, completion: nil)
}
However, this code crashes when called on an iPad with a sigbart crash (that is all I can see in the console). I see this is a common problem but the other solutions have not worked for me. I even set the version to the latest iOS and that didn't fix it. Can someone explain?
On an iPad, an action sheet is a popover. Therefore you must give its UIPopoverPresentationController a sourceView and sourceRect, or barButtonItem, so that it has something to attach its arrow to.

Resources