UIButton action doesn't work - ios

I'm trying to pass my app from Objective-C to Swift, but I have some problem with my UIButton action which are never called.
UIButton declaration (in footer view) :
let footerView = UIView.init(frame: CGRectMake(0, 0, self.view.frame.size.width, 140))
let acceptButton = UIButton(type: .Custom)
acceptButton.userInteractionEnabled = true
acceptButton.setTitle("Accepter", forState: .Normal)
acceptButton.addTarget(self, action: "acceptRequest:", forControlEvents: .TouchUpInside)
acceptButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
acceptButton.titleLabel!.font = UIFont(name: "AvenirNext-Medium", size:16.0)
acceptButton.frame = CGRectMake((self.view.frame.size.width/2)-115, 35,230, 40)
acceptButton.layer.cornerRadius = 4
acceptButton.layer.borderWidth = 1
acceptButton.layer.borderColor = UIColor.customGreen().CGColor
acceptButton.layer.backgroundColor = UIColor.customGreen().CGColor
footerView.addSubview(acceptButton)
return footerView;
Action :
func acceptRequest(sender:UIButton!) {
print("2")
}
I missed something with Swift ?

I looked at it carefully, your event should be no problem.I think what you said is UITableView seciton footer View, Would you determine whether or not to return to the height of the footerView, if there is no return footerView height, the event is also unable to response, because it is beyond the parent view display area.The hope can help you!
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 44
}

Try this:
footerView.userInteractionEnabled = false

Related

swift add switch programmatically in side menu

Im trying to style my side menu, I want the UISwitch to edit the label next to it. But the only think that happens when I click on the switch is that the app crashes and I receives following error message
2016-08-20 01:56:20.545 Moppio[4342:8394913] -[Moppio.BackTableViewController test()]: unrecognized selector sent to instance 0x7fe66a4ba530
2016-08-20 01:56:20.554 Moppio[4342:8394913] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Moppio.BackTableViewController test()]: unrecognized selector sent to instance 0x7fe66a4ba530'
* First throw call stack: ...
And this is the code that I use right now.
//Profile picture + bar
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
let view = UIView(frame: CGRectMake(0, 0, tableView.bounds.size.width, 60))
view.backgroundColor = UIColor(red:0.40, green:0.40, blue:0.40, alpha:1.0)
let profileImageView = UIImageView(frame: CGRectMake(20, 5, 50, 50)) // Change frame size according to you...
profileImageView.image = UIImage(named: "profile.png") //Image set your
view.addSubview(profileImageView)
let LabelStatus = UILabel(frame: CGRectMake(0, 0, 200, 21))
LabelStatus.center = CGPointMake(120, 32)
LabelStatus.textColor = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1.0)
LabelStatus.font = UIFont(name: "BebasNeue", size: 24)
LabelStatus.textAlignment = NSTextAlignment.Center
self.view.addSubview(LabelStatus)
let switchStatus=UISwitch(frame:CGRectMake(195, 15, 20, 20))
func test() {
if (switchStatus.on == true){
LabelStatus.text = ("Available")
print("on")
}
if (switchStatus.on == false){
LabelStatus.text = ("Not available")
LabelStatus.center = CGPointMake(130, 32)
print("off")
}
}
switchStatus.on = true
switchStatus.setOn(true, animated: false);
switchStatus.addTarget(self, action: "test()", forControlEvents: UIControlEvents.ValueChanged)
switchStatus.onTintColor = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1.0)
switchStatus.thumbTintColor = UIColor(red:0.25, green:0.25, blue:0.25, alpha:1.0)
self.view.addSubview(switchStatus);
return view
}
And this is what it currently looks like.
How can I make the switch edit the label next to it?
You are getting the 'unrecognized selector' error because you are incorrectly targeting the test function.
In this line
switchStatus.addTarget(self, action: "test()", forControlEvents: UIControlEvents.ValueChanged)
You are trying to find a function test on self, but test is a function within the table view's viewForHeaderInSection function, not a function on self.
Additionally, the selector syntax has changed from a String to the new #selector syntax.
To fix this, move the test function to be a function on self. You will also need to be able to reference your switchStatus and LabelStatus objects, so you could move these to be declared as members of your view controller as well.
So at the end you should end up with something like this:
class BackTableViewController: UITableViewController {
let LabelStatus = UILabel()
let switchStatus = UISwitch()
func test() {
// update the label here
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
// ...
switchStatus.addTarget(self, action: #selector(BackTableViewController.test), forControlEvents: UIControlEvents.ValueChanged)
// ...
}
}
Change that line of code, your syntax for the selector is not correct:
switchStatus.addTarget(self, action: #selector(BackTableViewController.test), forControlEvents: UIControlEvents.ValueChanged)

Add two buttons in footer in the same row

hello I want to add two buttons on my ViewController programmatically like this
What I have done is this
func createButton(buttonTitle: String,buttonAction: Selector) -> UIButton{
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame)/2, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = UIColor().blueColor() //top
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
footerView.addSubview(bottomButton!)
return footerView
}
At the moment it only prints one button. for second button I am doing this
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
bottomButton2 = createButton("Delete", buttonAction: "Delete")
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}
This code is not printing two buttons. just printing only one
I think the problem is that both buttons have the same position, so one is showing above the other.
Try this:
func createButton(buttonTitle: String,buttonAction: Selector, buttonNumber : Int) -> UIButton{
let backgroundColor = buttonNumber == 0 ? UIColor.blueColor() : UIColor.orangeColor()
let space : CGFloat = 5
let button = UIButton(type: UIButtonType.System) as UIButton
let width = (CGRectGetWidth(self.view.frame) - space)/2
let xPos = buttonNumber == 0 ? 0 : width + space
button.frame = CGRectMake(xPos, 0, width, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
// button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = backgroundColor
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
And then add it like so:
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish", buttonNumber: 0)
bottomButton2 = createButton("Delete", buttonAction: "Delete", buttonNumber: 1)
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}

set button on bottom of static tableView

hello I want to set the programmatically created button at bottom of static tableView. The problem I am having is the botton stays at the bottom on smaller phones(5s) which is completely fine. But on 6s Plus it shows white area underneath the button. Meaning the button is slightly above from the ground or above from edge of the bottom.
This is how I am setting the button
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
footerView.backgroundColor = UIColor.redColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
buttonNext.backgroundColor = UIColor.blueColor()
footerView.addSubview(buttonNext)
footerView.layoutIfNeeded()
return footerView
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50
}
It sounds like you want a footer at the bottom of the table, rather than at the end of the section. In this case you should use the table's tableFooterView property. You could do this with the following code in viewDidLoad (or elsewhere):
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
footerView.backgroundColor = UIColor.redColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
buttonNext.backgroundColor = UIColor.blueColor()
tableView.tableFooterView = footerView

How to change the title and action of a programmatically created UIButton on some condition

I have created a UIButton programmatically on my ViewController. I want to perform different actions on the same button depending on the condition and want to change the title as well.
First I create the button like this:
func createButton(buttonTitle: String,buttonAction: Selector) -> UIButton{
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(0, 0, 414, 65)
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = UIColor().blueColor() //top
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
Then I am showing like this
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height))
if(active == true){
bottomButton = createButton("UNPUBLISH", buttonAction: "unPublishToServer")
}else if(active == false){
bottomButton = createButton("PUBLISH", buttonAction: "publishToServer")
}else{
bottomButton = createButton("Request", buttonAction: "requestItem")
}
footerView.addSubview(bottomButton!)
return footerView
}
then on certain messages from server or conditions I am changing the button like this
func publishTripToServer(){
dispatch_async(dispatch_get_main_queue()) {
self.bottomButton?.setTitle("UNPUBLISH", forState: UIControlState.Normal)
}
}
func unPublishTripToServer(){
dispatch_async(dispatch_get_main_queue()) {
self.bottomButton?.setTitle("PUBLISH", forState: UIControlState.Normal)
}
}
The problem I am having is first it shows some background color behind the title when I click publish or unpublish. the second issue is button is not changing the action.
I'm not exactly sure what you mean for the background color issue.
But for your button, does something like this not work?
func publishTripToServer(){
self.bottomButton = createButton("UNPUBLISH", buttonAction: "unPublishToServer")
}
func unPublishTripToServer(){
self.bottomButton = createButton("PUBLISH", buttonAction: "publishToServer")
}
I don't know why you previously were trying to update the button title on the background thread, but you shouldn't ever update ui elements asynchronously.
And the reason your button action wasn't changing is that you never told it to change - you just changed the title

Set own cell accessory type

I'd like to set my own cellAccessoryType (an image) in an UITableViewCell. Do you know how I can do this? I'm using Swift, Xcode 6.2 and iOS 8.2. Thank you for you help!
Try this:
// first create UIImageView
var imageView : UIImageView
imageView = UIImageView(frame:CGRectMake(20, 20, 100, 320))
imageView.image = UIImage(named:"image.jpg")
// then set it as cellAccessoryType
cell.accessoryView = imageView
PS: I strongly advise you to upgrade to XCode 6.3.2 and using iOS 8.3 SDK
I assume you would like to get tap on accessory view, so I provide this answer with button.
If not, use shargath's answer with imageView.
var saveButton = UIButton.buttonWithType(.Custom) as UIButton
saveButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
saveButton.addTarget(self, action: "accessoryButtonTapped:", forControlEvents: .TouchUpInside)
saveButton.setImage(UIImage(named: "check-circle"), forState: .Normal)
cell.accessoryView = saveButton as UIView
func accessoryButtonTapped(sender:UIButton) {
}
Swift 5 version of Shmidt's answer, plus using sender.tag to keep track of which row the button was clicked on:
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell",
for: indexPath)
let checkButton = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
checkButton.addTarget(self, action:#selector(YOUR_CLASS_NAME.checkTapped(_:)),
for: .touchUpInside)
checkButton.setImage(UIImage(named: "check"), for: .normal)
checkButton.tag = indexPath.row
cell.accessoryView = checkButton
return cell
}
#objc func checkTapped(_ sender: UIButton) {
print(sender.tag)
}
Swift 5 version, adding contentMode:
let imageView: UIImageView = UIImageView(frame:CGRect(x: 0, y: 0, width: 20, height: 20))
imageView.image = UIImage(named:Imge.Card.Link.download)
imageView.contentMode = .scaleAspectFit
cell.accessoryView = imageView
Xamarin.iOS version of Shmidt's answer
// Create the accessory
var accessory = new UIButton(UIButtonType.Custom);
accessory.Frame = new CGRect(0f, 0f, 24f, 24f);
accessory.AddTarget(accessoryButtonTapped, UIControlEvent.TouchUpInside);
accessory.SetImage(UIImage.FromBundle("check-circle"), UIControlState.Normal);
// Set the accessory to the cell
cell.AccessoryView = accessory as UIView;
void accessoryButtonTapped(object sender, EventArgs args)
{
}
SWIFT 5 solution
This example presents how to add simple button with SF Symbols to your accessory view.
inside cellForRowAt:
let plusButton = UIButton(type: .system)
plusButton.setImage(UIImage(systemName: "plus"), for: .normal)
plusButton.contentMode = .scaleAspectFit
plusButton.sizeToFit()
cell.accessoryView = plusButton
and instead of adding target to the button we can use delegate method from UITableViewDelegate
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
//handle logic here
}

Resources