How to use CADisplayLink for a specific button? - ios

I'm trying to make an application where i have to touch a button who is moving up the screen. I am using CADisplayLinkfor this. The problem in my code is that its creating a new button instead of using a specific one:
#IBOutlet var label: UILabel!
#IBOutlet var button2: UIButton!
#IBAction func button1(sender: UIButton) {
label.hidden = true
button2 = UIButton(type: UIButtonType.System) as UIButton
button2.frame = CGRectMake(120, 400, 100, 100)
button2.setTitle("Test Button", forState: UIControlState.Normal)
button2.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
let displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
}
func handleDisplayLink(displayLink: CADisplayLink) {
var buttonFrame = button.frame
buttonFrame.origin.y += -2
button2.frame = buttonFrame
if button2.frame.origin.y <= 50 {
displayLink.invalidate()
}
}
func buttonAction(sender: UIButton) {
sender.alpha = 0
label.hidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
label.hidden = true
}
Thank you.
Anton

You can delete
button2 = UIButton(type: UIButtonType.System) as UIButton
button2.frame = CGRectMake(120, 400, 100, 100)
button2.setTitle("Test Button", forState: UIControlState.Normal)
And just set these attributes in Interface Builder.
Also this line:
self.view.addSubview(button)
No longer makes sense after you edited your question, but it is also not necessary if your buttons are IBOutlets.
This line:
var buttonFrame = button.frame
Only makes sense if button is an IBOutlet declared elsewhere.

Related

How do i get the button value in swift 4?

#IBOutlet var button: UIButton!
func randomize(){
var x_axis:CGFloat = 8.0
var y_axis:CGFloat = 330.0
for selected_Synonym in selected_Synonyms {
button = UIButton.init(type: UIButtonType.custom) as UIButton
button.frame = CGRect(x: x_axis, y: y_axis, width: 400, height: 50)
button.backgroundColor = UIColor.black
button.setTitle(selected_Synonym as? String, for: UIControlState.normal)
button.setTitleColor(UIColor.white, for: [])
button.addTarget(self, action: Selector(("pressed:")), for: UIControlEvents.touchUpInside)
self.view.addSubview(button)
x_axis = 10.0
y_axis += 70.0
}
}
func pressed(sender: Any){
let buttonTitle = button.currentTitle
print(buttonTitle)
}
However when it runs and I press on a button I get the following error:
Thread 1: signal SIGABRT.
The program creates 5 buttons. I am new to swift and ios development would be very grateful if someone could help me out. Thank you.
You have several issues. To fix the crash, replace Selector(("pressed:")) with #selector(pressed). The use of Selector is very out-of-date. Always use #selector.
Next, remove the #IBOutlet var button: UIButton! line. You don't need it.
Then change:
button = UIButton.init(type: UIButtonType.custom) as UIButton
to:
let button = UIButton(type: .custom)
Then update your pressed function to:
#objc func pressed(sender: UIButton){
let buttonTitle = sender.currentTitle
print(buttonTitle)
}
Note the addition of #objc. This is required for any function being used with a target/selector. Also note that sender is now UIButton instead of Any. It's best to set the sender's type to match the proper type.
Here's all of your code with lots of little fixes:
func randomize() {
var xAxis: CGFloat = 8.0
var yAxis: CGFloat = 330.0
for selectedSynonym in selectedSynonyms {
let button = UIButton(type: .custom)
button.frame = CGRect(x: xAxis, y: yAxis, width: 400, height: 50)
button.backgroundColor = .black
button.setTitle(selectedSynonym, for: .normal)
button.setTitleColor(.white, for: .normal)
button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
self.view.addSubview(button)
xAxis = 10.0
yAxis += 70.0
}
}
#objc func pressed(sender: UIButton){
let buttonTitle = sender.currentTitle
print(buttonTitle)
}
Use camelCase, not snake_case when naming variables and functions. Make use of Swift type inference.

how to create radio buttons dynamically in swift?

I have the following buttons which are adding dynamically based on some condition. Now i need to change all added buttons behaviour as radio buttons. so that I can do some actions based on the selection..
var posX = 0
var posY = 0
if trim.contains("0"){
print("contaim 0")
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
posX = 60
}
if trim.contains("1") {
print("contaim 1")
let button2 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button2.setTitleColor(UIColor.blackColor(), forState: .Normal)
button2.setTitle("Less", forState: .Normal)
button2.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button2.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button2)
posX = posX + 60
}
if trim.contains("2"){
print("contaim 2")
let button3 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button3.setTitleColor(UIColor.blackColor(), forState: .Normal)
button3.setTitle("Half", forState: .Normal)
button3.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button3.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button3)
posX = posX + 60
}
I have set the buttonAction methods as below buts its not working
func buttonAction(sender: UIButton!) {
print("Button tapped")
sender.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Normal)
}
let buttons = [UIButton]()
// create button1
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button1.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Selected)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
buttons.append(button1)
// create other buttons and add into buttons ...
func buttonAction(sender: UIButton!){
for button in buttons {
button.selected = false
}
sender.selected = true
// you may need to know which button to trigger some action
// let buttonIndex = buttons.indexOf(sender)
}
In case anyone finds this useful. Here is an example of how I use DLRadioButton library (https://github.com/DavydLiu/DLRadioButton) to create RadioButtons dynamically.
You can check a complete small project to show a working code in here https://github.com/omhack/DynamicRadioButtons
import UIKit
import DLRadioButton
//Delegate to manage the Polls
protocol QuestionsDialogDelegate : class{
func questionsAnswered(polls: [Poll])
}
class QuestionsDialog: UIViewController {
#IBOutlet weak var stackView: UIStackView!
#IBOutlet var rootView: UIView!
#IBOutlet weak var nestedView: UIView!
weak var delegate: QuestionsDialogDelegate?
var questions : [Question]!
var polls = [Poll]()
var serviceType : Int = 0
var indexView : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
//setting the stack view properties
stackView.alignment = UIStackViewAlignment.leading
stackView.axis = .vertical
}
//this is where the heavy logic, to create the dynamic radio buttons takes place
func showQuestions(){
if(questions.count <= 1){
rootView.frame.size.height = 200
nestedView.frame.size.height = 200
}else{
rootView.frame.size.height = 400
nestedView.frame.size.height = 400
}
for question in questions{
var otherButtons : [DLRadioButton] = []
let frame1 = CGRect(x: self.view.frame.size.width / 2 - 131, y: 350, width: 262, height: 17);
//we create a base radio button to use it as an anchor view
let firstRadioButton = createRadioButton(frame: frame1, title: "", color: UIColor.purple);
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 17.0)
label.textColor = UIColor.darkGray.withAlphaComponent(0.85)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
label.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
label.text = question.question
self.stackView.insertArrangedSubview(label, at: self.indexView)
self.indexView += 1
let poll = Poll()
poll.idQuestion = question.idQuestion
var i = 0;
for answer in question.answers{
let frame = CGRect(x: self.view.frame.size.width / 2 - 131, y: 380 + 30 * CGFloat(i), width: 300, height: 17);
let radioButton = createRadioButton(frame: frame, title: answer.answer! + " ", color: UIColor.purple)
radioButton.tag = answer.idAnswer
radioButton.params["poll"] = poll
otherButtons.append(radioButton)
self.stackView.insertArrangedSubview(radioButton, at: self.indexView)
i += 1;
self.indexView += 1
}
firstRadioButton.otherButtons = otherButtons
firstRadioButton.isHidden = true
firstRadioButton.otherButtons[1].isSelected = true
}
}
//Method to create a custom button
private func createRadioButton(frame : CGRect, title : String, color : UIColor) -> MyDLUIButton {
let radioButton = MyDLUIButton(frame: frame);
radioButton.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
radioButton.titleLabel!.font = UIFont.systemFont(ofSize: 14);
radioButton.setTitle(title, for: []);
radioButton.setTitleColor(UIColor.darkGray, for: []);
radioButton.iconColor = color;
radioButton.indicatorColor = color;
radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
radioButton.addTarget(self, action: #selector(QuestionsDialog.selectedAnswer(_:)), for: UIControlEvents.touchUpInside)
self.view.addSubview(radioButton);
return radioButton;
}
#objc func selectedAnswer(_ sender: MyDLUIButton){
let poll = sender.params["poll"] as? Poll
poll?.idAnswer = sender.tag
if let row = self.polls.index(where: {$0.idQuestion == poll?.idQuestion}) {
self.polls[row] = poll!
}else{
self.polls.append(poll!)
}
print("polls size: \(self.polls.count)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidDisappear(_ animated: Bool) {
if(self.polls.count < self.questions.count){
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "questionsDialogDismissed"), object: nil)
}
}
#IBAction func requestService(_ sender: UIButton) {
delegate?.questionsAnswered(polls: self.polls)
}
}
class MyDLUIButton: DLRadioButton{
var params: Dictionary<String, Any>
override init(frame: CGRect) {
self.params = [:]
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
self.params = [:]
super.init(coder: aDecoder)
}
}
I would create a tag for every UIButton, then add your UIButton to be send to your ButtonAction:
button.tag = 0
button.addTarget(object, action: #selector(YourViewController.buttonAction(_:)),
forControlEvents: .TouchUpInside)
func buttonAction(sender: UIButton!) {
let selectedButton = sender as! UIButton
print(selectedButton.tag) // here stands the correct button which is pressed
}
You could also create an Array containing all Buttons, for example:
let myButtons = [UIButton]()
let button1 = UIButton()...
button1.tag = 0
myButtons.add(button1)
And now change it like this way:
myButtons[0].setImage(.....)
Where 0 is your first button (so with tag 0) // you should set your tags in the same order in which you append it to your myButtons Array.

Button in view not clicking ios swift

I'm trying to implement a dropdown menu in Swift by adding a view below the navigation bar and initially setting it to hidden until a navigationBarItem button is pressed, which works. In the dropdown View I have added two buttons as seen in the code below but it doesn't seem to pick up the event.
var isAnimating: Bool = false
var dropDownViewIsDisplayed : Bool = false
var dropDownView : UIView!
var buttonOne : UIButton!
var buttonTwo : UIButton!
var screenWidth : CGFloat!
#IBOutlet weak var searchNavigationBar: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
screenWidth = self.view.bounds.size.width
self.navigationController?.navigationBar.translucent = false
dropDownView = UIView(frame: CGRectMake(0, -15, screenWidth, -80))
dropDownView.hidden = true
dropDownView.userInteractionEnabled = true
self.navigationController?.view.insertSubview(self.dropDownView, belowSubview: (self.navigationController?.navigationBar)!)
buttonOne = UIButton(frame: CGRectMake(0, 0, screenWidth, 40))
buttonOne.setTitle("Button One", forState: .Normal)
buttonOne.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonOne.backgroundColor = UIColor.whiteColor()
buttonOne.addTarget(self, action: Selector("buttonOnePressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonOne.userInteractionEnabled = true
dropDownView.addSubview(buttonOne)
buttonTwo = UIButton(frame: CGRectMake(0, buttonOne.bounds.size.height, screenWidth, 40))
buttonTwo.setTitle("Button Two", forState: .Normal)
buttonTwo.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonTwo.backgroundColor = UIColor.whiteColor()
buttonTwo.addTarget(self, action: Selector("buttonTwoPressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.userInteractionEnabled = true
dropDownView.addSubview(buttonTwo)
}
func buttonTwoPressed(){
self.performSegueWithIdentifier("showLocation", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showLocation") {
var location: LocationTableViewController = (segue.destinationViewController as? LocationTableViewController)!
}
}
Button click functions are not being called.
Are you using Swift 2.0 with Xcode 7? Just by quickly tried playing with your code like this, I found that the event handlers are being called properly without any big changes. Are you sure that there is nothing wrong somewhere else?
var isAnimating: Bool = false
var dropDownViewIsDisplayed : Bool = false
var dropDownView : UIView!
var buttonOne : UIButton!
var buttonTwo : UIButton!
var screenWidth : CGFloat!
#IBOutlet weak var searchNavigationBar: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
screenWidth = self.view.bounds.size.width
self.navigationController?.navigationBar.translucent = false
// I modified these 2 lines to test your code immediately
dropDownView = UIView(frame: CGRectMake(0, 65, screenWidth, 80))
dropDownView.hidden = false
dropDownView.userInteractionEnabled = true
self.navigationController?.view.insertSubview(self.dropDownView, belowSubview: (self.navigationController?.navigationBar)!)
buttonOne = UIButton(frame: CGRectMake(0, 0, screenWidth, 40))
buttonOne.setTitle("Button One", forState: .Normal)
buttonOne.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonOne.backgroundColor = UIColor.whiteColor()
buttonOne.addTarget(self, action: Selector("buttonOnePressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonOne.userInteractionEnabled = true
dropDownView.addSubview(buttonOne)
buttonTwo = UIButton(frame: CGRectMake(0, buttonOne.bounds.size.height, screenWidth, 40))
buttonTwo.setTitle("Button Two", forState: .Normal)
buttonTwo.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonTwo.backgroundColor = UIColor.whiteColor()
// Here I just wanted to show you that calling Selector() is not necessary at all
buttonTwo.addTarget(self, action: "buttonTwoPressed", forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.userInteractionEnabled = true
dropDownView.addSubview(buttonTwo)
}
// I didn't see this method in your code above so I added to test and it works!
func buttonOnePressed() {
print("buttonOnePressed")
}
// This is also being called normally
func buttonTwoPressed() {
print("buttonTwoPressed")
}
Can you please try with:
buttonOne.addTarget(self, action: Selector("buttonOnePressed:"), forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.addTarget(self, action: Selector("buttonTwoPressed:"), forControlEvents: UIControlEvents.TouchUpInside)
It won't works because it outside self.navigationController?.navigationBar.frame. You should add buttons on self.view or transparent modal view/UIWindow.

How to use a for-in-loop to make multiple objects in a CADisplayLink

So I am trying to create 10 buttons by using a for in loop and make all those 10 buttons move down using a CADisplayLink. The problem is that my CADisplayLink only moves one of the buttons down and I want it to move all 10 of the buttons. Please Help! Thanks in advance!
var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
var displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
for index in 0...10 {
var xLocation:CGFloat = CGFloat(arc4random_uniform(300) + 30)
button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(xLocation, 10, 100, 100)
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func handleDisplayLink(displayLink: CADisplayLink) {
for index in 0...10 {
var buttonFrame = button.frame
buttonFrame.origin.y += 1
button.frame = buttonFrame
if button.frame.origin.y >= 500 {
displayLink.invalidate()
}
}
}
func buttonAction(sender: UIButton) {
sender.alpha = 0
}
}
You've only got a reference to one of the 10 buttons you've created in viewDidLoad. Use an array of type button [UIButton] to store all 10 and then loop through each of them during your CADisplayLink callback.
Your declaration would be:
var buttons: [UIButton] = Array(count: 10, repeatedValue: UIButton.buttonWithType(.System) as! UIButton)
And any time you referenced a button in your original code, reference the button at the current index of your for loop using the array index operator:
buttons[index]
An overview of Swift arrays and the standard library reference are here:
Swift Language Guide: Collection Types
Swift Standard Library Reference: Arrays
So the provided code would be:
var buttons: [UIButton] = Array(count: 10, repeatedValue: UIButton.buttonWithType(.System) as! UIButton)
override func viewDidLoad() {
super.viewDidLoad()
var displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
for index in 0...10 {
var xLocation:CGFloat = CGFloat(arc4random_uniform(300) + 30)
buttons[index].frame = CGRectMake(xLocation, 10, 100, 100)
buttons[index].setTitle("Test Button \(index)", forState: UIControlState.Normal)
buttons[index].addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(buttons[index])
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func handleDisplayLink(displayLink: CADisplayLink) {
for index in 0...10 {
var buttonFrame = buttons[index].frame
buttonFrame.origin.y += 1
buttons[index].frame = buttonFrame
if buttons[index].frame.origin.y >= 500 {
displayLink.invalidate()
}
}
}
func buttonAction(sender: UIButton) {
sender.alpha = 0
}

clicking a on runtime created button crashes my ios app (swift)

I am a newby in ios development and I am facing the following problem.
I create a button at runtime in the viewDidLoad method:
class ViewController: UIViewController {
#IBOutlet weak var TestButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("start");
// Create Button at runtime
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.redColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
func buttonAction(sender:UIButton!)
{
println("Button tapped.")
}
}
When I press the button in the simulator the app stops at line :
class AppDelegate: UIResponder, UIApplicationDelegate {
of AppDelegate.swift
Does anyone have any idea why it doesn't output "Button tapped." ?
If I get a problem like this, how can I report the errormessage to someone else ? I mean I do not see any errorcode or stacktrace in XCode. Where to find this ?
Function not in viewDidLoad.
example:
class ViewController: UIViewController {
#IBOutlet weak var TestButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("start");
// Create Button at runtime
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.redColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
} // CLOSE
func buttonAction(sender:UIButton!)
{
println("Button tapped.")
}
}// CLOSE
You should extract your method for button outside your function like following:
class ViewController: UIViewController {
#IBOutlet weak var TestButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("start");
// Create Button at runtime
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.redColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
func buttonAction(sender:UIButton!)
{
println("Button tapped.")
}
}
Why is this you might ask? It is because you will register your event which is in scope of the function. When function ends your function for event is not there any more. Since, the chrash
Try this:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.frame = CGRectMake(100, 100, 100, 50)
button.backgroundColor = UIColor.greenColor()
button.setTitle("Test Button", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
func buttonAction(sender:UIButton!)
{
println("Button tapped")
}
Also import UIKit

Resources