In Swift 5, How to execute actions successively in UIAlert? - swift

I have created an alert Where a mybutton have to be hidden while the activity indicator has to be shown. but it didn't work.
Here is the code:
private func showAlert() {
let alert = UIAlertController(title: "aaaaaa", message: ccccccccc, preferredStyle: .alert)
let attributedString = NSAttributedString(string: "aaaaa", attributes: [.font: UIFont.boldSystemFont(ofSize: 18), //your font here
.foregroundColor : Theme.bleu!])
alert.setValue(attributedString, forKey: "attributedTitle")
alert.addAction(UIAlertAction(title: annuler, style: .cancel))
alert.addAction(UIAlertAction(title: optimiserLesMicrosUniquement, style: .default, handler: { (action) in
self.myButton.isHidden = true // Here begins the problem
self.activityIndicator.isHidden = false
let menuOptimiser = functionNumberX()
self.activityIndicator.isHidden = true // Here is the problem
self.myButton.isHidden = false
let reponse = menuOptimiser.0
if reponse == false {
self.showAlerteMenuOptimal()
} else {
if menuOptimiser.1 > 0 {
self.presentAlerteDuGain(gain: menuOptimiser.1, menu: menuOptimiser.2)
} else {
self.presentAlerteOptimisationSansGainDeCalories(calorie: abs((round(menuOptimiser.1))), menu: menuOptimiser.2)
}
}
self.gestionDeLaNotationDuMenuEnCours()
}))
present(alert, animated: true)
}
When i execute it, mybutton never disappears, and activity indicator never appears.
i don't know how to do that.

try removing, these two lines , since you are opposite at almost the same time .
self.activityIndicator.isHidden = true // Here is the problem
self.myButton.isHidden = false

I just found a solution. Here is the code
var menuOptimiser : (Bool, Float, [[AlimentObject]])!
private func showAlert() {
let alert = UIAlertController(title: "aaaaaa", message: ccccccccc, preferredStyle: .alert)
let attributedString = NSAttributedString(string: "aaaaa", attributes: [.font: UIFont.boldSystemFont(ofSize: 18), //your font here
.foregroundColor : Theme.bleu!])
alert.setValue(attributedString, forKey: "attributedTitle")
alert.addAction(UIAlertAction(title: annuler, style: .cancel))
alert.addAction(UIAlertAction(title: optimiserLesMicrosUniquement, style: .default, handler: { (action) in
self.myButton.isHidden = true // Here begins the problem
self.activityIndicator.isHidden = false
DispatchQueue.main.asyncAfter(deadline: .now()) {
let menuOptimiser = functionNumberX()
self.activityIndicator.isHidden = true // Here is the problem
self.myButton.isHidden = false
let reponse = menuOptimiser.0
if reponse == false {
self.showAlerteMenuOptimal()
} else {
if menuOptimiser.1 > 0 {
self.presentAlerteDuGain(gain: menuOptimiser.1, menu: menuOptimiser.2)
} else {
self.presentAlerteOptimisationSansGainDeCalories(calorie: abs((round(menuOptimiser.1))), menu: menuOptimiser.2)
}
}
}
self.gestionDeLaNotationDuMenuEnCours()
}))
present(alert, animated: true)
}

Related

swift how change UIAlertController font

When I added an extension to UIAlertController to modify actions fonts, it didn't seem to work. What should I do to modify the Action font。
Here is my code
extension UIAlertController {
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if self.preferredStyle == .actionSheet {
for i in self.actions {
let attributedText = NSAttributedString(string: i.title ?? "", attributes: [NSAttributedString.Key.font : UIFont(name: "SFProText-Semibold", size: 15.0)!])
guard let label = (i.value(forKey: "__representer") as AnyObject).value(forKey: "label") as? UILabel else { return }
label.attributedText = attributedText
}
}
}
}
Create an extension of UIAlertController
extension UIAlertController {
func setBackgroudColor(color: UIColor) {
if let bgView = self.view.subviews.first,
let groupView = bgView.subviews.first,
let contentView = groupView.subviews.first {
contentView.backgroundColor = color
}
}
func setTitle(font: UIFont?, color: UIColor?) {
guard let title = self.title else { return }
let attributeString = NSMutableAttributedString(string: title)
if let titleFont = font {
attributeString.addAttributes([NSAttributedString.Key.font : titleFont],
range: NSMakeRange(0, title.utf8.count))
}
if let titleColor = color {
attributeString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor],
range: NSMakeRange(0, title.utf8.count))
}
self.setValue(attributeString, forKey: "attributedTitle")
}
func setMessage(font: UIFont?, color: UIColor?) {
guard let title = self.message else {
return
}
let attributedString = NSMutableAttributedString(string: title)
if let titleFont = font {
attributedString.addAttributes([NSAttributedString.Key.font : titleFont], range: NSMakeRange(0, title.utf8.count))
}
if let titleColor = color {
attributedString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor], range: NSMakeRange(0, title.utf8.count))
}
self.setValue(attributedString, forKey: "attributedMessage")
}
func setTint(color: UIColor) {
self.view.tintColor = color
}
}
Call it from a UIViewController may be in a button action like below.
func tapShowAlert() {
let alertController = UIAlertController(title: "Alert!!", message: "This is custom alert message", preferredStyle: .alert)
alertController.setTitle(font: UIFont.boldSystemFont(ofSize: 24), color: UIColor.yellow)
alertController.setMessage(font: UIFont(name: "Verdana", size: 16), color: UIColor.red)
let actnOk = UIAlertAction(title: "Ok", style: .default, handler: nil)
let actnCancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alertController.addAction(actnOk)
alertController.addAction(actnCancel)
self.present(alertController, animated: true, completion: nil)
}

Set title label of two action sheet buttons

when i choose an option from action sheet, it set a title label to button. But when i click another button with another action sheet, it cancel title label of first button. How can i set each button without cancel any title label?
This is how it works:
This is my code of two action sheets:
#IBAction func paymentMethodActionSheet(_ sender: Any) {
PaymentMethodTitle.titleLabel?.text = "Seleziona"
let optionMenu = UIAlertController(title: nil, message: "Scegli il metodo di pagamento", preferredStyle: .actionSheet)
let cardAction = UIAlertAction(title: "Paga con carta", style: .default, handler: { action in
self.PaymentMethodTitle.titleLabel?.text = "Paga con carta"
self.PaymentMethodTitle.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let contantiAction = UIAlertAction(title: "Contanti", style: .default, handler: { action in
self.PaymentMethodTitle.titleLabel?.text = "Contanti"
self.PaymentMethodTitle.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let cancelAction = UIAlertAction(title: "Cancella", style: .cancel)
optionMenu.addAction(cardAction)
optionMenu.addAction(contantiAction)
optionMenu.addAction(cancelAction)
if let popoverController = optionMenu.popoverPresentationController {
popoverController.barButtonItem = sender as? UIBarButtonItem
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []
}
self.present(optionMenu, animated: true, completion: nil)
}
#IBAction func shippingMethodActionSheet(_ sender: Any) {
shippingMethodTitle.titleLabel?.text = "Seleziona"
let option2Menu = UIAlertController(title: nil, message: "Scegli l'opzione d'acquisto", preferredStyle: .actionSheet)
let houseAction = UIAlertAction(title: "Consegna a domicilio", style: .default, handler: { action in
self.shippingMethodTitle.titleLabel?.text = "Consegna a domicilio"
self.shippingMethodTitle.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let businessAction = UIAlertAction(title: "Ritiro presso attività", style: .default, handler: { action in
self.shippingMethodTitle.titleLabel?.text = "Ritiro presso attività"
self.shippingMethodTitle.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let cancel2Action = UIAlertAction(title: "Cancella", style: .cancel)
option2Menu.addAction(houseAction)
option2Menu.addAction(businessAction)
option2Menu.addAction(cancel2Action)
if let popoverController2 = option2Menu.popoverPresentationController {
popoverController2.barButtonItem = sender as? UIBarButtonItem
popoverController2.sourceView = self.view
popoverController2.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController2.permittedArrowDirections = []
}
self.present(option2Menu, animated: true, completion: nil)
}
Instead of using self.PaymenMethodTitle?.titleLabel.text = "Contanti"to change the button title inside closure, just Use self.PaymentMethodTitle.setTitle("Contanti", for: .normal).
I've tried it myself and Its working Fine.
Code:
class ViewController: UIViewController {
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btn1Pressed(_ sender: Any) {
let optionMenu = UIAlertController(title: nil, message: "Scegli il metodo di pagamento", preferredStyle: .actionSheet)
let cardAction = UIAlertAction(title: "Paga con carta", style: .default, handler: { action in
self.btn1.setTitle("Paga con carta", for: .normal)
self.btn1.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let contantiAction = UIAlertAction(title: "Contanti", style: .default, handler: { action in
self.btn1.setTitle("Conati", for: .normal)
self.btn1.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let cancelAction = UIAlertAction(title: "Cancella", style: .cancel)
optionMenu.addAction(cardAction)
optionMenu.addAction(contantiAction)
optionMenu.addAction(cancelAction)
if let popoverController = optionMenu.popoverPresentationController {
popoverController.barButtonItem = sender as? UIBarButtonItem
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []
}
self.present(optionMenu, animated: true, completion: nil)
}
#IBAction func btn2Pressed(_ sender: Any) {
let option2Menu = UIAlertController(title: nil, message: "Scegli l'opzione d'acquisto", preferredStyle: .actionSheet)
let houseAction = UIAlertAction(title: "Consegna a domicilio", style: .default, handler: { action in
self.btn2.setTitle("Consegna a domicilio", for: .normal)
self.btn2.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let businessAction = UIAlertAction(title: "Ritiro presso attività", style: .default, handler: { action in
self.btn2.setTitle("Ritiro presso attività", for: .normal)
self.btn2.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.right
})
let cancel2Action = UIAlertAction(title: "Cancella", style: .cancel)
option2Menu.addAction(houseAction)
option2Menu.addAction(businessAction)
option2Menu.addAction(cancel2Action)
if let popoverController2 = option2Menu.popoverPresentationController {
popoverController2.barButtonItem = sender as? UIBarButtonItem
popoverController2.sourceView = self.view
popoverController2.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController2.permittedArrowDirections = []
}
self.present(option2Menu, animated: true, completion: nil)
}
}
Simulator ScreenShot:

Multiple UITextFields not displaying properly inside an UIAlertController

I need to display 4 UITextFields in an UIAlertController (Xcode 11.5). Did it as usual but the center UITextFields appear w/o border view image and it doesn't look well (I am adding a screenshot). I tried to set the UITextField Borderstyle, frame, but I can't get it right.
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var dayOfWeekField = UITextField()
var inicioTextField = UITextField()
var terminoTextField = UITextField()
var numeroDeCirugias = UITextField()
let alert = UIAlertController(title: "Agregar Nuevo Bloque", message: "", preferredStyle: .alert)
let action = UIAlertAction(title: "Agregar", style: .default) { (action) in
let nuevoBloque = Bloques(context: self.context)
nuevoBloque.dia = dayOfWeekField.text!
nuevoBloque.inicio = inicioTextField.text!
nuevoBloque.termino = terminoTextField.text!
nuevoBloque.cirugias = Int16(numeroDeCirugias.text!)!
self.bloques.append(nuevoBloque)
self.saveBloques()
}
alert.addAction(action)
alert.addAction(UIAlertAction(title: "Cancelar", style: .destructive, handler: nil))
alert.addTextField { (field) in
dayOfWeekField = field
dayOfWeekField.placeholder = "dia de la semana"
dayOfWeekField.autocapitalizationType = .none
}
alert.addTextField { (field2) in
inicioTextField = field2
inicioTextField.placeholder = "Inicio Bloque (HH:MM)"
inicioTextField.keyboardType = .numbersAndPunctuation
}
alert.addTextField { (field3) in
terminoTextField = field3
terminoTextField.placeholder = "Término Bloque (HH:MM)"
terminoTextField.keyboardType = .numbersAndPunctuation
}
alert.addTextField { (field4) in
numeroDeCirugias = field4
numeroDeCirugias.placeholder = "Número Cirugías"
numeroDeCirugias.keyboardType = .numberPad
}
present(alert, animated: true, completion: nil)
}[enter image description here][1]
Try this solution. I suggest to not capture references to the UITextfields, maybe that might have caused the behavior. You can Access them by UIAlertController.textFields property. Usually all layouting is done by the UIAlertController basically fine, I never encountered bugs there.
Also. try to avoid force unwrapping with ! by using guard let
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "Agregar Nuevo Bloque", message: "", preferredStyle: .alert)
let action = UIAlertAction(title: "Agregar", style: .default) { (_) in
let nuevoBloque = Bloques(context: self.context)
guard
let dayOfWeek = alert.textFields?[0].text,
let inicio = alert.textFields?[1].text,
let temino = alert.textFields?[2].text,
let numeroDeCirugiasString = alert.textFields?[3].text,
let numeroDeCirugias = Int(numeroDeCirugiasString)
else {
// not all textfields were implemented or filled out properly
return
}
nuevoBloque.dia = dayOfWeek
nuevoBloque.inicio = inicio
nuevoBloque.termino = termino
nuevoBloque.cirugias = numeroDeCirugias
self.bloques.append(nuevoBloque)
self.saveBloques()
}
alert.addAction(action)
alert.addAction(UIAlertAction(title: "Cancelar", style: .cancel, handler: nil))
alert.addTextField { (field) in
field.placeholder = "dia de la semana"
field.autocapitalizationType = .none
}
alert.addTextField { (field2) in
field2.placeholder = "Inicio Bloque (HH:MM)"
field2.keyboardType = .numbersAndPunctuation
}
alert.addTextField { (field3) in
field3.placeholder = "Término Bloque (HH:MM)"
field3.keyboardType = .numbersAndPunctuation
}
alert.addTextField { (field4) in
field4.placeholder = "Número Cirugías"
field4.keyboardType = .numberPad
}
present(alert, animated: true, completion: nil)
}
EDIT:
Image of the Solution implemented by OP:

UIButton not highlighting or running code when clicked

I'm setting up 26 buttons, adding them as subviews to a letterButtonLabel, and appending them to an letterButtons array.
for row in 0..<6 {
for column in 0..<5 {
if row == 5 && column > 0 { continue }
let letterButton = UIButton(type: .system)
letterButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
letterButton.setTitle("O", for: .normal)
letterButton.addTarget(self, action: #selector(letterTapped), for: .touchUpInside)
let frame = CGRect(x: width * column, y: height * row, width: width, height: height)
letterButton.frame = frame
letterButtonLabel.addSubview(letterButton)
letterButtons.append(letterButton)
}
}
Afterwards, I assign a letter to each button using the letterButtons array.
var index = 0
for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
letterButtons[index].setTitle("\(letter)", for: .normal)
index += 1
}
I then manually add layout constraints.
Here is the functionality for each button:
#objc func letterTapped(_ sender: UIButton) {
// check the letter and react
sender.isHidden = true
guard let word = currentWord else { return }
guard var charactersArray = currentWordField.text?.components(separatedBy: "") else { return }
guard let originalCurrentWordField = currentWordField.text else { return }
for (index, letter) in word.enumerated() {
let strLetter = String(letter)
if strLetter == sender.titleLabel?.text {
charactersArray[index] = strLetter
}
}
currentWordField.text = charactersArray.joined()
if currentWordField.text == originalCurrentWordField {
livesLeft -= 1
}
if wordBank.contains(word) {
// you got it! reset letters
level += 1
let ac = UIAlertController(title: "Good job!", message: nil, preferredStyle: .alert)
let action = UIAlertAction(title: "Continue", style: .default, handler: resetForNextLevel)
ac.addAction(action)
present(ac, animated: true)
}
if livesLeft == 0 {
let ac = UIAlertController(title: "Game Over", message: nil, preferredStyle: .alert)
let action = UIAlertAction(title: "Restart", style: .default, handler: resetForNextLevel)
ac.addAction(action)
present(ac, animated: true)
}
}
(adding all just in case)
My button doesn't highlight or click. Is there anything here that might explain the problem? I'm curious about common mistakes.
UILabel has by default userInteractionEnabled = false.
Setting this to true should fix your problem

Pass text from textField in UIAlertController to other view

I have a UIAlertController with two textFields :
class ModifiedSearchViewController: UISearchController, UISearchBarDelegate {
var nameOfOwnPlace = ""
var adressOfOwnPlace = ""
func insertYourPLace() {
let alertController = UIAlertController(title: "Insert New Place", message: "", preferredStyle: UIAlertControllerStyle.Alert)
let saveAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: {
alert -> Void in
let nameTextField = alertController.textFields![0] as UITextField
let adressTextField = alertController.textFields![1] as UITextField
self.nameOfOwnPlace = nameTextField.text!
self.adressOfOwnPlace = adressTextField.text!
print(self.nameOfOwnPlace)
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: {
(action : UIAlertAction!) -> Void in
})
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Place's Name..."
}
alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Adress's Name..."
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
...
}
I have an other view using my ModifiedSearchViewController class
but I dont succeed to send my strings (nameOfOwnPlace, adressOfOwnPlace) to the other view
searchController = ModifiedSearchViewController(searchResultsController: resultsViewController)
print(searchController.adressOfOwnPlace) // nil
Thanks for any help! :)
EDIT::
var resultsViewController = GMSAutocompleteResultsViewController()
var searchController = ModifiedSearchViewController()
func setSearchViewController() {
resultsViewController.delegate = self
searchController = ModifiedSearchViewController(searchResultsController: resultsViewController)
searchController.searchResultsUpdater = resultsViewController
print(searchController.adressOfOwnPlace) // nil
}