swift add switch programmatically in side menu - ios

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)

Related

addSubview not working after converting

I upgraded xcode from 7.3.1 to 8 and converted to swift 2.2, other than the storyboard being a mess everything worked except adding a UIView programatically.
This was working fine before, now nothing shows up at all and there are no errors. Any ideas?
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//create view
let vw = UIView()
vw.backgroundColor = UIColor(red: 0.9137, green: 0.9176, blue: 0.9216, alpha: 1.0) /* #e9eaeb */
//create label inside view
let label: UILabel = UILabel()
label.frame = CGRectMake(0, 0, 200, 28)
label.textAlignment = NSTextAlignment.Left
label.textColor = UIColor.grayColor()
label.font = label.font.fontWithSize(13)
if !clearSearch {
label.text = " Recent Searches"
} else {
label.text = " Search Results"
}
vw.addSubview(label)
//create button inside view
let button: UIButton = UIButton()
button.frame = CGRectMake(self.view.frame.size.width - 45, 0, 40, 28)
button.titleLabel?.font = UIFont.systemFontOfSize(13)
button.setTitle("Clear", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(deleteSearches), forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor(red: 0.3216, green: 0.7176, blue: 0.5333, alpha: 1.0), forState: UIControlState.Normal)
vw.addSubview(button)
return vw
}
Thanks for any help.
Looks like this is now required.
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 28
}

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
}

Selector method of UIButton not called during animation

I have dynamically created buttons on a dynamic view and later I add that dynamic view to main view.
Everything is working well except that the selector method of UIButton is not called.
var baseView:UIView?
override func viewDidLoad() {
super.viewDidLoad()
randomizeButtons()}
func randomizeButtons(){
baseView = UIView(frame:CGRectMake(view.bounds.origin.x + 10, view.bounds.origin.y + 50, view.bounds.size.width, view.bounds.size.height-20))
let viewWidth = baseView.bounds.size.width;
let viewHeight = baseView.bounds.size.height;
baseView.userInteractionEnabled = true
let i = GlobalArrayofUsers.count
var loopCount = 0
while loopCount < i{
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
print(userBaseView.frame)
userBaseView.backgroundColor = UIColor.redColor()
userBaseView.userInteractionEnabled = true
userBaseView.layer.cornerRadius = 45
userBaseView.clipsToBounds = true
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.greenColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: #selector(ViewController.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
button.setTitle("hello", forState: .Normal)
button.userInteractionEnabled = true
userBaseView.addSubview(button)
baseView.addSubview(userBaseView)
print("button frame is\(button.frame)")
baseView.bringSubviewToFront(userBaseView)
loopCount += 1
}
}
baseView.subviews.forEach { (users) in
UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat], animations: {
users.center.y += 10
}, completion: nil)
}
view.insertSubview(baseView, atIndex: view.subviews.count)
}
func handleTapEventofBtn(sender: UIButton!) {
// handling code
}
Any idea why my selector method is not called? It is due to animation. How can i handle it.
SOLUTION: Allow userinteraction in UIAnimationOptions
The problem is that you are trying to click an object that is being animated. From the docs:
During an animation, user interactions are temporarily disabled for
the views being animated. (Prior to iOS 5, user interactions are
disabled for the entire application.)
But worry not, the solution is very easy, just call your animation with the option .AllowUserInteraction. For example (with your code):
UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat,.AllowUserInteraction], animations: {
users.center.y += 10
}, completion: nil)
Have you tried this way:
for _ in 0...5{
// generate new view
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
userBaseView.backgroundColor = UIColor.redColor()
// add button to view
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.yellowColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: #selector(self.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
button.setTitle("hello", forState: .Normal)
userBaseView.addSubview(button)
}
self.view.addSubview(userBaseView)
All you need is to create userBaseView before cycle, then create buttons in cycle and add them to userBaseView, after that just add userBaseView to self.view or where you need to add it. In your example you create userBaseView in every iteration of the loop.
I think the problem could be here:
userBaseView.addSubview(button)
// add new view containing button to self.view
self.view.addSubview(userBaseView)
}
userBaseView.addSubview(button)
baseView.addSubview(userBaseView)
First you add userBaseView to self.view in the loop:
// add new view containing button to self.view
self.view.addSubview(userBaseView)
then add it to baseView:
baseView.addSubview(userBaseView)
Can you post how it looks like in IB?
The action has a parameter so the selector signature is actually takeActionBtn:
(note the colon at the end).
You need to change that or the button will try to call a version of the function with no parameter which doesn't exist.
button.addTarget(self, action: "button:",forControlEvents: UIControlEvents.TouchUpInside)
func button(sender: UIButton!) {
// handling code
print("1")
}
// hi. your problem is in the selector line. try this:
for _ in 0...5 {
// generate new view
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % self.view.frame.size.width - 90) , abs(CGFloat(arc4random()) % self.view.frame.size.height - 120), 90, 90))
userBaseView.backgroundColor = UIColor.redColor()
// add button to view
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.yellowColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
button.setTitle("hello", forState: .Normal)
userBaseView.addSubview(button)
self.view.addSubview(userBaseView)
}
// tested with xcode 7.2
func buttonAction() {
print("working")
}

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

UIButton action doesn't work

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

Resources