Passing parameters in a clickable UIabel - swift

I'm trying to make a clickable UILabel by following with this code:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(ViewController.ale_plato1))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
...
#objc
func ale_plato1(sender: UITapGestureRecognizer){
let label = sender.view
print ("tapped!")
}
This works well. But I want to pass parameters to the function. Something like this:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(MenuController.ale_plato1("parameter")))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
#objc
func ale_plato1(sender: UITapGestureRecognizer, parameterRecived: String){
}
But I don't know how do that in swift 3...
Any help? Thanks you

Wherever you make your multiple UILabel set each label to a different tag.
for i in 0..<3 {
let label = UILabel()
label.tag = i
let tap = UITapGestureRecognizer(target: self, action: #selector(tap))
label.isUserInteractionEnabled = true
label.addGestureRecognizer(tap_plato)
}
#objc func tap(sender: UITapGestureRecognizer) {
let label = sender.view as! UILabel // if you are SURE that your tap will be a UILabel
if(label.tag == 0) {
label.text = "This is label 0"
if(label.tag == 1) {
label.text = "This is label 1"
}
}
Threw this up in a jiffy, hop over the syntax issues if there are any.
Here we can create labels with tags and apply the same tap to them. From there, we can check what tag it is inside the tap method and do something from there.

You could use the tag attribute for Int values, but if you want anything other than that:
Create a custom UILabel Class with a value variable.
class LabelWithValue : UILabel {
var value : String = ""
}
Then you can use it as a normal Label
let label = LabelWithValue()
label.text = "bla"
label.value = "Anything"
label.isUserInteractionEnabled = true
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleGetText)))
Then you can get it's text and it's value.
#objc func handleGetText(_ sender : UITapGestureRecognizer) {
if let label = sender.view as? LabelWithValue {
print(label.text)
print(label.value)
}
}

Related

I want to switch the screen when the Label named New Account is pressed, but the application keeps crashing. Can you help me?

lazy var newAccountLabel: UILabel = {
let newAccountLabel = UILabel()
newAccountLabel.text = " New Account"
newAccountLabel.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: LoginViewController.self, action: #selector(LoginViewController.newAccountLabelTapped(_:)))
newAccountLabel.addGestureRecognizer(tap)
newAccountLabel.textColor = .systemGray
return newAccountLabel
}()
The creation of the label I want to click on.
#objc func newAccountLabelTapped(_ sender: UIButton){
let goToVc = RegisterViewController()
self.present(goToVc, animated: true, completion: nil)
}
The action function that the transition should be.
Replace LoginViewController.self with self
let tap = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.newAccountLabelTapped(_:)))

How to fix UIButton not responding to touch?

I am working an app with quizzes, have 4 UIButtons (custom type) on subview which is custom view and none of the buttons is recognising the action even though I set the target. I have to do it programatically.
I have tried setting isUserInteractionEnabled but it is not working. Buttons are on the view, respecting the bounds.
Here, viewDidLoad from InitialViewController:
override func viewDidLoad()
{
super.viewDidLoad()
self.questionView?.firstanswer!.isEnabled = true
self.questionView?.firstanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.secondanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.thirdanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.fourthanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
}
Here is the action function:
#objc func answerTheQuestion(_sender:UIButton) {
print("aa")
if let questionsAnswers = self.quizzes?.quizzes[self.randomNumber!]["questions"] as? [[String:Any]] {
if (questionsAnswers[self.randomQuestion!]["question"] as? String) != nil {
if let correctAnswer = questionsAnswers[self.randomQuestion!]["correct_answer"] as? String {
if _sender.titleLabel?.text == correctAnswer {
_sender.backgroundColor = UIColor.green
} else {
_sender.backgroundColor = UIColor.red
}
}
}
}
}
View and buttons are added normally, only tap is not working.
It should go red when the answer is wrong, and green when it is right. Questions and everything else is added normally, but it even won't print "aaa" in the beginning of the target function. Pls help, thanks!!

Call selector from nother class - Swift 3

I'm creating an UIbutton from "Utils_class", and return it to my "getBtsDetails" class.
I successfully achieve to call "buttonAction" function implemented into "getBtsDetails", but then it return an error
"Unexpectedly found nil while unwrapping an Optional value"
getBtsDetails :
let Utils_Class = Utils()
var labelY : Int = 90
override func viewDidLoad() {
super.viewDidLoad()
WS_Class.GetDiplomaSubject(id: Int(self.BTS_id)!) { number, responseObject, error in
if((error) == nil) {
#let's create an UIbutton from Utils_class which gonna call the buttonAction below
self.scrollview.addSubview(self.Utils_Class.createButton(text: "Calcul", buttonY:self.labelY+30))
self.scrollview.contentSize.height = CGFloat(self.labelY+40)
}
}
}
#objc func buttonAction(_ sender:UIButton!)
{
#the error occurs here
print(self.Utils_Class.getTextFields(view : self.scrollview)/1)
}
And my second class, Utils :
public func createButton(text: String!, buttonY: Int!) -> UIButton {
helpClasses = GetBTSDetails.init()
let button = UIButton(type: UIButtonType.system) as UIButton
button.frame = CGRect(x:0, y:buttonY, width:self.screenWidth/5, height:15)
button.backgroundColor = UIColor.lightGray
button.setTitle(text, for: UIControlState.normal)
button.tintColor = UIColor.black
button.addTarget(btsClasse, action: #selector(btsClasse.buttonAction(_:)), for: .touchUpInside)
return button
}
var btsClasse: GetBTSDetails!
Ok, i finally succeed, by simply creating a new instance of my class and replacing :
var btsClasse: GetBTSDetails!
by
var btsClasse = GetBTSDetails()
This way, my class "GetBTSDetails", all functions, variables are already initialized allowing myself to call the UIButton action.
Because you didn't init it
var btsClasse: GetBTSDetails!
so when target runs
button.addTarget(btsClasse, action: #selector(btsClasse.buttonAction(_:)),for: .touchUpInside
what in buttonAction will be nil , so you have to linkbtsClasse object to the presented instance that you reference the selector from

Looping UITapGestureRecognizer only added to last one not all of them

So I'm up to the point that I'm creating UIViews programmatically based on the amount of an array which is returned from JSON. Everything seems to be going ok except for the loop which is supposed to add the tap to each of the views but it is only adding it to one view. Only prints on the last UIView.
func addsubviews(howmany: Int) -> Void{
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))
for x in 1...howmany{
guard let v = UINib(nibName: "DealsView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as? UIView else { return }
v.translatesAutoresizingMaskIntoConstraints = false
guard let lbl = v.viewWithTag(99) as? UILabel else { return }
lbl.text = "Here is a new Label for Loop: " + "\(x)"
self.allContainer.addSubview(v)
v.backgroundColor = UIColor.white
var horizontalConstratint1 = NSLayoutConstraint()
var horizontalConstratint2 = NSLayoutConstraint()
var verticalConstraint1 = NSLayoutConstraint()
heightConstraint = v.heightAnchor.constraint(equalToConstant: 100)
horizontalConstratint1 = v.leadingAnchor.constraint(equalTo: (v.superview?.leadingAnchor)!, constant: 10)
horizontalConstratint2 = v.trailingAnchor.constraint(equalTo: (v.superview?.trailingAnchor)!, constant: -10)
if prevView == nil{
verticalConstraint1 = v.topAnchor.constraint(equalTo: (v.superview?.topAnchor)!, constant: 20)
}else
{
if let pv = prevView as? UIView {
verticalConstraint1 = v.topAnchor.constraint(equalTo: (pv.bottomAnchor), constant: 20)
}
}
NSLayoutConstraint.activate([horizontalConstratint1,horizontalConstratint2,verticalConstraint1])
prevView = v
}
if let pv = prevView as? UIView {
print("final constratint")
NSLayoutConstraint.activate([
self.allContainer.bottomAnchor.constraint(equalTo: pv.bottomAnchor, constant: 20)
])
}
for views in self.allContainer.subviews{
print("adding views")
views.addGestureRecognizer(tap)
}
}
After some trial and error...
The tap recognizer added for each loop:
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(sender:)))
the action which will be where the action goes on the tap:
func handleTap(sender: UITapGestureRecognizer) {
// You can get the view here by writing
let myv = sender.view
print(myv)
}
You have just a single UITapGestureRecognizer before your view loop starts. AFAIK, tap gesture recognizers can only be attached to one view at a time. Check out this question. To solve this, try writing this line:
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))
inside your view loop.
To find out what view was tapped, make your selector handleTap take an argument like so:
Selector("handleTap:")
and the method itself like this:
func handleTap(sender: UITapGestureRecognizer? = nil) {
// You can get the view here by writing
let v = sender.view
}

swift uitapgesturerecognizer pass parameters

I have a lot of Buttons created programmatically and that can change anytime. my tap gesture :
let apriVideoGesture = UITapGestureRecognizer(target: self, action: #selector(PrincipaleController.apriVideo(_:)))
cont.addGestureRecognizer(apriVideoGesture)
func apriVideo(sender : UITapGestureRecognizer){
}
how can i pass parameters? somethig like this :
let apriVideoGesture = UITapGestureRecognizer(target: self, action: #selector(PrincipaleController.apriVideo(stringa : "ciao")))
cont.addGestureRecognizer(apriVideoGesture)
func apriVideo(sender : UITapGestureRecognizer, stringa : String){
}
sorry for bad english, i'm italian
First of all, if you are using button then why are you adding tap gesture? You can add target to it as
btn.addTarget(self, action: #selector(self.btnPressed(_:)), forControlEvents: .TouchDragInside)
But still you can achieve you goal using tap gesture as
Using UIView as u have insisted
class ViewController: UIViewController {
let arrayOfSongsURL: [String] = []
let startingTag = 100
override func viewDidLoad() {
super.viewDidLoad()
let height : CGFloat = 100
let width : CGFloat = 100
(arrayOfSongsURL as NSArray).enumerateObjectsUsingBlock { (url, index, finished) -> Void in
let v = UIView(frame: CGRectMake(0, CGFloat(index) * height, width, height))
v.tag = self.startingTag + index
v.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleTapGesture(_:))))
self.view.addSubview(v)
}
// Do any additional setup after loading the view, typically from a nib.
}
#objc func handleTapGesture(gesture : UITapGestureRecognizer)
{
let v = gesture.view!
let tag = v.tag
let songURL = arrayOfSongsURL[tag - startingTag]
//Do what you want to do with songURL
}
}