how to set up background view update in durandal - durandal

I develop some admin pannel in durandal and have some view which show actively mutating data.
How can i force this view to repeatedly update, say, once in T seconds?
just give me a link to some sample/doc page/methods.
thanks

Actually, if you will use observable variables (which are part of KnockoutJs, and part of Durandal) in your application - you will see changes immediately. KnockoutJs Observables Documentation
If you are already use observables but need to make some delay between updating observable and refreshing UI - you can use Rate-limiting observable notifications which are delaying update notification for observable variables.

Related

UI is rendered but screen is not painted unless touched

We are able to confirm that the render() method of our component is getting invoked. We also see that the data that needs to be shown is correctly passed in via props. However, the actual phone display won't repaint the updated UI until it is touched.
Interestingly this only happens in the production build not on the development builds of the app. Sigh.
We have seen this in the past when updates are done from InteractionManager.runAfterInteractions, but in this case we have removed every use of runAfterInteractions and are still seeing this behavior.
Using react native 0.57 but also seeing the same issue on 0.58.
I can provide more specifics if needed, but wanted to know if anyone has seen anything like this before and what if anything they did to fix such an issue.
I had this issue also when the content that should repaint was inside a 'ScrollView'. I refactored my code using a 'FlatList' instead of a 'ScrollView' and the problem disappeared.
It was a struggle, but I figured out what was happening.
TL;DR
The solution is to wrap your redux action dispatches inside a setTimeout(..., 0) whenever you are doing UI updates from a function passed to runAfterInteractions or from a Realm callback.
Some quick background:
I was dispatching a redux action inside a Realm callback. The action would in turn cause the UI to re-render, except the rendered UI would not repaint on screen until it was touched.
Similar behavior was observed when you dispatch redux actions from a callback passed to InteractionManager.runAfterInteractions. This makes sense because callbacks passed to runAfterInteractions wait for UI to do its thing and are then executed as a setImmediate batch. These callbacks were intended for heavy background jobs that would otherwise block UI rendering. So if one were to do UI rendering in such callbacks those would themselves get halted like a background job!
Solution:
The point of the realm callback is to notify you that some data has changed, so that you can re-render your UI. However, the realm callback was behaving like one passed to runAfterInteractions and so UI re-rendering was getting held up. I took a leap of faith and decided to move the Redux action dispatching code to a different queue, namely setTimeout. Here's what the fix looked like:
...
// assume this is in a callback passed to runAfterInteractions
// or in a realm callback
// PUT YOUR REDUX ACTION DISPATCHES IN A setTimeout
// callback
setTimeout(() => {
getFilteredCartAreas(dispatch, realm)
dispatch(new ActionCartAreaCardChanged())
}, 0)
...
The fix is to do the UI rendering logic inside a callback passed to setTimeout. Notice the zero delay; the goal is to simply move logic to a different queue that is not held up by UI interactions.

Should I use NSNotificationCenter to trigger a app refresh?

Background:
I currently have a NSTimer running in my AppDel class (I also have a method to calculate the amount of time my app spends in the background and adds it to the total, in case anyone brings this up).
The timer is checked at different intervals to see if it has reached 12 hours, at 12 hours the app needs to refresh its data from the server.
When this occurs, I need to display a UIAlert which when its button is pressed:
• Pops off view controllers to the first view controller.
This “refresh” should only be able to occur on 3 (specific)view controllers out of 7 within my app.
The Question(s):
Is NSNotifcationCenter sufficient for my requirements?
Where I would add an observer only to the view controllers I want this to occur on?
Is there a better approach I should be taking?
ya you can implement the NSNotifcationCenter approach but best alternative is to use custom delegate approach .By this way your app will work according to apple guidelines and memory utilisation of app is also less.
Using NSNotificationCenter is a good approach when you need to send information about some event (for example need of refreshing app) and you want to make as few changes as possible, without redesign all app architecture. I recommend you https://github.com/AllinMobile/AIMObservers because is created to facilitate the work with NSNotificationCenter and NSNotification.

Starting transitions before activate resolves

Is there a simple way to use Durandal's transitions to fade out an old view immediately, and fade in the new one once its activate function has resolved?
Here's some context:
I have a Durandal 1.2 SPA where most of the views' activate functions make service calls and return a promise as appropriate. This all works great, but transitions only run when loading is complete sometimes services can take few seconds to respond - leading to a poor user experience where you click on a link and it takes a few seconds before anything noticeable happens.
The solution is to animate away the old view immediately (before activate resolves) and then animate in the new view when activate is done. At the moment, every animated view corresponds to a route and I don't expect this to change. I've come up with and tested a few solutions that all work but seem less than ideal (and don't leverage Durandal's transition framework):
Manually animate away every view in its deactivate() and animate it back in via its viewAttached()
Bind the .page-host div's visibility to router.isNavigating (using a custom binding to handle the transition such as the fadeVisible example from the knockout site)
Manually subscribe to router.isNavigating and run custom logic when it changes
I've tried them all and so far I like the custom binding on the .page-host div the best since it involves the least amount of code, but it only works in my case because of my specific circumstances and isn't a generic solution.
This seems like exactly the sort of thing Durandal's transitions were created for. Is there a more elegant way to do this in Durandal using transitions (in 1.2 or the upcoming 2.0 release)?
I saw this question which seems to be asking something similar, but seems a little less specific and doesn't have a relevant answer.
Move your async logic out of activate and put it into viewAttached. This will allow the view to animate in immediately. Then, from viewAttached, you are safe to execute async code without breaking KO because the bindings have already been applied. (Note: viewAttached is renamed in 2.0 to attachedToParent.)
You can add handler for 'router:route:activating' event by adding next code into your shell.js:
router.on('router:route:activating').then(function () {
//fade out animation goes here;
//Usually that is changing of observable which will add/remove css class for your view (or shows loading overlay)
//Animation of view transition could be done by add class css3 animation.
});
And in case if you are using "loading" observable - in custom transition you can set this observable back to hide loading overlay:
if (context.bindingContext.$data && context.bindingContext.$data.isLoading && ko.isObservable(context.bindingContext.$data.isLoading )) {
composition.current.complete(function() {
context.bindingContext.$data.isLoading (true);
});
}

Is this a valid use of NSNotificationCenter

I come from a .NET web application background and have just started iOS development. The initial design of my app focuses around the NSNotificationCenter. I was reasonably happy with this until I saw various posts explaining how reaching for the NSNotificationCentre was a common newbie mistake.
Here is a simplified version of the problem I am trying to address:
My application is trying to show a list of messages that are populated using web service calls, think Facebook messaging.
When the app is first loaded it pulls a collection of messages from the server and displays them in a table to the user. The user can add new messages (which get sent back over the API) and the app can receive Push Notifications about new messages which are added to the feed.
The messages are never persisted to disk so I'm just using POCOs for the model to keep things simple.
I have a MessageFeedController which is responsible for populating the message feed view (in a storyboard). I also have a message feed model, which stores the currently retrieved values and has various methods:
(void) loadFromServer;
(void) createMessage: (DCMMessage*) message;
(void) addMessage: (DCMMessage*) message;
(NSArray*) messages;
(int) unreadMessages;
The current implementation I have is this:
Use case 1 : Initial Load
When the view first appears the "loadFromServer" method is called. This populates the messages collection and raises an NSNotificationCenter event.
The controller observes this event, and when received it populates the tableview
Use Case 2: New Message
When a user clicks the "add" button a new view appears, they enter their message, hit send and then the view is dismissed.
This calls the createMessage method on the model, which calls the API
Once we have a response the model raises the NSNotificationCenter event
Once again the MessageFeedController listens for this event and re-populates the table
Use Case 3: Push Message
A push notification is received while the app is open, with the new message details
The AppDelegate (or some other class) will call the addMessage method on the model, to add it to the collection
Once again, assuming the MessageFeed view is open, it re-populates
In all three cases the MessageFeed view is updated. In addition to this a BadgeManager also listens to these events which has the responsibility of setting the app icon badge and the tabbar badge, in both cases the badge number relates to the number of unread messages.
It's also possible that another view is open and is listening to these events, this view holds a summary of messages so needs to know when the collection changes.
Right, thanks for sticking with me, my question is: Does this seem like a valid use of NSNotificationCentre, or have I misused it?
One concern I have is that I'm not 100% sure what will happen if the messages collection changes half-way through re-populating the message table. The only time I could see this happening is if a push notification was received about a new message. In this case would the population of the table have to finish before acting upon the NSNotification anyway?
Thanks for your help
Dan.
In other words, you're posting a notification whenever the message list is updated. That's a perfectly valid use of NSNotificationCenter.
Another option is to use Key-Value Observing.
Your controller (and anyone else) can register as an observer to the "messages" property, and will be notified whenever that property changes. On the model side, you get KVO for free; simply calling a method named setMessages: will trigger the KVO change notification. You can also trigger the notification manually, and, if so desired, the KVO notification can include which indexes of the array have been added, removed, or changed.
KVO is a standardized way to do these kinds of change notifications. It's particularly important when implementing an OS X app using Cocoa Data Binding.
NSNotificationCenter is more flexible in that you can bundle any additional info with each notification.
It's important to ensure that your messages list is only updated on the main thread, and that the messages list is never modified without also posting a corresponding change notification. Your controller should also take care to ignore these notifications whenever it is not the top-most view controller or not on screen. It's not uncommon to register for change notifications in viewWillAppear: and unregister in viewWillDisappear:.
In my opinion using a delegate protocol pattern would be a much better fit for this scenario. Consider the scenario where your "api layer" needs used across many view controllers in an application. If another developer were to be introduced to your code, they would have to hunt around for notificationcenter subscriptions instead of just following a clean 'interface' like protocol.
That being said, your code will work just fine and this is a valid use of notification center. It is just my personal preference for 'cleaner' code to use a protocol based approach. Take a look around in the iOS SDK itself and you will see scenarios where Apple themselves use protocols and use notifications. I feel it is much more easy to comprehend and use the protocols than having to dig around and determine what I must listen to for a notification.
NSNotifications run the receivers code synchronously as soon as they are posted, so a new message during repopulation would join the back of that execution queue. On the whole it seems valid to me, and it keeps a reasonable degree of separation between The view controllers and the model.
Depending on the number of classes that are likely to want to listen for the same information arriving, you may want to use a delegate pattern, maybe keeping an dictionary of delegate objects, but I personally don't feel as though this scales so well, and you also have to take care of nil-ing out delegates if a page is dealloced to avoid crashes. To sum up, your approach seems good to me.

Using NSManagedObjectContextObjectsDidChangeNotification

In many of my UIViewControllers, I update certain controls based on the state of my data. For example, I might have an edit button on a UITableViewController that should only be enabled when there is one or more items. Or perhaps I want to limit the number of items that can be added, and disable the 'add' button otherwise.
Every time I add or delete an item (or take any other action that can add/remove items), I have to remember to update any controls that might need enabling/disabling. This is trivial for the most part, but doesn't feel comfortable - there is a lot of repetition, and I have to remember to add the calls to updateControlEnabled (or whatever) whenever I add new functionality that might affect the data.
And then I noticed NSManagedObjectContextObjectsDidChangeNotification. Reading the docs, it looks like I can receive a notification whenever something changes in my managed object context. This seems ideal, but I have a few questions:
Is this an appropriate use of
NSManagedObjectContextObjectsDidChangeNotification?
Should I anticipate any performance impact if a controller
subscribes to these and parses each one to see if it needs to update
the UI? I will be checking the userInfo for every change, instead of
only those that I know I will care about.
Where should I subscribe to the notifications? My UIViewController has a
reference to the context, which helps, but I don't know where to
subscribe (loadView? viewDidLoad? init?) such that the view
controller will always have one and only one subscription.
The view controller will continue to receive and process notifications
when it's offscreen - enabling and disabling controls as the
data model is affected from elsewhere. Is this ok?
I guess I'm mostly just wondering if anyone else uses this approach and if so, what their experience is.
Q) Is this an appropriate use of NSManagedObjectContextObjectsDidChangeNotification?
A) Yes - I used it on OSX for a similar purpose.
Q) Should I anticipate any performance impact if a controller subscribes to these and parses each one to see if it needs to update the UI? I will be checking the userInfo for every change, instead of only those that I know I will care about.
A) NO - it will normally be a very small set of objects - ones that were directly changed.
Q) Where should I subscribe to the notifications? My UIViewController has a reference to the context, which helps, but I don't know where to subscribe (loadView? viewDidLoad? init?) such that the view controller will always have one and only one subscription.
A) Well, you cannot affect the UI til the view shows - so probably viewDidLoad or viewWillAppear. The problem with the later is you may get it a few times depending on push/pops, so maybe I'd do it in viewDidLoad.
Q) The view controller will continue to receive and process notifications when it's offscreen - enabling and disabling controls as the data model is affected from elsewhere. Is this ok?
A) Sure - when the view reappears all the elements will be setup correctly.
What you want to do is a classical use of that notification. Just check the thread it comes in on - if its not the mainThread then you want to make all your changes in a block posted to the mainThread.