Are `setHidden` messages to `WKInterfaceObject` guaranteed to be delivered in order? - watchos-2

If I call:
someButton.setHidden(true)
someButton.setHidden(false)
someButton.setHidden(true)
Is it guaranteed that button will be hidden now?
I know that in watchOS 1, these messages would be sent from iPhone to Watch, but in watchOS 2 it should run on the same device - but given that there is no way to check if object is hidden, I have doubts about what's guaranteed.
Thanks

The button will be hidden, since true is the last value which will take effect.
From the WKInterfaceObject Class Reference:
WatchKit coalesces the data from all setter method calls made during the same run loop iteration and transmits it to the device at the end of the run loop. If you set an attribute to different values in the same run loop iteration, only the last value is transmitted.
The button will never be hidden, shown, then hidden again, as the previous messages do not get applied by the run loop. Only the last of those messages has any effect, and only one update is made to the button.

Related

iOS UI Not Updating

I am using Firebase Firestore listeners and am updating 2 tabBarItem badges after fetching.
The badges were updating fine and appeared on the UI until I added a fourth listener, all of which I need. So in total I have 4 asynchronous listeners.
As I've put breakpoints, each listener is working correctly and fetching the right data, and at the point of setting the badgeValue, I see the correct count assigned that was a result of the fetch.
However, the UI either entirely doesn't update and show the badgeValue or inconsistently does.
Is this a memory issue with all the listeners firing off? Any thoughts on what I could possibly implement as a workaround? I've already tried things like DispatchQueue.main.async, and even delaying it, but all have shown inconsistent results.
Any help would be appreciated..

Remove previously posted notification

Posting notifications from the NSNotificationCenter on the certain button click event Hence When I have rapid button events The notification is being called that many times leads to the many problems. I want to cancel the previous posted notification when rapid events happening. How to do with below code.
func buttonClick() {
// I want to cancel the previous Event here
NSNotificationCenter.defaultCenter().postNotificationName("Event", object: self)
}
UPDATE:
Let me explain clearly what I want actually I have one observer method when a button click is happened from that I want to post the some notifications to control some UI elements like changing the button image. The problem is When I hit the button rapidly observer getting called many times as well my notifications being posted on the same count hence UI is blinking I can't have control on the Observer on the button click event I have only control over the posted event from my side.
Any help much appreciated.
NSNotificationCenter.post() is synchronous. It does not return until all the observers have performed their actions. So there is no way to cancel it; there is no queue.
If you are generating a lot of notifications very close to each other (especially within the same run-loop cycle), you can coalesce them using NSNotificationQueue with enqueueNotification. Generally something like:
NSNotificationQueue.defaultQueue().enqueNotification(note, postingStyle: .whenIdle)
That said, if this is tied to a button click (a human interaction), then the notifications are likely very far apart in computer terms. Half a second is an eternity in computer terms. If that's the case, you're likely better-off controlling this first at the UI, by disabling the button until you're willing to accept another click (for example with button.enabled = false).
It is possible to write a wrapper that coalesces operations over any arbitrary period, but this is likely to be confusing in your case, because the user will be able to click something that the system will ignore. If that's still what you want, I'll see if I can find an example of a coalescing trampoline (I've written them in ObjC, but I don't have a Swift example on hand).

VoiceOver stops announcing UIAccessibilityPostNotification messages

I'm working on an application that is designed to speak some information about the data it captures from video as the video is being captured. Right now I'm using UIAccessibilityPostNotification to get VoiceOver to say what I want it to say with UIAccessibilityAnnouncementNotification. This typically works great until the user attempts to navigate between my UI controls. After swiping back and forth along the elements (a menu and an info button) a little bit, the application stops speaking the persistent notifications. I also find that posted notifications do not announce if I background the app and then return it to the foreground
I have a magic tap handler that pauses and resumes that persistent announcement and once it is triggered (which also triggers speech about the last rendered info), manually triggered speech works again and upon resume from a second magic tap the announcements continue as if nothing had stopped.
Is there a mechanism to get voiceover to reliably resume speaking without requiring some other kind of user-screen input in between?
Fortunately this was, following the rule of "it's probably your own code's fault first", my own fault. A timer was inadvertently changing the state of things and what I was using to track when to announce was being set to an invalid state which stopped the announcements.

Where to update the UI of a notification widget just once

In my Notification Center Today Extension/Widget I need to update a portion of the UI every time Notification Center is activated. It never needs to update while Notification Center is in use, nor while it's in the background. In what method should I place that code?
viewDidLoad and viewWillAppear are both called every time it will be displayed, for example if you scroll up and down they will be called again, so that's too often.
widgetPerformUpdateWithCompletionHandler is not called at all before it's displayed for the first time it seems (at least with iOS 8.2 beta), and this method is automatically called whenever iOS feels like it to update the UI even when it's in the background which is not appropriate either.
loadView is only called a single time, never to be called again unless the widget is removed from memory. So if you open Notification Center and view the widget then dismiss Notification Center and reopen it later, it may not call that method again depending on whether or not it's been cleared from memory.
I'd just use viewDidLoad and not worry about the possibility of multiple calls. Unless the method takes a long time to run, there's no reason not to do it that way. [And if it does take a long time to run, your today extension is going to suck, so fix that.]
If for some reason you only want it to happen once, add a BOOL ivar to the class. Set it to YES in initWithCoder: Then in viewDidLoad, check that value. If it's YES, do your update and set the value to NO. If it's already NO, skip your update.

arc4random always returns same initial value on app start

I am developing an application for the iphone that, in viewDidLoad, calls arc4random to get a random number. My problem is that each time the application starts, it gets the same number from arc4random. I ought to point out that I see this behaviour when I test the app on my iphone device and start the application from the device touchscreen. If I run the app on the device from xcode, then I see different random numbers.
Any help or advice would be appreciated. Thanks.
arc4random does not need seeding and should not be returning the same results each time you call it.
From your comments, it seems to me that your code is not being executed each time your app comes to the foreground. Remember that when you press the home button your app is not terminated by default. It will enter the background, and will resume when you tap the icon again.
If your code is inside viewDidLoad, it will only be called once which means your variable will not be updated and will contain the same value each time you inspect it. When you run from Xcode your app will be fully terminated each time and you will get the expected behaviour.
You should probably put your code in viewWillAppear: or viewDidAppear: so it is called whenever the view appears on screen, rather than once when your view initially loads.

Resources