I have created 5 buttons dynamically in Swift like this:
for theIndex in 0..<5 {
let aButton = UIButton()
aButton.frame = CGRectMake(self.view.bounds.width / 2 - 120, self.view.bounds.height / 2 - 150, 240, 300)
aButton.setTitle("Button \(theIndex)", forState: .Normal)
aButton.addTarget(self, action: "btnClicked:", forControlEvents:.TouchUpInside)
self.view.addSubview(aButton)
}
But how can I get the BUTTON_ID for each one?
func btnClicked(sender: AnyObject?) {
let vc = storyboard!.instantiateViewControllerWithIdentifier("vc_name") as! DetailVC
vc.selectedId = **WANT_TO_PASS_BUTTON_ID_HERE**
self.presentViewController(vc, animated:true, completion:nil)
}
You can use tag property of your buttons (for example, you can set there a button's index), and retrieve it later in func btnClicked(sender: AnyObject?) method to determine a button with which index was pushed
While cycling through your indexes do:
aButton.tag = theIndex
and in btnClicked method do:
vc.selectedId = sender.tag
See for reference Apple docs on UIView
Related
I have three buttons that connect to the same IBAction. They all have their own out looks.
I found out how to make the button become highlighted when they are pressed and unhighlighted when the user presses another button. Is their a better way to write the code? Here is what I am using:
#IBAction func tipChanged(_ sender: UIButton) {
zeroPCTButton.isSelected = false
tenPCTButton.isSelected = false
twentyPCTButton.isSelected = false
sender.isSelected = true
}
The reason why I am asking is because I could make an application that has a thousand buttons and I don't want to brute force statements a thousands times
We can unhighlight the non pressed UIButton in the following way,
#IBAction func buttonAction(_ sender: Any) {
let the_tag = (sender as AnyObject).tag;
let button = self.view.viewWithTag(the_tag!) as? UIButton
button?.isSelected = true
button?.backgroundColor = UIColor.white
button?.setTitleColor(UIColor.black, for: .normal)
// Create a list of all tags
let allButtonTags = [1, 2, 3, 4, 5]
let currentButtonTag = (sender as AnyObject).tag
allButtonTags.filter { $0 != currentButtonTag }.forEach { tag in
if let button = self.view.viewWithTag(tag) as? UIButton {
// Deselect/Disable these buttons
button.backgroundColor = #colorLiteral(red: 0.80803, green: 0.803803, blue: 0.805803, alpha: 1)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.isSelected = false
}
}
}
Let's Imagine you have 1000 buttons, You need to Implement some loop to do all the action related Button (Create,Add constraints, click events).Create UIButton Array for store your buttons.
var buttons:[UIButton] = []
Add buttons to this array when you create buttons
for buttonIndex in 1...1000 {
// your other stuff to create, add constraints to button
button.tag = buttonIndex
buttons.append(button)
}
Now you can easily achieve your object.
#IBAction func tipChanged(_ sender: UIButton) {
buttons.forEach({$0.isSelected = $0.tag == sender.tag})
view.layoutIfNeeded()
}
import Foundation
import MapKit
class CustomAnnotationView : MKPinAnnotationView
{
let selectedLabel:UILabel = UILabel.init(frame:CGRectMake(0, 0, 250, 125))
let Button:UIButton = UIButton.init(frame:CGRectMake(0, 0, 100, 38))
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(false, animated: animated)
if(selected)
{
selectedLabel.text = annotation!.title!
selectedLabel.center.x = 0.5 * self.frame.size.width
selectedLabel.center.y = -0.5 * selectedLabel.frame.height
self.addSubview(selectedLabel)
Button.backgroundColor = UIColor.yellowColor()
Button.setTitle("Press", forState: UIControlState.Normal)
//the code below here //
var storyboard = UIStoryboard(name: "Main", bundle: nil)
let Map = storyboard.instantiateViewControllerWithIdentifier("Map")
Button.addTarget(Map, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
//self.view.addSubview(button)
Button.center.x = 0.5 * self.frame.size.width + 10
Button.center.y = selectedLabel.center.y
self.addSubview(Button)
}
else
{
selectedLabel.removeFromSuperview()
}
}
//This in Map.swift
func buttonAction () {
print("button pressed")
}
}
Instead of using Button.addTarget(self...
As i'm coding in a custom class.
How do I get it to run the action?
I've set the names also for the storyboard as Main on the right panel and same with the Map.
The Map is released after go out the setSelected method. You should handle the Map by something(property, global variable, ...)
in your CustomAnnotationView class add a block:
var tapProccess:(()->())?
in your action func
func buttonAction () {
self.tapProccess?()
}
And implement it:
let customAnno = CustomAnnotationView()
customAnno.tapProccess = {()->() in
// do some thing
}
Well, one possible solution to this would be to add a tap gesture recognizer to the button which can be done in code like this:
let tap = UITapGestureRecognizer(target: self, action: Selector("actionTap:"))
tap.delegate = self
Button.addGestureRecognizer(tap)
Then you could let the view controller conform to the class of UIGestureRecognizerDelegate.
Also, create a function that will do what you want the button to do when tapped, and name it "actionTap" like this:
func actionTap(sender: UITapGestureRecognizer? = nil) {
// Implement what you want the button to do here.
}
I have several buttons defined in a loop in viewDidLoad. They are inside a content view, which is in a scroll view.
for var i:Int = 0; i < colleges.count; i++ {
let collegeButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
collegeButton.frame = CGRectMake(0, 0, self.contentView.frame.size.width, 30)
collegeButton.center = CGPoint(x: self.contentView.center.x, y: 30 * CGFloat(i) + 30)
collegeButton.setTitle(sortedColleges[i], forState: UIControlState.Normal)
collegeButton.setTitleColor(UIColor.darkGrayColor(), forState: UIControlState.Normal)
collegeButton.titleLabel?.font = UIFont(name: "Hiragino Kaku Gothic ProN", size: 15)
collegeButton.addTarget(self, action: "collegeSelected:", forControlEvents: UIControlEvents.TouchUpInside)
self.contentView.addSubview(collegeButton)
}
As you can see, the title of each button is set based on a previously defined array of strings. Whenever a button is selected, a segue is called to move to a table view, which is embedded in a navigation controller.
I need to set the navigation controller title to be the same as the specific button title.
Here are some things I have tried:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var destViewController:videosTableView = segue.destinationViewController as videosTableView
//destViewController.title = collegeButton.titleLabel?.text
//var buttonTitle = sender.titleLabel?.text
//destViewController.title = buttonTitle
}
The commented lines were failed attempts.
I also tried working in the action function called when the button is pressed:
func collegeSelected(sender: UIButton!) {
self.performSegueWithIdentifier("goToTableView", sender: self)
//Set navigation title of next screen to title of button
var buttonTitle = sender.titleLabel?.text
println(buttonTitle)
}
Using the sender to get the button title works, but I don't know how to pass it to the next view controller.
Thanks a lot to anyone who can help.
In your button function, pass the button along as the sender of the segue:
func collegeSelected(sender: UIButton!) {
self.performSegueWithIdentifier("goToTableView", sender: sender)
}
Then in prepareForSegue, get the button title from the sender (i.e. the button):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destViewController = segue.destinationViewController as videosTableView
if let buttonTitle = (sender as? UIButton)?.titleLabel?.text {
destViewController.title = buttonTitle
}
}
I've a gameviewcontroller which gets 2 values from 1st view controller .. i.e. selectedlevelnumber and nextlevelnumber. I want to show Next Level button when current level is completed. So next level button is showing when level is completed but when clicking on next level button it gives me unknown error, console says lldb and takes me to AppDelegate.swift.
I have this code in my GameViewController
if levelisCompleted == true {
LevelCompletedView().levelcomplete(selectedlevelnumber, nextlevel: nextlevelnumber)
} .. this is working perfectly
now this is my LevelCompletedView
class LevelCompletedView: UIViewController {
func levelcomplete(levelnum:String, nextlevel:String) {
println("\(levelnum) is completed ")
println("next level is \(nextlevel)")
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(10, 10, 200, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Next Level", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonA:", forControlEvents: UIControlEvents.TouchUpInside)
gamesubView.addSubview(button)
func buttonA(sender:UIButton!) {
println("loading next level \(nextlevel)")
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var gameview = self.storyboard?.instantiateViewControllerWithIdentifier("gamevc") as GameViewController
gameview.levelSelectedNum = String(nextlevel)
self.presentViewController(gameview, animated: true, completion: nil)
}
}
}
everything works, only the button is not working when clicked.
As it stands now, the buttonA: method is local since it's contained within levelComplete, so once levelComplete has finished executing, the buttonA: function disappears. Your button's not recognizing it's target action buttonA: because it wasn't defined within the scope of its class -- thus the resulting error. Move func buttonA outside of levelComplete to correct this issue.
And to access nextlevel, save it as a global variables, ex.
class LevelCompletedView: UIViewController {
var nextLevelVar:String!
func levelcomplete(levelnum:String, nextlevel:String) {
println("\(levelnum) is completed ")
println("next level is \(nextlevel)")
nextLevelVar = nextlevel
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(10, 10, 200, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Next Level", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonA:", forControlEvents: UIControlEvents.TouchUpInside)
gamesubView.addSubview(button)
}
func buttonA(sender:UIButton!) {
println("loading next level \(nextLevelVar)")
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var gameview = self.storyboard?.instantiateViewControllerWithIdentifier("gamevc") as GameViewController
gameview.levelSelectedNum = String(nextLevelVar)
self.presentViewController(gameview, animated: true, completion: nil)
}
}
I want to create a Button that presents another view controller when it is tapped.
I am trying to to this via selector but when I click the button I get a Thread1: signal SAGABRT error.
So I commented out the presenting and just put in a print to console-statement. I also get the same error. :(
My code is the following:
override func viewDidLoad() {
var menuView = UIView()
var newPlayButton = UIButton()
var newPlayImage = UIImage(named: "new_game_button_5cs")
var newPlayImageView = UIImageView(image: UIImage(named: "new_game_button_5cs"))
newPlayButton.frame = CGRectMake(0, 0, newPlayImageView.frame.width, newPlayImageView.frame.height)
newPlayButton.setImage(newPlayImage, forState: .Normal)
newPlayButton.addTarget(self, action:"showNewPlay:", forControlEvents: UIControlEvents.TouchUpInside)
menuView.addSubview(newPlayButton)
self.view.addSubview(menuView)
}
func showNewPlay(sender:UIButton!) {
//var vc = self.storyboard?.instantiateViewControllerWithIdentifier("newGameID") as ViewController
//self.presentViewController(vc, animated: false, completion: nil)
println("Button tapped")
}