smartGWT onDraw when is it executed? - notifications

When is executed the onDraw method of a DynamicForm exactly?
When I first load my page (a puremvc.Mediator page) and draw my DynamicForm with an onDraw method, I enter in this onDraw method. Then I destroy the view component, remove the Mediator from the Facade, and re-load the page. DynamicForm is being created again, the viewComponent too, but I don't enter in the onDraw method. Just as if the object has already been drawn! But the thing is it was destroyed, its parent too, and the parent of the parent, too.
What could be the problem?

OK, I got it.
The thing is that I use PUREMVC Mediator and Notification. On the first load, everything's good as the async method that returns data for DynamicForm C is sending the successful notification AFTER I have already created the VLayout B, and thus the addMember method adds and displays the DynamicForm C.
On the second load, I use the data that has already been gathered from DB, so no async method is being processed and the notification arrives BEFORE I create VLayout B, so basically the DynamicForm C is NOT being drawn.
My solution : I reordered some lines of code to make sure I always call the method that sends data via Notification (whether from DB or stocked) AFTER of the page creation.

Related

ReactiveCocoa + Progress Indicator

I have a class, EventPresentationController, that displays data in an Event object. The class needs to be passed an Event object, but sometimes that object needs to be downloaded from a remote service first. I don't want the controller to have any knowledge of networking stuff, so I thought that instead of passing in an Event object, I'd pass it a RAC signal. Then if the object exists I can send the signal immediately, but if the object needs to be downloaded, I can download it then send the signal. However, I'd like for the controller to display an activity indicator if in fact a download needs to occur.
I see that RACCommand has an executing signal I can subscribe to, so I suppose I can pass that instead of an event, but semantically it seems weird to be initializing a view controller with a "command" (vs. an event, or a signal that will deliver an event). Is using RACCommand the right thing to do?
That's an interesting question. I think your instincts are right that you should pass the view controller a signal.
So let's go with that. Then let's suppose your view controller has a activityIndicator property.
You should be able to do something like:
- (id)initWithEventSignal:(RACSignal *)signal {
// ... init stuff ...
// Send a YES and then a NO when `signal` completes. If `signal`
// immediately sends a value, then it will immediately send NO.
RACSignal *loading = [[[RACSignal return:#YES] takeUntil:signal] concat:[RACSignal return:#NO]];
RAC(self.activityIndicator, hidden) = [loading not];
RAC(self, event) = signal;
// ... other stuff ...
}
We're using -takeUntil: to short-circuit our loading signal when the event signal sends its result.

Is -[NSView setsNeedsDisplay:] a synchronous call?

I have an NSView in a Mac OS X application that draws itself. When I am ready for this to happen I request it with the call:
[self.imageRenderedView setNeedsDisplay:YES];
My question is, does this call block? That is, is it synchronous, and can I assume the drawing has happened by the time the subsequent statement is executed? This assumption seems to work for me, but I feel a bit insecure about it.
The setNeedsDisplay: call only marks the view as needing display by setting
a flag in the view object.
Therefore it returns very quickly, but the drawing has not yet happened when the method returns.
From the documentation:
Whenever the data or state used for drawing a view object changes, the
view should be sent a setNeedsDisplay: message. NSView objects marked
as needing display are automatically redisplayed on each pass through
the application’s event loop. (View objects that need to redisplay
before the event loop comes around can of course immediately be sent
the appropriate display... method.)

Request traitement crash - Message sent to deallocated instance

I'm executing an asynchronous method on an object and when my request is finish I print the result in a label. My problem is : if I launch my request and then I remove my object, I have a crash on my setText method (because my object is deallocated).
How can I avoid this crash even if my object has been released ?
Is there any test to do ?
1) Don't remove your object until the request is finished :)
2) Cancel the request (not always possible depending on your object)
The solution is to have a NSMutableArray object created in you "init" or in your "viewDidLoad" method. When you want to remove the object, always put it in this array after removing it from its superview. Then in your asynchronous method (which better be running on the main thread to print the result), the last thing it does is [storageArray removeObject:object], to release it.
If your object is deallocated and its currently a subview on a view, then the view itself has been destroyed, you have nowhere to display the label contents. Why this would be depends on the design of your app, but usually the removal of a view is detectable by your code and you should set any references to the view to nil in that case if you know its gone.
If the label hasnt been added to the view yet - then you needed to retain the label, so that you can set the text on it and call addSubview on the containing view.
Also if a user action would be causing the view to be removed - display a spinner and block the user from doing this since a request they invoked is in progress.
The asynchronous request can retain the object until it's done with it.

Sending an event up the UIResponder chain?

I just created a custom UIViewController with some user actions like touch. I would like to handle the user interaction in the parentObject. In other words the one that created the ViewController.
From other languages I am used to use Events that are pushed up. So my parent object would have some kind of listener on the reference of the ViewController object it can react to.
How would that type of interaction handled by Objective C?
This can be done by 1) responder chain, 2) notifications and 3) delegates.
All UI objects form the responder chain, starting from the currently focused element, then it's parent view and so on, usually until the application object. By sending action to the special First Responder object in your nib, you'll throw it down the responder chain until someone handles it. You can use this mechanism for firing events without knowing who and when will handle them. This is similar to HTML event model.
Notifications send by NSNotificationCenter can be received by any number of listeners. This is the closest analog to e.g. C# events.
Delegates is the simplest mechanism of sending event to one single object. The class declares weak property named delegate that can be assigned with any object, and a protocol that this object is supposed to implement. Many classes use this approach; the main problem is that you can't have more than one listener this way.
you should look into delegations/delegate for interactions between two viewControllers. You need to understand how it works first.
https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html
It sounds like you need to implement a delegate protocol, which will allow your 'child' view controller to communicate back to it's 'parent'
See http://developer.apple.com/library/ios/#documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html

NSTableView -setDataSource not working when triggered by FSEvents

So here's what I've got:
An NSTableView with an NSMutableArray data source
FSEvents monitoring a folder that contains the file that contains the data for the table view (Using SCEvents for Objective-C abstraction goodness)
The FSEvents triggers the same function that a reload button in the UI does. This function refreshes the table view with a new data source based on the contents of said file via setDataSource:.
And here's what happens:
If I make a change to the file, the FSEvent gets triggered and the refresh method gets called.
The array that the table view should be accepting does indeed include the changes that triggered the FSEvent.
setDataSource: gets sent to the NSTableView with the correct data source.
The changes do not appear in the table view!
But then:
If I hit the refresh button, which triggers the exact same method as the FSEvent, the table view gets updated with the new data.
I also tried replacing the FSEvent with an NSNotification (NSApplicationDidBecomeActiveNotification), but the same thing happens.
Anyone have any idea why this is happening?
Edit: For clarification, the jist of my question is this: Why does my NSTableView reload as it should when triggered by a button press, but not when triggered by an FSEvent or an NSNotification?
Edit: Thanks to diciu, I've figured out that in fact all of my UI references point to 0x0 when triggered by the event, but then have valid addresses when triggered by the button click. These objects are all declared in IB, so there's no instantiation or allocation for them going on in my code. So my question is now: what can I do to stop these pointers from pointing to nil?
We call reloadData on NSTableView when we have new data to add/remove to the table.
This might help, to force the NSTableView to redraw.
I'm not really sure if this is what your asking though. The wording of your question is kind of confusing, you state a series of events, but never a true question.
sounds like when you register for the event/notification, you're passing in a different instance of your controller class.
Have you tried calling your method from your FSEvent on a second pass of the run-loop?
[myObject performSelector:#selector(reloadAction:) withObject:nil afterDelay:0.0];
You're setting an NSArray directly as the data source of the table view?
That's not how NSTableView works. The data source must be an object that conforms to NSTableDataSource. NSArray doesn't. You write the data source yourself; it will probably be the same object that you currently have calling setDataSource:.
The other way would be to use Bindings.
Could it be that reference to table view within the scope of your refresh method is not valid?
I.e. are you sure you're not calling [nil reloadData] which does not yield any errors?
Your reference to your table view might be nil in the refresh code if you're set it before awakeFromNib or in some other circumstances.