I created a UISwitch on storyboard and tried to drag it to controller to create an action but there were only Insert Outlet / Insert Outlet Collection 2 options available? Why did this happen and how can I create action for UISwitch? I am using Xcode8.1
PS: The UISwitch was added on a container view
When "ctrl" + drag, you should see something like:
You should choose "Action" and let the event -which is by default- "Value Changed".
However, if you can't see this (and I assume you should, or there is somehow a problem), you can add an event programmatically to the switch outlet:
In viewDidLoad() method, you need to add:
override func viewDidLoad() {
// ...
mySwitch.addTarget(self, action: #selector(mySwitchTapped), for: .valueChanged)
// ...
}
mySwitchTapped(mySwitch: UISwitch) method:
func mySwitchTapped(mySwitch: UISwitch) {
if mySwitch.isOn {
} else {
}
}
Related
We want Lyft button touch event because I am working in analytics, so, I need how many people choose Lyft but I can't put UIView click event. I try below code.
let gesture = UITapGestureRecognizer(target: self, action: #selector(self.checkAction))
cell.lyftButton.addGestureRecognizer(gesture)
How can i achieve this?
You can directly assign a selector method to lyftButton e.g
lyftButton.addTarget(self, action: #selector(lyftButtonAction(_:)), for: .touchUpInside)
#objc
func lyftButtonAction(_sender: UIButton) {
//Do your action
}
To retrieve the LyftButton, you'll need to fetch the button inside the Lyft view, after retrieving it, I tried to add another target to it which was your 'checkAction' method, but for some reason it is not being called. One workaround solution is:
On Auto Layout, created a transparent button on top of the Lyft Button View, let's callet it 'Transparent Lyft Button': Example (I've embeded in another view because it was on a stackView);
On the code, retrieved the button with the above method, held it in a variable, let's call it 'requestLyftButton' and disabled it.
Created an IBAction for the 'Transparent Lyft Button' that triggers the method 'self.checkAction' that you've created and also calls requestLyftButton.sendActions(for: .touchUpInside), which triggers the original Lyft SDK action.
To Retrieve Lyft UIButton:
#IBOutlet weak var lyftButton: LyftButton!
#IBOutlet weak var transparentLyftButton: UIButton!
var requestLyftButton: UIButton?
func retrieveLyftButton(in view: UIView) {
for view in view.subviews {
if let lyftBtn = view as? UIButton {
lyftBtn.isEnabled = false
requestLyftButton = lyftBtn
} else {
retrieveLyftBtn(in: view)
}
}
}
transparentLyftButton IBAction to trigger your method + lyft sdk original action:
#IBAction func requestLyft(_ sender: UIButton) {
if let lyftBtn = requestLyftButton {
checkAction() // Your method
lyftBtn.sendActions(for: .touchUpInside)
}
}
I hope that you can understand what was done, if you have any questions, just let me know.
I have created a custom view that is to be used as a radio button with images and text. I need to be able to load the saved selection when the controller loads. I set my listeners this way:
for button in genderButtons {
button.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(genderTapped(_:))))
}
#objc private func genderTapped(_ sender: UITapGestureRecognizer) {
for button in genderButtons {
button.select(sender.view! == button) // Toggles the button to display selected/deslected state.
...
}
}
The problem is that I can't find a way to tell the view to select. I tried making the gesture recognizer and object, but it doesn't have any methods I can use to trigger it. The 'buttons' aren't actually buttons, they're views, so I can't send an action event.
How can I select the correct button with code?
Just call genderTapped directly, handing it the gesture recognizer already attached to the desired "button".
For example, if thisGenderButton is the one you want to "tap", say:
if let tap = thisGenderButton.gestureRecognizers?[0] as? UITapGestureRecognizer {
genderTapped(tap)
}
You can add this method in your customView like this,
Class CustomView: UIView {
public func select(_ value: Bool) {
self.backgroundColor = value ? .green: .red
}
}
and then in below method you can call select for the tapped view.
#objc private func genderTapped(_ sender: UITapGestureRecognizer) {
(sender.view as? CustomView)?.select(true)
}
I just want to write one or two lines of code on button click like
print("Button Clicked")
for this i dont want to create a seperate function and call via selector
as
action: #selector(BtnKlkFnc(_:))
I want to simplify like
action: { action in print("Button Clicked")}
I also tried
#selector({print("Button Clicked")})
Can anyone help me to simplify this
Am new to stackoverflow and do not have enough reputations yet, So kindly vote for my question up, so i can vote for your ans
Short answer: You can't do that. Button actions are part of the target/action mechanism built into Cocoa/Cocoa touch. It's based on selectors, and you must create a named method and use it's selector. You can't use a Swift closure as a button action.
EDIT:
Note that it is possible to create a custom subclass of UIButton that has a closure property and invokes that closure when the button is tapped. What you'd do is to make the button's init method set itself up as the target of a touchUpInside event and invoke a method of the button that in turn invokes your closure (after making sure the closure property isn't nil.)
EDIT #2:
Note that it is pretty straightforward to create a custom subclass of UIButton that sets itself up as the target for button presses and keeps a closure.
Here is a sample implementation:
class ClosureButton: UIButton {
var buttonClosure: ((UIButton) -> Void)?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addTarget(self, action: #selector(handleTap(_:)), for: .touchUpInside)
}
#objc func handleTap(_ sender: UIButton) {
if let buttonClosure = buttonClosure {
buttonClosure(sender)
} else {
print("No button closure defined")
return
}
}
}
And in your view controller:
override func viewDidLoad() {
super.viewDidLoad()
button.buttonClosure = { _ in
print("You tapped the button")
}
}
I'm trying to add a UIView subview into a UIViewController, and that UIView has a UISwitch that I want the user to be able to toggle. Based on the state, a UITextField's value will toggle back and forth. Here is the subview (InitialView):
import UIKit
class InitialView: UIView {
// All UI elements.
var yourZipCodeSwitch: UISwitch = UISwitch(frame: CGRectMake(UIScreen.mainScreen().bounds.width/2 + 90, UIScreen.mainScreen().bounds.height/2-115, 0, 0))
override func didMoveToSuperview() {
self.backgroundColor = UIColor.whiteColor()
yourZipCodeSwitch.setOn(true, animated: true)
yourZipCodeSwitch.addTarget(ViewController(), action: "yourZipCodeSwitchPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.addSubview(yourZipCodeSwitch)
}
}
If I want to have it's target properly pointing at the below function, where should I either set the target or include this function? I tried:
Setting the target in the UIViewController instead of the UIView
Keeping the function in the UIView
Here's the function:
// Enable/disable "Current Location" feature for Your Location.
func yourZipCodeSwitchPressed(sender: AnyObject) {
if yourZipCodeSwitch.on
{
yourTemp = yourZipCode.text
yourZipCode.text = "Current Location"
yourZipCode.enabled = false
}
else
{
yourZipCode.text = yourTemp
yourZipCode.enabled = true
}
}
And here is where I'm loading it into the UIViewController:
// add initial view
var initView : InitialView = InitialView()
// Execute on view load
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.addSubview(initView)
}
Any help is much appreciated - thanks!
Yeah, the didMoveToSuperView() placement doesn't make much sense. So you're creating a random, totally unconnected ViewController instance to make the compiler happy but your project sad. Control code goes in controllers, view code goes in views.
You need in your real ViewController:
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(initView)
// Note 'self' is the UIViewController here, so we got the scoping right
initView.yourZipCodeSwitch.addTarget(self, action: "yourZipCodeSwitchPressed:", forControlEvents: .ValueChanged)
}
Also, .TouchUpInside is for UIButtons. Toggle switches are much more complicated, so their events are different. Touching up inside on a toggle switch's current setting can and should do nothing, whereas touchup inside on the opposite setting triggers the control event above. iOS does all the internal hit detection for you.
I'm very new to Swift and Xcode so this question may sound elementary to some.
I have a button and a label in a custom table view cell. I'm trying to change the value of the label text when the button click is detected.
Currently, I'm setting the button.tag = indexPath.row (as shown in the code below) and I'm catching it in the btn_click function.
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: "btn_click:", forControlEvents: UIControlEvents.TouchUpInside)
How can I access the label contained within the same cell as the button clicked so I can change the value of the label text? Can I use indexPath.row to return the correct label object?
You don't need to use the tag to accomplish your goal, in your CustomTableViewCell class you have to set an action to the button and a outlet to the label inside the cell, something like this :
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
// action to tap the button and change the label text
#IBAction func tappedButton(sender: AnyObject) {
self.label.text = "Just Clicked"
}
}
You can the manually set the action for the button and the outlet for the label in the Interface Builder, you don't need to set in code.
Then, when you make a tap inside the button in the cell the label it's changed only inside the cell.
I hope this help you.