Equivalent of NSNotificationCenter for React Native? - react-native

Been searching for a while to see if there's anything built-in or any 3rd party modules for adding NSNotificationCenter style functionality to a react-native app.
Specifically, I want modules to "listen" for certain notification types, and I will be able to "broadcast" events from other parts of the app (from within javascript).
The closest thing I've found is this from 3 days ago: https://stackoverflow.com/a/32004456/798533, but it only supports sending NSNotificationCenter events, not listening.

Ok, I figured out an acceptable solution. Here's what I ended up doing in case anybody has the same question:
I installed the npm package backbone-events-standalone, which is just the extracted events code from Backbone.js.
In the main entry point for my app (index.ios.js), I included the following code by the imports:
var BackboneEvents = require('backbone-events-standalone');
// global event bus
window.EventBus = BackboneEvents.mixin({});
Inside any component's componentDidMount, you can now add event listeners, like so:
componentDidMount() {
window.EventBus.on('yourEventName', this.yourEventHandlerFunc);
}
And you can fire events thusly:
window.EventBus.trigger('yourEventName', 'optional event info');
This could also easily be combined with NSNotificationCenter events using something like the solution linked in the original question.
If you're removing components, it would be wise to also remove the event listeners, but I'll leave that as an exercise for the reader.

Related

Vue: Showing that the function does not exist when I have defined it the relevant store

I am currently working on a simple app to store workout routines in Nuxt 3 and Appwrite. The link to the source code is here.
After logging in and adding in some workouts in the app's UI, whenever I try to call the deleteWorkout function, I get an error in the console saying that the function is not defined, whereas I have clearly defined in the workoutStore. I can't seem to figure out the reason for the same.
The same can be seen in the given screenshot.
Console on clicking the delete button
PS:
Most probably the error should be originating from either /pages/workouts.vue, /components/WorkoutDetails.vue or /stores/workout.js.
I am using Appwrite to manage the back-end of the web app, and the instructions to setup the same can be found in the README.md. (Though I don't think the error I am facing is related to the same.)
In your code the problem is, you declear your deleteWorkout() function outside of the actions block in workout.js file.
Make sure all your functions in the workout store are inside the actions block. Then it will be accessable from the vue component

iOS9 storyboard what is unhandled action (handleNonLaunchSpecificActions)?

I've noticed the following error popping up in the console when running my app on iOS 9 when using a storyboard. I'm using xCode7. Is this something I need to be concerned about?
-[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:] ** unhandled action -> <FBSSceneSnapshotAction: 0x176bfb20> {
handler = remote;
info = <BSSettings: 0x176a5d90> {
(1) = 5;
};
}
There is nothing wrong with your code. This is a logging message internal to Apple, and you should file a radar about it.
There are two hints that show that this is probably Apple's code:
The underscore leading the method name _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion is a convention indicating that the method is private/internal to the class that it's declared in. (See this comment.)
It's reasonable to guess that the two letter prefix in FBSSceneSnapshotAction is shorthand for FrontBoard, which according to Rene Ritchie in "iOS 9 wish-list: Guest Mode" is part of the whole family of software related to launching apps:
With iOS 8, Apple refactored its system manager, SpringBoard, into several smaller, more focused components. In addition to BackBoard, which was already spun off to handle background tasks, they added Frontboard for foreground tasks. They also added PreBoard to handle the Lock screen under secure, encrypted conditions. [...]
I have no idea what the BS prefix in BSSettings is for, but
BS is shorthand for BackBoard Settings, and an analysis of this log message would indicate that it's not anything you did, and you should file a radar with steps to reproduce the logging message.
If you want to try and grab a stack trace, you can implement the category linked to here. Some would argue that overriding private API is a bad idea, but in this case a temporary injection to grab a stack trace can't be too harmful.
EDIT:
But, we still want to know what this action is. So I put a breakpoint on -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion] and started printing out register values and found a class called FBSceneImpl which had a whole bunch of information about my application:
We are able to find out which private method is called next (stored in the program counter, instruction pointer, register 15.)
I tried finding the un-handled FBSceneSnapshotAction referenced in the log, but no dice. Then, I subclassed UIApplication, and overrode _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion. Now I was able to get at the action directly, but still, we don't know what it is.
Then, I looked at the FBSceneSnapshotAction again. Turns out it has a superclass called BSAction.
Then I wrote a tool similar to RuntimeBrowser and looked up all of the subclasses of BSAction. It turns out that there's quite a list of them:
The two method names we have (one from the log and one from the program counter on the devices) indicate that these actions are used under the hood for passing actions around the system.
Some actions are probably sent up to the app delegate's callbacks, while others are handled internally.
What's happening here is that there is an action that wasn't handled correctly and the system is noting it. We weren't supposed to see it, apparently.
AFAIK, the info above is related to iOS during snapshot the screen (i suppose for double click home multitask related behaviour).I deeply investigated my application and seems that it does not get any side behaviours. You can safely ignore it, for now.
You can use the following gist simple category to test yourself against the calls to the above function:
I have figured it out, it will happen when you have IBAction method declared in .h or .m file but you have not bind it to any control.
.m example:
- (IBAction)click:(id)sender{
}
but not assigned this method to any control in storyboard.
haven't find out why it happens in my app, but at least you can catch the exception, if you want to keep this from popping up in your log pane. It's not a solution, but it might give you more insight why it is happing by inspecting any of the arguments that are passed in the catch.
swift 2 version:
import UIKit
extension UIApplication {
func _handleNonLaunchSpecificActions(arg1: AnyObject, forScene arg2: AnyObject, withTransitionContext arg3: AnyObject, completion completionHandler: () -> Void) {
//whatever you want to do in this catch
print("handleNonLaunchSpecificActions catched")
}
}

pygtk vlc player does not play next track

I'm writing a small custom player based on libvlc. I've used much of the code from https://github.com/hartror/python-libvlc-bindings/blob/master/examples/gtkvlc.py that plays a single track just like I need.
Now I want to swtich to another track after previous has finished. To do that I catch callback "EventType.MediaPlayerEndReached" and in callback handler I write code:
<------>def endCallback(self,event):
<------><------>fname = vlc_controller.GetNextTrack()['url']
<------><------>self.w.set_title(fname)
<------><------>self.vlc.player.set_mrl(fname)
<------><------>self.w.set_title('after set_mrl')
<------><------>self.vlc.player.play()
<------><------>self.w.set_title('after play')
Now when this code gets executed it stucks on self.vlc.player.set_mrl(fname) and does not go any further and as a result I see NO NEXT TRACK.
I've tried different variations of this code using (vlc.stop(), vlc.set_media instead of vlc.set_mrl) but nothing works
Finally....
I think the best choise is to make multi threaded application on python
2 Threads:
Main thread - gtk.loop and displaying video an some other thinks
Additional thread that makes media switching.
For some time I was afraid of multithreading but now I know that this was the best way to do this task
For those facing similar issue in C# (Xamarin), per VLC documentation, calling the VLC object from an event tied to the object may freeze the application. So they said to use the code below inside the trigger event.
ThreadPool.QueueUserWorkItem(_ => PlayNext());
An example would be calling the code above inside the EndReach event.
Where PlayNext() is your own custom method to handle the next action you want to execute.
I struggled with this for about a day before seeing that portion of the documentation.

CAsyncSocketEx + console application ?

I have console applicaiotn that currently uses CAsyncSocket.
I need to implement SSL so after some searching I found this project: http://www.codeproject.com/Articles/3915/CAsyncSslSocketLayer-SSL-layer-class-for-CAsyncSoc
For some reason same simple code that works fine on GUI code does not work in console app.
Has anyone exp. with CAsyncSslSocketLayer ?
Thanks.
CAsyncSocketEx uses a window as a sort of cheap thread to handle the event notifications that come from select(). Unfortunately, if you don't have a message loop, then the window which it creates will not receive these events.
http://support.microsoft.com/kb/90975
This article explains that a call to CreateWindow() needs to be called from a thread which has a message loop. And if you don't, then anything sent via PostMessage() won't get there.
I've recently started to tinker with this -- I want to remove the annoying hidden window and replace it with a normal thread. Their code relies on WSAAsyncSelect() in order to receive socket events... to a window. Yuk!
It's been a while since I had the same problem, but if I remember correctly, to use CAsyncSocket in a console app you need to add something like DECLARE_CONSOLEAPP (first two links shown below) to your console app. This should give your console a message pump to generate the socket notifications (OnReceive, etc.) GUI apps have these pumps but console apps don't, generally. The third (msdn) link below might also apply, it has more info and a different way.
If these still don't work, you should put breakpoints in your socket code and make sure your socket isn't instantiated in a thread or callback other than the main console app (the one that now has the message pump).
I think googling around for 'CAsyncSocket WinApp' or 'CAsyncSocket console app' would show more.
http://www.codeguru.com/cpp/misc/misc/consoleapps/article.php/c243/Console-app-using-MFC.htm
http://troels.knakkergaard.dk/code.htm
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/a6f1b72a-21d8-4046-a3dc-d7d29ece2ef6

How to monitor global modifier key state (in any application)?

I'm using some Carbon code in my Cocoa project for handling global key events (shortcuts) from other applications. Currently I have setup a kEventHotKeyReleased event handler and I can successfully obtain hot keys when my application is not active. That triggers some operation in my application.
The problem I have with the behavior of kEventHotKeyReleased is:
Say for example I press the Cmd-Shift-P key combination. As soon as I release the "P" key the hot key event is triggered. I need to be able to trigger the event (or manually trigger it) when all of the keys are unpressed (i.e: the Cmd and Shift keys are released too).
It is easy to monitor for hot keys but I have seen nothing for monitoring individual keystrokes. If I could monitor the modifier key states I would be in business.
Any hints on how to do this?
Thanks in advance!
UPDATE:
I've tried using kEventRawKeyUp and kEventRawKeyModifiersChanged but while kEventHotKeyReleased works those two don't even though I set them up in the exact same way as kEventHotKeyReleased.
EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line
The globalHotKeyHandler method is called for kEventHotKeyReleased, but not for kEventRawKeyUp for some reason I can't seem to grasp. Here's what my globalHotKeyHandler method looks like:
OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
NSLog(#"Something happened!");
}
Is there an additional call that needs to be made or something else I forgot?
N.B: At first glance, it seems like it could be that Access for Assistive Devices is disabled but it is not. So I'm pretty clueless.
UPDATE 2:
I investigated a bit on the CGEventTap Leibowitzn suggested and I came up with this setup:
CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);
... and the callback:
CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(#"KeyUp event tapped!");
return event;
}
As you can see I'm using kCGEventKeyUp as the mask for the event tap but somehow I'm receiving mouse down events ??!??
UPDATE 3:
Ok forget that, I overlooked the line in the doc that said to use CGEventMaskBit(kCGEventKeyUp) for this parameter, so the correct call is:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);
I'm still having a problem though: modifier keys do not trigger the kCGEventKeyUp...
UPDATE 4:
Ok forget that again... I'm bound to answer to my own questions 5 minutes after asking them today huh!
To intercept modifier keys, use kCGEventFlagsChanged:
CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);
So in essence I got the key and modifier key state detection working, but I'm still interested in knowing why kEventRawKeyUp doesn't work...
N.B: Also note that I'm developing on Tiger with the goal of having support for new and older versions of the OS as much as possible. CGEventTap is 10.4+ only so I'll be using this for now but a backwards-compatible solution would be welcome.
One option is to use EventTaps. This lets you monitor all keyboard events. See:
http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate
Unfortunately event taps will stop working if an application is requesting secure input. For example Quicken.
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
This is not global. This installs the handler only when your own application is active, and (I believe) after the Carbon Event Manager's own event filters.
You need to use InstallEventHandler, which takes an event target as its first parameter (InstallApplicationEventHandler is a macro that passes the application event target).
For events that occur while your application is not active, the target you want is GetEventMonitorTarget(). For events that occur while your application is active, the target you want is GetEventDispatcherTarget(). To catch events no matter what application is active, install your handler on both targets.
Nowadays, though, I'd just use CGEventTaps, as Leibowitzn suggested.