Prevent UISegmentedControl from sending action method automatically - uikit

I'm programming an app for tvOS and am using a UISegmentedControl. My issue is that as I'm scrolling through items, it sends its action method as soon as I remain on an item for a second or two. I would like to disable this behaviour and rather fire the action only if user clicks it.
Does anyone know how to do it?

I had the same problem with my tvOS app and solved with this:
#IBOutlet weak var searchSegmentedControl: UISegmentedControl!
override func viewDidLoad() {
let tap = UITapGestureRecognizer(target: self, action: #selector(didClickSegmentedSearchButton))
tap.numberOfTapsRequired = 1
view.addGestureRecognizer(tap)
}
func didClickSegmentedSearchButton() {
switch searchSegmentedControl.selectedSegmentIndex {
case 0:
// Restaurant
case 1:
// Hotel
case 2:
// Attraction
case 3:
// Shopping
default:
// Unknown
}
}

Related

How to detect a Pan Gesture inside a NSTouchBarView

Is it possible to detect a finger pan on a NSTouchBarView?
Sorry for the lack of code but I don't even know where to start.
MacOS is not made for finger touches but the TouchBar is but I do not see how to do it on a NSTouchBarView
I don't know specifically about using NSTouchBarView, but using a pan recognizer in a touch bar usually works like this: create a view, then create a NSPanGestureRecognizer (don't forget to set the target and action) then add the recognizer to the previously created view. Finally, create your NSCustomTouchBarItem and assign the previously created view to the item's view. Quick example in Swift:
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? {
switch identifier {
case NSTouchBarItemIdentifier.yourCustomItem:
return itemWithRecognizer(identifier: identifier)
default:
return nil
}
}
func itemWithRecognizer(identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem {
let customView = NSView()
customView.wantsLayer = true
let recognizer = NSPanGestureRecognizer()
recognizer.target = self
recognizer.action = #selector(doSomething)
customView.addGestureRecognizer(recognizer)
let item = NSCustomTouchBarItem(identifier: identifier)
item.view = customView
return item
}
func doSomething() {
// gesture was activated
}

GPUImage does not update when MotionShake detected

I have a fuction, which after a shake, resets all sliders to their defaults and calls -proccesImage after the slider's value has been changed. The problem is that each of the sliders do, in fact, get reset to the default positions but GPUImage does not update the view.
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?)
{
if(event?subtype) == UIEventSubtype.MotionShake{
for slider in sliders!
{
slider.value = myDefault(slider.tag);
sliderValueChanged(slider)
}
}
}
#IBAction func sliderValueChanged(sender: UISlider)
{
switch sender.tag{
case 1:
filter.temperature = CGFloat(sender.value)
case 2:
dliter2.exposure = CGFloat(sender.value)
case 3:
//more cases..
default:print("...")
}
gpuimage?.processImage(); // I know for a fact that this gets called, but doesn't update the view :(
}
Note that I also have an identical functionality attached to UITap gesture. When a user double taps a slider, it goes back to its default value and updates right away. Code below works perfectly fine.
func resetSlider(sender: UITapGestureRecognizer)
{
let tag = (sender.view?.tag)!;
sliders![tag].value = myDefault(tag)
sliderValueChanged(sliders![tag]);
}
So I haven't found a reason why it wasn't updating. But I solved the issue by removing all targets and calling viewWillAppear() after that, so that it would re-add the targets just as if it was a brand new image.

Add completion handler to presentViewControllerAsSheet(NSViewController)?

I am attempting to present a sheet configuration view (AddSoundEffect) for my main window/view controller (I'm using storyboards), and when the configuration view controller is dismissed, take the values entered in the AddSoundEffect view and pass that back to the main view. My current code in the main view controller:
presentViewControllerAsSheet(self.storyboard!.instantiateControllerWithIdentifier("AddSoundEffect") as! AddSoundViewController
And in the AddSoundViewController.swift file, the code to dismiss it is:
self.dismissViewController(self)
To pass the data, I have a class-independent tuple that I save data to. How do I add a completion handler to presentViewControllerAsSheet, and (optionally) is there a better way to pass the data between view controllers?
Setup: Xcode version 6.4, OS X 10.10.4
Delegation pattern is the easiest way for you.
// Replace this with your tuple or whatever data represents your sound effect
struct SoundEffect {}
protocol AddSoundViewControllerDelegate: class {
func soundViewController(controller: AddSoundViewController, didAddSoundEffect: SoundEffect)
}
//
// Let's say this controller is a modal view controller for adding new sound effects
//
class AddSoundViewController: UIViewController {
weak var delegate: AddSoundViewControllerDelegate?
func done(sender: AnyObject) {
// Dummy sound effect info, replace it with your own data
let soundEffect = SoundEffect()
//
// Call it whenever you would like to inform presenting view controller
// about added sound effect (in case of Done, Add, ... button tapped, do not call it
// when user taps on Cancel to just dismiss AddSoundViewController)
//
self.delegate?.soundViewController(self, didAddSoundEffect: soundEffect)
// Dismiss self
self.dismissViewControllerAnimated(true, completion: {})
}
}
//
// Let's say this controller is main view controller, which contains list of all sound effects,
// with button to add new sound effect via AddSoundViewController
//
class SoundEffectsViewController: UIViewController, AddSoundViewControllerDelegate {
func presentAddSoundEffectController(sender: AnyObject) {
if let addSoundController = self.storyboard?.instantiateViewControllerWithIdentifier("AddSoundEffect") as? AddSoundViewController {
addSoundController.delegate = self
self.presentViewController(addSoundController, animated: true, completion: {})
}
}
func soundViewController(controller: AddSoundViewController, didAddSoundEffect: SoundEffect) {
// This method is called only when new sound effect is added
}
}
Another way is to use closures:
// Replace this with your tuple or whatever data represents your sound effect
struct SoundEffect {}
//
// Let's say this controller is a modal view controller for adding new sound effects
//
class AddSoundViewController: UIViewController {
var completionHandler: ((SoundEffect) -> ())?
func done(sender: AnyObject) {
// Dummy sound effect info, replace it with your own data
let soundEffect = SoundEffect()
//
// Call it whenever you would like to inform presenting view controller
// about added sound effect (in case of Done, Add, ... button tapped, do not call it
// when user taps on Cancel to just dismiss AddSoundViewController)
//
self.completionHandler?(soundEffect)
// Dismiss self
self.dismissViewControllerAnimated(true, completion: {})
}
}
//
// Let's say this controller is main view controller, which contains list of all sound effects,
// with button to add new sound effect via AddSoundViewController
//
class SoundEffectsViewController: UIViewController {
func presentAddSoundEffectController(sender: AnyObject) {
if let addSoundController = self.storyboard?.instantiateViewControllerWithIdentifier("AddSoundEffect") as? AddSoundViewController {
addSoundController.completionHandler = { [weak self] (soundEffect) -> () in
// Called when new sound effect is added
}
self.presentViewController(addSoundController, animated: true, completion: {})
}
}
}
Or many other ways like sending notification, ... Whatever suits your needs. But delegation pattern or closures is the best way to go in this specific case.
I missed that your question is about NSViewController. This example is for iOS, but same pattern can be used on OS X without any issues.
The easiest way to detect sheet opening or closing is to use the Sheet Notifications:
class ViewController: NSViewController, NSWindowDelegate {
override func viewDidLoad(){
NSApplication.sharedApplication().windows.first?.delegate = self
}
func windowDidEndSheet(notification: NSNotification) {
}
func windowWillBeginSheet(notification: NSNotification) {
}
}

Xcode_OSX/Swift_NSPopUpButton.

I am incredibly new to this, so please keep that in mind!
I've been at this all night, watched countless videos/haunted
countless forums...I can't find one single answer!
I am trying to make a basic popup menu in Swift/OSX What I need to figure out is:
How can I add more than the 'three items' to this menu
Whatever is selected in the popup, for that info to send an integer
value to another number.
I very much would appreciate your help, Thanks.
A NSPopupButton is a container for a bunch of NSMenuItem objects so to add an item you can use
func addItemWithTitle(_ title: String!)
The NSMenuItem gets constructed for you by the call.
and as you may wish to start from scratch you can use
func removeAllItems()
To clean existing items from the button.
There are also other methods around moving and removing menu items from the button.
A NSPopupButton is-a NSControl so you can use var action: Selector to set the action sent when an item is selected and var target: AnyObject! to control which object receives the message. Or just wire it up in Interface Builder.
protocol FooViewDelegate{
func itemWithIndexWasSelected(value:Int)
}
class FooViewController: NSViewController {
#IBOutlet weak var myPopupButton: NSPopUpButton!
var delegate: FooViewDelegate?
let allTheThings = ["Mother", "Custard", "Axe", "Cactus"]
override func viewDidLoad() {
super.viewDidLoad()
buildMyButton()
}
func buildMyButton() {
myPopupButton.removeAllItems()
myPopupButton.addItemsWithTitles(allTheThings)
myPopupButton.target = self
myPopupButton.action = "myPopUpButtonWasSelected:"
}
#IBAction func myPopUpButtonWasSelected(sender:AnyObject) {
if let menuItem = sender as? NSMenuItem, mindex = find(allTheThings, menuItem.title) {
self.delegate?.itemWithIndexWasSelected(mindex)
}
}
}
All the button construction can be done in Interface Builder rather than code too. Remember that you can duplicate items with CMD-D or you can drag new NSMenuItem objects into the button.

Add gestures and animation in Swift

I am making an application which is inspired from iOS8 voice messages and trying to add 'gestures and animations(like slide left and cancel the record,slide rightto Upload the voice record.)' but it doesn't work at all.Here is the code snippet below.
// Swipe left and cancel
let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: "swipeLeftCancel")
swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.Left
self.view.addGestureRecognizer(swipeLeftGesture)
// Swipe right and upload
let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: "swipeRightUpload")
swipeRightGesture.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRightGesture)
session.requestRecordPermission({(granted: Bool)-> Void in
if granted {
self.setupRecorder()
} else {
println("Permission to record not granted")
}
})
func swipeLeftCancel(sender: UISwipeGestureRecognizer) {
// slide left and cancel
}
func swipeRightUpload(sender: UISwipeGestureRecognizer) {
// slide right and upload
)
Whole code(before adding UISwipeGestureRecognizer) is in here ー> https://github.com/chansuke/GoForIt
Anyone give some advice?
Your action selectors should be named swipeLeftCancel: and swipeRightUpload::
let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: "swipeLeftCancel:")
The colon at the end is necessary because your functions accept an argument sender. This is because in Objective-C, your method would be declared as - (void)swipeLeftCancel:(id)sender, and its selector would be swipeLeftCancel:. In Swift this makes a lot less sense, but it's just something you have to remember when you use selectors.
// adding Gesture:
let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action:"swipeLeft")
swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.Left
self.view.addGestureRecognizer(swipeLeftGesture)
Where swipeLeft is your selector fired on Gesture action.

Resources