iOS: Swift: UISlider editingDidEnd not being called - ios

I've set up a function for editing did end with a slider, but it doesn't look like it's being called. I've thrown a print statement into it, and a breakpoint. Is there something else that needs to be done to trigger a function when my user lets go of the slider?
#IBAction func sliderEditingDidEnd(sender: UISlider) {
print("did end");
}

Use the event "Value Changed". If you just want updates for the final value, alter UISlider.continuous
var slider = UISlider()
slider.continuous = false
//add slider to view
#IBAction func valueChanged(sender: UISlider) {
println("Value changed.")
}
//prints "Value changed." once upon releasing slider.
If the slider needs to be continuous, you can implement an event for UIControlEvent.TouchUpInside.
Or in code:
override func viewDidLoad() {
super.viewDidLoad()
mySlider.addTarget(self, action: "userReleasedSlider:", forControlEvents: UIControlEvents.TouchUpInside)
// Do any additional setup after loading the view, typically from a nib.
}
func userReleasedSlider(slider: UISlider) {
print("User released slider.")
}

I think what you are trying to do is to get the notification when the value is changed. Then you have to set event to 'Value Changed' not 'Editing Did End'.

If you set both Touch Up Inside and Touch Up Outside to point to your #IBAction then you can get the function to fire when the user finishes sliding and keep the slider as continuous.

Related

Programmatically Tap View

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)
}

programmatically toggle UISwitch, prevent IBAction function

I have a UISwitch, when it is toggled, the IBAction is triggered:
#IBAction func mySwitchToggled( switch_: UISwitch ) {
...
}
So, when user toggle the switch, the above function is invoked.
At some point, I also need to toggle the switch programmatically:
mySwitch.setOn(false, animated: false) //It triggers the IBAction function
The above code triggers the IBAction function.
For my special requirement, I need to have the IBAction function being triggered when user toggled the switch but when programmatically toggle the switch, I don't want the IBAction function get triggered.
How to programmatically toggle my switch without triggering the IBAction function?
hmmm... intersting. It gets triggered in my project
I don't have enough rep to comment so I post it as a answer going at PPL his answer, did you checked your outlets. Most of the time the storyboard keeps the connection to your other IB action which causing them to trigger both. (removing existing outlets and implementing the value change, should work)
Here is another (some what hacky) solution, by implementing a skip boolean when calling the switch by code:
var skip: Bool = false
#IBAction func mySwitchToggled( switch_: UISwitch ) {
guard !skip else {
skip = false
return
}
// do stuff
}
func someFunc() {
// called it like this
skip = true
mySwitch.setOn(false, animated: false)
}
Please find below, Here swcValueChanged is Value Changed function and it will call only when user toggle the switch.
#IBAction func swcValueChanged(_ sender: Any) {
print("Switch value changed")
}
Here on button tap event, above function will not call.
#IBAction func btnTapped(_ sender: Any) {
swcTemp.setOn(!swcTemp.isOn, animated: true)
}

Detect button being tapped - iOS

I'm working with objective-c and I want to detect when the user is tapping a button (not when he tapped it, but the actual moment when is being taped until he stops).
Is there any method? I'm not finding it if there's any.
Thanks
Using touchDown event you can make an action while your button is pressed
Example
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func testing(_ sender: Any) {
label.textColor = UIColor.red
}
#IBAction func testingCancel(_ sender: Any) {
label.textColor = UIColor.black
}
#IBAction func testingUpInside(_ sender: Any) {
label.textColor = UIColor.black
}
}
Here (UIControlEvents) are all events of control/actions (with their brief description)
UIControlEventTouchCancel: A system event canceling the current touches for the control.
UIControlEventTouchDown: A touch-down event in the control; when button is tapped/pressed.
UIControlEventTouchDownRepeat: A repeated touch-down event in the control; for this event the value of the UITouch tapCount method is
greater than one.
UIControlEventTouchDragEnter: An event where a finger is dragged into the bounds of the control.
UIControlEventTouchDragExit: An event where a finger is dragged from within a control to outside its bounds.
UIControlEventTouchDragInside: An event where a finger is dragged inside the bounds of the control.
UIControlEventTouchDragOutside: An event where a finger is dragged just outside the bounds of the control.
UIControlEventTouchUpInside: A touch-up event in the control where the finger is inside the bounds of the control.
UIControlEventTouchUpOutside: A touch-up event in the control where the finger is outside the bounds of the control.
Use Touch Down to get button tapping event.
Yes it is possible
Button has following events to listen
You can use Touch Down

How to detect when user finished moving Range slider in Swift

I use this is Range slider in my project. How use it.
I want to detect, when user finished moving Range slider.
I tried to use function SliderAction(sender: RangeSlider), but I get each moving points in the slider. I think I need to use this function: func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?), but it is doesn't work.
How can I make it?
To detect when user finished moving the range slider you can add a controlevent to your slider , you can add it programatically :
mySlider.addTarget(self, action: "sliderDidEndSliding:", forControlEvents: .UIControlEventTouchUpInside)
then you have to do your logic the recieving methode .
func sliderDidEndSliding(sender: UISlider) {
}
For swift 3 I used this:
mySlider.addTarget(self, action: #selector(self.sliderDidEndSliding), for: .touchUpInside)
func sliderDidEndSliding() {
// process stuff
}
reading values is done with:
#IBAction func mySlider(_ sender: Any) {
}
based on this example viewcontroller, you should check the value sender.selectedMax value changed should be equal to the one you set in storyboard for that slider view
You need to override endTrackingWithTouch. It'll get called when tracking ends by the underlying machinery, giving you a chance to respond.
Be sure and call the super of this during your version of endTrackingWithTouch so the the parents classes can do their bit.
Swift 4
slider.addTarget(self, action: #selector(sliderDidEndSliding), for: .touchUpInside)
and add
#objc func sliderDidEndSliding(sender: UISlider) {
}

Click button in a UIViewController that was loaded a subView (UIView)

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.

Resources