How to catching doubleClick events from NSOutlineView in ViewController? - swift

I am trying to catch doubleClick events from my NSOutlineView to be passed to my ViewController. My idea is to catch doubleClick events and to get the selected row from my OutlineView
What I did so far was subclassing the NSOutlineView in order to overwrite mouseDown
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
if event.clickCount >= 2 {
...
}
}
That works well however I don't know how to pass this event to my ViewController. The ViewController is already implementing the NSOutlineViewDelegate protocol.
I guess that the solution is not far away but somehow I am stuck.

UPDATED
Although you can set up NSGestureRecognizer for single click and NSClickGestureRecognizer for double clicks in OSX, You should probably be using the doubleAction property of the NSOutlineView directly.
Here's an example of how to set it up
This comes from a another of the Wenderlich tutorials, and there is a good discussion on SO already

Related

Is there a way to get a generic call to any UIButton's method selector?

I've recently come across the technique of swizzling. It looks like it's not a super common practice to use and I can understand the drawbacks I keep seeing listed for it. But as it's a thing that we can use in swift, I was hoping I could throw together something in a playground or practice project.
The idea I had was to use swizzling for analytics purposes. At this point, just to print off what the user is actually doing. I can't really think of interactions the user might make besides tapping buttons on their screen. I figure, I might be able to swizzle UITapGestureRecognizer and make it run a function tracking tap position, etc. But that's too much information for me. I just want to know when a button is tapped. So I think the only thing I need to swizzle is the UIButton. But we set the selector for UIButtons or we set them up as IBActions.
So my question is, Is there a way to get a generic call to any button's method selector? That way, I can swizzle the button in one place. Make it run the analytics and then call the primary function all without actually changing my code in my UIViewController classes directly.
I would post my attempts, but their rather sensical and I couldn't get anything to even run.
Is this a possibility?
You can try swizzling sendAction(_:to:for:) in UIControl. UIControl calls this whenever an event happens for every target-action pair.
extension UIControl {
// call this at an early point in your app lifecycle
static func swizzle() {
if let originalMethod = class_getInstanceMethod(UIControl.self, #selector(sendAction(_:to:for:))),
let swizzledMethod = class_getInstanceMethod(UIControl.self, #selector(swizzled_sendAction)) {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
#objc func swizzled_sendAction(_ action: Selector,
to target: Any?,
for event: UIEvent?) {
swizzled_sendAction(action, to: target, for: event)
if self is UIButton {
// do some analytics things
}
}
}
Caveats:
Since this method is called for every target-action pair, this means that this only works if all your buttons have exactly one target-action pair, and only for the event touchUpInside (a "tap"). In other words, for each button, you only call addTarget once, or add one connection in the storyboard for touchUpInside.
If a button does not have any target-action pairs, then tapping it does nothing. The swizzled method will not be called.
If a button has multiple target-action pairs for touchUpInside, then tapping it would cause the swizzled method to be called multiple times.
If a button has target-action pairs for events other than touchUpInside, then triggering those events would also cause the swizzled method to be called, though this can be prevented to an extent if you carefully check the UIEvent parameter.
To be honest, I would rather just subclass UIButton, instead of swizzling. Make a subclass that does something like this upon its creation:
addTarget(self, action: #selector(doAnalytics), for: .touchUpInside)
...
#objc func doAnalytics() {
// ...
}

How to detect swiping or selecting event in XLPagerTabStrip swift

I am going to detect the swiping or selecting tab event in XLPagerTabStrip library in Swift 4.
I only need to get the tab index whenever selected tab is changed.
So I have checked library in Github but not found any good solutions.
thanks.
So I didn't find a solution from the library itself but, I used viewWillDisappear and for every time you swipe away of the view this function will be called.
Should be written as follows in your child view controller:
override func viewWillDisappear(_ animated: Bool) {
//Do your thing here
}
You can read more about this callback function here.
You can simply override updateContent
override func updateContent() {
super.updateContent()
// your code ....
}

Shake Gesture not Working

I have a project set up using SWReveal for the slide out menu.
When I place a motion ended override function it never seems to be called even though everything else in the class loads (indicated with the 'loading'.
I have had a good play around and found that if I change the segue to the page to a 'show' segue the code functions as I would expect it to.
However when I use a custom segue with the SWReveal as the class the motion ended does not work.
I have attached a screen shot to help describe the issue.
Any help much appreciated.
You need to override canBecomeFirstResponder method.
override func canBecomeFirstResponder() -> Bool {
return true
}

SWRevealViewController conflict with UISlider

I currently facing an issue trying to delegate SWRevealViewController panGestureRecognizer method in one of my view.
When i slide my UISlider, the panGesture interfer and open the sidemenu instead to move my slider.
i tried to delegate the panGesture and it works well, but if i quit my view and go to an other, the pangesture is not functionnal anymore, and i can't reveal my sidemenu from my second view.
My code :
class Search : UIViewController, UIGestureRecognizerDelegate{
#IBOutlet weak var sliderprice: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
self.revealViewController().panGestureRecognizer().delegate = self
}
override func viewDidAppear(animated: Bool) {
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (touch.view == self.sliderprice){
return false
}
else{
return true
}
}
}
While this is an old question, I'll answer it anyways, maybe for someone coming from Google search it will be helpful.
After many hours of research and thinking, finally I was able to come up with multiple solutions to this problem.
The Lazy
This solution is not recommended, but working, so I decided to list it.
Before setting self as self.revealViewController().panGestureRecognizer()'s delegate, store the original self.revealViewController().panGestureRecognizer().delegate to a property, and when you leave the screen at viewWillDisappear(), set self.revealViewController().panGestureRecognizer().delegate back to the one you stored in viewDidLoad(). So in the end it gets back its original delegate. Tampering with delegates like this is never really recommended, but I said, it works.
The Nicer One
I consider this still not the best solution, but we are getting there. Find a class, a controller that you use in the whole application and gets called when you start the app. Here set the SWRevealViewController's panGestureDelegate to this class, and overwrite the gestureRecognizerShouldBeginmethod appropriately (see below).
The Best One - (in my opinion)
Now this is the best and most clear solution.
For the time being (May, 2018) the last commit to SWRevealViewController was in 2015.
Fork the original project ( https://github.com/John-Lluch/SWRevealViewController ) or simply copy the two necessary files (SWRevealViewController.m and SWRevealViewController.h) and place them into a separate folder to handle 3rd party libraries. Then you can remove SWRevealViewController from your Podfile. Don't forget to fix your imports for SWRevealViewController where you have it.
Now you are free to modify the files. What I suggest is the following.
Go to SWRevealViewController.m and implement the following method:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
return ![touch.view isKindOfClass:UISlider.class];
}
If the touched view is a UISlider (or a custom class that inherits from UISlider) the gesture won't begin, meaning the pan gesture will no longer be conflicted with the UISlider's pan gesture.
I seriously hope I could help anyone out there as this problem was a pain in my back for quite some time now.

Swift, unable to reload chat window using JSQMessagesViewController

My app allows users to view another users info by tapping their avatar, at which they can block that user so that their message content is not visible.
What is the best way when returning to the chat view to clear the messages and reload them?
This would allow my blocking code to work on the fly. Currently it works when I dismiss the chat view and return but not when jump to another view and then back to the chat view.
Ive tried self.collectionView!.reloadData() but that does not do anything.
All you need is to implement
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.collectionView?.reloadData()
}
that is called when you come back from an already instantiated view.
Call the reloadData method after a delay.
self.performSelector(#selector(self.delayReload), withObject: nil, afterDelay: 0.1)
func delayReload() {
self.collectionView.reloadData()
}
Hope this will help you.
Sincerely,
Harri.