How to use WCSession didReceiveMessage to receive different messages? - watchkit

I need to send different messages from different buttons. How do I use didReceiveMessage to receive them all?

didReceiveMessage being called
According to Apple:
didReceiveMessage is called every time a new mesage is received from
WatchConnectivity on Apple Watch.
You could use its argument to check the message, and you could add an entry to the dictionary passed by WCSession to check the source. For example if the argument is called message, you can use the following code:
Swift
switch message["source"] {
case "button1" : print("Source is button 1")
case "button2" : print("Source is button 2")
default : break
}
Objective-C
switch (message[#"source"]){
case #"button1" : NSLog(#"Source is button 1"); break;
case #"button2" : NSLog(#"Source is button 2"); break;
}
So you could use one didReceiveMessage method to receive all different messages from different buttons.
Conclusion
1- didReceiveMessage is called every time a message is coming.
2- You could use its argument to check the message.
3- You could use one didReceiveMessage method to receive all different messages from different buttons.

Related

Drop / skip messages - C++ Actor Framework (CAF)

Using the C++ Actor Framework (CAF), I want to be able to skip / drop messages. E.g. incoming messages are being received at 100Hz. I only want the receiving actor to process messages at 1Hz (skipping 99 messages per second).
Does CAF provide any native functionality to do this?
Thanks.
There is support for both skipping and dropping. Skipping leaves messages in the mailbox, allowing actors to process it some later point after changing their behavior. Dropping is generally viewed as an error (unexpected messages).
The mechanism to do is in CAF is via default handlers. CAF dispatches any message that was not processed by the current behavior to a "fallback", which then decides what to do with the unmatched input.
You can override this handler however you want, but CAF also offers standard implementations to choose from:
skip: leaves the message in the mailbox. This message gets automatically re-matched later.
drop: considered an error. Terminates the receiver with an unexpected_message error, also sending an error message to the sender.
print_and_drop: like drop, but also prints an error to stderr (this is the default).
CAF also comes with examples showcasing how to use these handlers, e.g., https://github.com/actor-framework/actor-framework/blob/master/examples/dynamic_behavior/skip_messages.cpp. If you are looking for a "silent" drop that discards the message without an error:
caf::skippable_result silent_drop(scheduled_actor*, message&) {
return caf::message(); // "void" result
}
All that being said, if all you are looking for is simply checking that some amount of time has passed before processing the next message: why not just leave the message handler early?
caf::behavior my_actor(caf::stateful_actor<my_state>* self) {
return {
[](const my_input& x) {
if (!self->state.active())
return;
// ...
}.
};
}
Here, the idea is that active returns true only if some amount of time has passed since last processing a message.

How to make an action connection for multiple buttons in xcode10?

I am wondering how do we make an action connection for multiple buttons in Xcode10. Just ONE CODE for ALL buttons.NOT SEPARATE.
For example, we have 7 music key buttons, and we want to make one action connection for all 7 of them, and then continue to code to make the code know which key is being exactly pressed. As the code that I posted in this question, how do we make " #IBAction func notePressed(_ sender: UIButton)" this line? Not by typing, by clicking and dragging.
Another example is, we have "true" and "false", two buttons. We want to make just one action connection for these two buttons in ViewController.swift.
I know how to make one action connection for a single button, but when it comes to multiple buttons, I do not know how to do. I use xcode10
I have tried to hold the command and select all the buttons at the same time, and then hold the control key and try to drag all the buttons from the mainStoryBoard to my swift code, but it seems that I only created an action connection for on button in this way.
#IBAction func notePressed(_ sender: UIButton)
{
let selectedNote : String = soundArray[sender.tag - 1]
playSound(inputNote : selectedNote)
}
If you find the connected actions part in the First Responder part in the storyboard, you are able to connect it one by one as the screenshot.

Do I need to cancel StreamSubscriptions that don't assign to a variable?

Here are 2 different ways I can listen to a stream. The top one gives no IDE warning about cancelling a subscription. The bottom one does.
// No IDE warning about cancelling subscription
_loginBloc.state.listen((state) {});
// "Cancel instances of dart.async.StreamSubscription"
StreamSubscription s = _loginBloc.state.listen((state) {});
If I use the first method, do I need to cancel the subscription somehow, or will it dispose of itself?
There is no behavior difference between these two. You are running in to a limitation of the lint. That lint has a number of false positives and negatives.
In general if you aren't using the StreamSubscription returned from listen you should be using forEach instead.
If you know that the Stream will end before whatever is listening doesn't care about it anymore there isn't any need to explicitly cancel. Where you want to be sure to cancel is if there is a point in time where the listener no longer cares about the result - say because it's a widget which is no longer being displayed.

How do I dismiss a WKInterfaceController that was presented with contextForSegue?

I have a WKInterfaceController with a WKInterfaceTable that lists some events a user has recorded in my app.
A user can tap a row of the table to see more details about that event. To accomplish this, I've overridden contextForSegue(withIdentifier:in:rowIndex:) on the WKInterfaceController that contains the table, so tapping a row modally presents a detail view of that row in a new WKInterfaceController called EventDetailController.
The modal presentation is defined on the Storyboard. I can't use push presentation because the WKInterfaceController with the WKInterfaceTable is a page among multiple instances of WKInterfaceController at the top level of my app.
Here's the main issue:
Within the EventDetailController, there's a Delete button to destroy the record that the table row represents.
When a user taps the Delete button, I present an alert that allows the user to confirm or cancel the delete action.
Once the user confirms the record deletion, I want to dismiss the EventDetailController since it's no longer relevant, because it represents a deleted record.
Here's the IBAction defined on EventDetailController that gets called when the Delete button is tapped:
#IBAction func deleteButtonTapped(_ sender: WKInterfaceButton) {
let deleteAction = WKAlertAction(title: "Delete", style: .destructive) {
// delete the record
// as long as the delete was successful, dismiss the detail view
self.dismiss()
}
let cancelAction = WKAlertAction(title: "Cancel", style: .cancel) {
// do nothing
}
presentAlert(withTitle: "Delete Event",
message: "Are you sure you want to delete this event?",
preferredStyle: .alert,
actions: [deleteAction, cancelAction])
}
The problem is that watchOS doesn't seem to allow this. When testing this code, the EventDetailController does not dismiss. Instead, an error message is logged in the console:
[WKInterfaceController dismissController]:434: calling dismissController from a WKAlertAction's handler is not valid. Called on <Watch_Extension.EventDetailController: 0x7d1cdb90>. Ignoring
I've tried some weird workarounds to try to trick the EventDetailController into dismissing, like firing a notification when the event is deleted and dismissing the EventDetailController from a function that's called from an observer of the notification, but that doesn't work either.
At this point I'm thinking there's some correct way I'm supposed to be able to dismiss a WKInterfaceController, or in other words reverse the contextForSegue(withIdentifier:in:rowIndex:) call, but I don't know what it is.
When I call dismiss() directly in the IBAction, instead of in a WKAlertAction handler, it works fine, but I don't like this implementation since it doesn't allow the user to confirm the action first.
I feel like an idiot, but I figured out the solution.
The answer was in Apple's WKInterfaceController.dismiss() documentation the whole time (emphasis added):
Call this method when you want to dismiss an interface controller that you presented modally. Always call this method from your WatchKit extension’s main thread.
All I had to do differently was call self.dismiss() on the main thread.
Here's my updated code for the delete action, which now works as expected:
let deleteAction = WKAlertAction(title: "Delete", style: .destructive) {
// delete the record
// as long as the delete was successful, dismiss the detail view
DispatchQueue.main.async {
self.dismiss()
}
}
Hopefully this will save someone else some troubleshooting time!

Qt pass data between multiple forms

I am new to Qt and understands the concept of signal and slots. However I am not able to implement it.
My objective is:
Form1 has a button Config. So when I click Config it should open another form Form2( without closing Form1) and send a string strData to Form2.
In Form2 I set some value in the string strData. Then I click Ok button in Form2, Form2 should close and return back the string to Form1.
When the call returns back to Form1, it should continue from where it emitted the signal to invoke Form2.
Any help is highly appreciated.
You can't do this using signals/slots; the signal is emitted, and all of the connected slots are executed, and then the code continues from where the signal is emitted and eventually returns to the event loop. That's when your second form is actually shown and the user can respond to it, but by then, your code is long past where the signal was emitted.
What I believe you're looking for is the QDialog::exec method; use it in place of the signal. The basic pattern of the code is:
// This is the response to click on Config...
Form2Dialog form2;
form2.setSomeStringValue (some_value);
if (form2.exec() == QDialog::Accepted)
{
QString some_new_value = form2.newValue();
}
The Form2Dialog is a subclass of QDialog where you've added your own setSomeStringValue and newValue methods. (What you actually name these is up to you.)
The important thing is that the exec method blocks and doesn't return until the user selects OK or Cancel on the dialog, or closes it using the "close" button in the title bar (if there is one).

Resources