Using a nested function as the selector of an action - swift - swift

This is my code:
func didSelectLabel() {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 30))
label.center = viewForEdit.center
label.textAlignment = .center
label.isUserInteractionEnabled = true
func userDragged(gesture: UIPanGestureRecognizer) {
let loc = gesture.location(in: self.viewForEdit)
label.center = loc
}
gesture = UIPanGestureRecognizer(target: self, action: userDragged(gesture:))
label.addGestureRecognizer(gesture)
let alert = UIAlertController(title: "Write your text", message: "", preferredStyle: .alert)
let continueAction = UIAlertAction(title: "Continue", style: .default) { (UIAlertAction) in
label.text = alert.textFields?[0].text
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addTextField { (textField) in
textField.placeholder = "Write here"
}
alert.addAction(continueAction)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
self.viewForEdit.addSubview(label)
}
I would like to use
func userDragged(gesture: UIPanGestureRecognizer)
as the selector of
gesture = UIPanGestureRecognizer(target: self, action: userDragged(gesture:))
The problem is that if I run the code it crashes saying
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TestApp.ViewControllerEditor userDragged:]: unrecognized selector sent to instance 0x7fc6b3c282b0'
P.S. I cannot put the function 'userDragged(gesture:)' outside of the function 'didSelectLabel()' becuse if I do so 'label.center = loc' returns an error. This is because 'label' is called inside of the function 'didSelectLabel()'

The easiest way is to move your function outside didSelectLabel, and change it to:
func userDragged(gesture: UIPanGestureRecognizer) {
let loc = gesture.location(in: self.viewForEdit)
let label = gesture.view as? UILabel
label?.center = loc
}

Related

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

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

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

Programed textfile&Labels with CoreData -Swift3

I'm using CoreData and I have an issue.
So, I'm using scroll view and in the following code it adds a label and a textfield every time the user presses the "add" button. And I need to save this to CoreData(yes it needs to be CoreData). But how can I do this? I went through CoreData relationships but couldn't understand and hoping for help.
Thank you vary much :)
var count = 0
#IBAction func add(_ sender: Any) {
count += 1
let myPoint = count * 100
if count >= 1 {
let myAlartController = UIAlertController(title: "Add Item", message: "Please add title and context", preferredStyle: UIAlertControllerStyle.alert)
myAlartController.addTextField(configurationHandler: ({(firstText: UITextField!) -> Void in firstText.placeholder = "Please add title"}))
myAlartController.addTextField(configurationHandler: ({(secondText: UITextField!) -> Void in secondText.placeholder = "Please add context"}))
let okButton = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
(action: UIAlertAction) -> Void in
//When the bottum is pressed
let myCGRect = CGRect(x: 0, y: 0, width: 105, height: 30)
//Label
let myLabel = UILabel(frame: myCGRect)
myLabel.backgroundColor = UIColor.orange
let labelOfAlert = myAlartController.textFields?[0]
myLabel.text = labelOfAlert?.text
myLabel.textColor = UIColor.white
myLabel.layer.position = CGPoint(x: 60, y: (565 + myPoint))
//textFiled
let myTextField = UITextField(frame: myCGRect)
myTextField.backgroundColor = UIColor.gray
let textOfAlert = myAlartController.textFields?[1]
myTextField.text = textOfAlert?.text
myTextField.layer.position = CGPoint(x: 135, y: (565 + myPoint))
self.labelTopConstrain.constant = (CGFloat(900 + myPoint))
self.labelBottomConstrain.constant = 20
self.myScroll.layoutIfNeeded()
myLabel.tag = self.count
myTextField.tag = self.count
self.myScroll.addSubview(myLabel)
self.myScroll.addSubview(myTextField)
let testSave = Test(context: myContext)
testSave.label = myLabel.text
testSave.textField = myTextField.text
(UIApplication.shared.delegate as! AppDelegate).saveContext()
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
myAlartController.addAction(okButton)
myAlartController.addAction(cancelAction)
present(myAlartController, animated: true, completion: nil)
}/*if*/
}/**/