Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
So I have written some code, which is supposed to open an app called MobilePay. The problem is that my code won't be accepted in SWIFT when i try to make a else stament. Can somebody tell me what is wrong? - SWIFT tells me that there is an error.
The error is that it expects somekind of expression
#IBAction func Invoker(sender: AnyObject) {
let alertController = UIAlertController(title: "Betal", message: "Vælg en af nedstående betalingsmulighed", preferredStyle: .ActionSheet)
let ok1 = UIAlertAction(title: "MobilePay", style: .Default, handler: { (action) -> Void in
let url = NSURL(string: "mobilepay://")
if UIApplication.sharedApplication().canOpenURL(url!) == true
{
UIApplication.sharedApplication().openURL(url!)
} else {
}
let cancel = UIAlertAction(title: "Annuller", style: .Destructive) { (action) -> Void in
}
alertController.addAction(ok1)
alertController.addAction(cancel)
presentViewController(alertController, animated: true, completion: nil)
}
}
Looks like your braces are messed up:
#IBAction func Invoker(sender: AnyObject)
{
let alertController = UIAlertController(title: "Betal", message: "Vælg en af nedstående betalingsmulighed", preferredStyle: .ActionSheet)
let ok1 = UIAlertAction(title: "MobilePay", style: .Default, handler: { (action) -> Void in
let url = NSURL(string: "mobilepay://")!
if UIApplication.sharedApplication().canOpenURL(url)
{
UIApplication.sharedApplication().openURL(url)
}
else
{
// Unable to open url
}
}) // You were missing this brace
let cancel = UIAlertAction(title: "Annuller", style: .Destructive) { (action) -> Void in
// Respond to the cancel action
}
alertController.addAction(ok1)
alertController.addAction(cancel)
presentViewController(alertController, animated: true, completion: nil)
}
// You had an extra brace here
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am new in swift. I have made generic actionsheet
import Foundation
extension UIAlertController{
func action(mes:String,tit:String,tit2:String,operation1:(),operation2:()) {
let actionSheet = UIAlertController(title: "", message:mes, preferredStyle: .actionSheet)
let EButton = UIAlertAction(title:tit ,
style: .default,
handler: { _ in
operation1
})
let AllEButton = UIAlertAction(title:tit2,
style: .default ,
handler:{ _ in
operation2
})
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil)
[EButton, AllEButton, cancelAction].forEach { $0.setValue(UIColor.red, forKey: "titleTextColor")
}
actionSheet.addAction(EButton)
actionSheet.addAction(AllEButton)
actionSheet.addAction(cancelAction)
present(actionSheet, animated: true, completion: nil)
}
}
I want to want to call this extension from viewControllerA
let actionView = UIAlertController()
class viewControllerA: UIViewController {}
private extension viewControllerA {
func alertBottomSheat() {
actionView.action(mes: "Update",tit: "Update only",tit2: "Update All", operation1:saveEvent(),operation2:saveEvent())
}
#IBAction func deleteEventButtonClicked(_ sender: Any) {
actionView.action(mes: "delete ",tit: "Delete only",tit2: "Delete All ",operation1:deleteEvent(),operation2:deleteEvent(deleteAll: true))
}
}
Q1- I this right way to call the extension from viewControllerA extension?
Q2- please tell me how to pass function in action function parameter using closure in this line?
actionView.action(mes: "delete ",tit: "Delete only",tit2: "Delete All ",operation1:deleteEvent(),operation2:deleteEvent(deleteAll: true))
and how to use closure in handler of action sheet in this line
let EButton = UIAlertAction(title:tit ,
style: .default,
handler: { _ in
operation1
})
You first need to create an extension for UIViewController instead of UIAlertController
Also, set the correct closure argument for the function and then call the function like this.
extension UIViewController {
func action(message: String, firstTitle: String, secondTitle: String, firstAction: (() -> Void)? = nil, secondAction: (() -> Void)? = nil) {
let actionSheet = UIAlertController(title: "", message: message, preferredStyle: .actionSheet)
let eButton = UIAlertAction(title: firstTitle ,
style: .default,
handler: {_ in firstAction?()})
let allEButton = UIAlertAction(title: secondTitle,
style: .default ,
handler: {_ in secondAction?()})
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil)
[eButton, allEButton, cancelAction].forEach { $0.setValue(UIColor.red, forKey: "titleTextColor")}
actionSheet.addAction(eButton)
actionSheet.addAction(allEButton)
actionSheet.addAction(cancelAction)
present(actionSheet, animated: true, completion: nil)
}
}
Usage
private extension viewControllerA {
func alertBottomSheat() {
self.action(message: "Update", firstTitle: "Update only", secondTitle: "Update All", firstAction: saveEvent, secondAction: saveEvent)
}
#IBAction func deleteEventButtonClicked(_ sender: Any) {
self.action(message: "delete ", firstTitle: "Delete only", secondTitle: "Delete All ", firstAction: { self.deleteEvent()}, secondAction: { self.deleteEvent(deleteAll: true) })
}
func saveEvent() {
}
func deleteEvent(deleteAll: Bool = false) {
}
}
Note: Fixed coding standard rule and var names.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to implement based on ActionSheet button click to show selected button title on main viewcontroller UILabel. Here, below code I am using but the label title not updating based on actionsheet button click.
The issue happening by for loop execution. UILabel.text not changing before last For Loop execution. how to handle and fix it?
ActionSheet
#IBAction func ClickAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData {
let action = UIAlertAction(title: title.status, style: .default) { (action) in
print("Title: \(title.status)")
print("Title: \(title.id)")
self.resultTitle.text = title.status // not updating here.
let icon = UIImage.init(named: title.icon)
action.setValue(icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}
Getting Output
Your issue not occured in my machine. Please restart your machine, maybe problem will resolve.
You need to make the checks with action title not with the id. So, here is you solution that is working fine:
struct ActionOption {
var id: String
var title: String
var icon: UIImage?
static func getAll() -> [ActionOption] {
let titleData = ["Red", "Green", "Yellow"]
var all: [ActionOption] = []
for (idx, ttl) in titleData.enumerated() {
all.append(ActionOption(id: "\(idx)", title: ttl, icon: nil))
}
return all
}
}
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var titleData: [ActionOption] = []
override func viewDidLoad() {
super.viewDidLoad()
self.titleData = ActionOption.getAll()
}
#IBAction func changeAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData {
let action = UIAlertAction(title: title.title, style: .default) { (action) in
switch (action.title ?? "") { // you need to vhange your code here
case "Red" :
self.imageView.backgroundColor = UIColor.red
case "Green" :
self.imageView.backgroundColor = UIColor.green
case "Yellow" :
self.imageView.backgroundColor = UIColor.yellow
default : self.imageView.backgroundColor = UIColor.black
}
}
action.setValue(title.icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}
}
You need to make some changes in you switch statement, use the parameter closure for deciding the desired action to perform. As these closure will call when the action being perform and that time title for loop object will not be present/available for being used.
Result As of Code:
Just put self.resultTitle.text = title.status inside DispatchQueue.main.async { }
#IBAction func ClickAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData { // I thik this is the plm
let action = UIAlertAction(title: title.status, style: .default) { (action) in
print("Title: \(title.status)")
print("Title: \(title.id)")
DispatchQueue.main.async {
self.resultTitle.text = title.status
}
}
let icon = UIImage.init(named: title.icon)
action.setValue(icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}
I would like to add a method to my ViewController that shows a message with text as an alert with a Yes and a No button. The result should be of type Bool (Yes/No).
What I have tried is the following:
func YesNoBox(msg: String) -> Bool
{
var retVal = false
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in NSLog("The \"Yes\" alert occured."); retVal = true })
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in NSLog("The \"No\" alert occured."); retVal = false })
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
return retVal
}
However, the value of retVal is always false. If I was in C/C++, I guess I could resolve this issue with a pointer, but this is Swift (and I am pretty new to this).
Any idea anyone how I could get this working?
EDIT: The problem that I have is the following. On a ViewController I have a TextField. When I tap on the text field, the app should ask the user whether they want to paste the text from the clipboard. If yes, paste, otherwise give the TextField the focus (i.e. let the cursor blink in it). I tried to do this with 'textFieldShouldBeginEditing' and in this method I display the YesNoBox. The problem is that the TextField never gets the focus after the YesNoBox is closed. And when I use 'becomeFirstResponder()' after the Box call, the app freezes. I don't know what to do?
Use a completion
func yesNoBox(msg: String,completion:#escaping(Bool) -> ())
{
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in
NSLog("The \"Yes\" alert occured.");
completion(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in
NSLog("The \"No\" alert occured.");
completion(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
call
yesNoBox(msg:"someMessage") { yes in
if yes {
// do yes action
}
else {
// do no action
}
}
2 Callbacks:
This function has 2 completions ( imagine we have a function that uploads an image and notifies the progress with a completion and another 1 to say done )
func uploadImage(data: Data,progress:#escaping(Float) -> (),completion:#escaping(Bool) -> ()) {
// implementation here
}
To call
self.uploadImage(someData) { progress in
print(progress)
}) { done in
print(done)
}
This can be achieved with completion handlers.
func showAlertWithOptions(title: String, message: String, completionHandler: #escaping (Bool) -> Void) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler: { _ in
completionHandler(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler: { _ in
completionHandler(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
Now call the function and add any other functions or actions that you want to perform depending on the action selected.
showAlertWithOptions(title: "Any title", message: "Any message") { success in
if success {
NSLog("The \"Yes\" alert occured.")
} else {
NSLog("The \"No\" alert occured.")
}
}
This question already has an answer here:
Cropped characters - iOS11 - Alert Dialog
(1 answer)
Closed 4 years ago.
Cropped characters - iOS11 - Alert Dialog. How to fix it?
Does anyone know the reason why this is happening?
func settingsButtonPressed() {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let closeAction = UIAlertAction(title: "Anuluj", style: .cancel) { (action) in
}
alert.addAction(closeAction)
let restorePurchases = UIAlertAction(title: "Przywróć zakupy", style: .default) { (action) in
self.restorePurchases()
}
alert.addAction(restorePurchases)
let refreshCatalogs = UIAlertAction(title: "Odśwież", style: .default) { (action) in
self.collectionView.reloadData()
}
alert.addAction(refreshCatalogs)
let delPubs = UIAlertAction(title: "Usuń publikacje", style: .destructive) { (action) in
self.deletePublications()
}
alert.addAction(delPubs)
present(alert, animated: true, completion: nil)
}
Can't reproduce. I ran your exact same code (minus the calls in the handlers, of course) and this is what I see:
My suggestion would be: try just this part of your code in a plain vanilla project, just to persuade yourself that this should work. Then start thinking about how your real app is different. Perhaps you are messing with fonts or appearance in a way that causes this issue.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
My iOS app requires a customized group of alerts with similar functionality. Can I pack those in a class, so I don't have to copy paste in every UIViewController?
func displayAlert(msg:String, handler: (UIAlertAction) -> Void){...}
func successMsg (msg: String){...}
func failMsg(msg: String){...}
I was trying to pack them into a subclass(AlertViewController) of UIViewController, but then there was runtime error:"Attempt to present <...UIAlertController...> on <...UIAlertController...> whose view is not in the window hierachy!"
code in myViewController:
#IBAction func leave() {
let date = getDate()
let datePresent = dateForPresent()
if stID == nil || name == nil {
return
} else {
alert.displayAlert("\(datePresent)"){action in
self.request.getResult(self.request.leavePara(self.stID!, date: date, name: self.name!) ){ (result) in
dispatch_async(dispatch_get_main_queue(), {
let flag = result["result","out_Flag"].int
print(result)
let msg = result["result","out_nszRtn"].string!
if flag == 0 {
self.alert.successMsg(msg){ action in
self.performSegueWithIdentifier("personUnwind", sender: self)
}
}else {
self.alert.failMsg(msg)
}
})
}
}
}
}
Please use this code.
func displayAlertWithMessage(title: String, message: string){
let ac = UIAlertController(title: title, message: message, preferredStype: .Alert)
ac.addAction(UIAlertAction(title:"OK", style: .Default, handler: nil))
let rootVC = UIApplication.sharedApplication().keyWindow?.rootViewController
rootVC?.presentViewController(ac, animated: true){}
}
If you want to display alert for specific view controller you can use this function.
func displayAlertWithMessage(viewController: UIViewController, title: String, message: string){
let ac = UIAlertController(title: title, message: message, preferredStype: .Alert)
ac.addAction(UIAlertAction(title:"OK", style: .Default, handler: nil))
viewController.presentViewController(ac, animated: true){}
}
And you can call it function with this code.
displayAlertWithMessage(self, animated: true, completion: nil)
I'm not sure what the error you were getting was about, but if you want to avoid a subclass you could implement a UIAlertViewController initializer that returns an object customized to your needs.
For example, the following could be written at a global level:
extension UIAlertController {
enum AlertMessageID {
case SaveFailed
}
convenience init(messageID: AlertMessageID) {
switch messageID {
case .SaveFailed:
self.init(title: "Oops", message: "The save failed.", preferredStyle: .Alert)
}
let okayButton = UIAlertAction(title: "Okay", style: .Default, handler: nil)
self.addAction(okayButton)
}
}