I'm new to Cocoa so apologies if this doesn't make sense.
I'm using an NSBrowser to get a Finder-style column view of some data from a web service.
The NSURLConnection result is returned asynchronously.
My issue is that the browser correctly calls its delegate to populate columns when the app starts, but I can't make it reload once I've got the data.
I've tried reloadDataForRowIndexes, noteHeightOfRowsWithIndexesChanged, addColumn, reloadColumn and loadColumnZero, but none of them trigger the browser to call numberOfRowsInColumn on the delegate as I would expect (and see on startup).
I know the browser delegate is ok because I can see it being called at startup.
Is there another way to ask the browser to refresh, or do I need to try another approach?
Plan B would be to fire the urlConnection off on another thread, and block the browser. I'm not keen on blocking the UI thread as I fear this will cause a beachball.
Plan C maybe would be to delay the browser loading from the nib file until the data was ready, but I'd have a similar issue next node unless I load all nodes a column early in anticipation.
[browser reloadColumn:0] did not work for me but [browser loadColumnZero].
[browser reloadColumn:0] is the right way to go. This just works, no workaround needed. Your error is elsewhere if this does not work for you.
Related
I'm writing a Cocoa app, and I need to indicate to the user that a view is invalid and can't respond until a background job is completed.
Longer version:
A view in my app contains some data fetched from a server. When the app determines that the data is invalid, it fetches fresh information and displays it. Usually the update happens too quickly to see, but if server or network problems cause the background job to take more than a second or two, I need to make sure the user
Cannot interact with the view until the job is finished;
Can tell that the view is awaiting an update; and
Can continue to interact with other parts of the application until the job is finished.
1) is important because any operation initiated with the stale data will fail, and if the network or the server is slow, I don't want the user to waste his time with futile attempts to interact with that part of the application. (It's fine if the user can still see the data. That could conceivably be helpful, actually, but it isn't crucial.)
What is the standard way to do this in Cocoa? For what it's worth, in the Eclipse framework I think I used the showBusy method on ViewPart.
If there isn't a standard way, does anyone have any suggestions for tackling it? I haven't been using OS X very long, so I'm not even sure how an app is supposed to look and behave in this situtaion. (The screenshots on this page looking promising, but it's iOS, not OS X: http://cocoawithlove.com/2009/04/showing-message-over-iphone-keyboard.html)
Right now I'm working on replacing the whole view with an NSProgressIndicator and restoring the view after the task finishes, but removing the view means my app could end up in a funky state if something goes wrong. Also, I'd like to be able to factor this functionality out into its own class or category(?) since I will have this issue with several different view classes in my application. Ideally I'd like to end up with something as simple as Eclipse's view.showBusy(true)/view.showBusy(false).
Any and all help would be appreciated.
Thanks!
Why not just draw another view on top of the busy view? You could either have it display an image that means busy, or draw it as semitransparent, so it shades out the before-update version of the busy view.
I'm writing a plugin for an application and need to use Carbon to show a dialog. I have everything set up including the event handler, but I cannot possibly call RunApplicationEventLoop() because this would stall the host application.
How can I fix this? Will I need to create a separate thread and call RunApplicationEventLoop() from there?
-Joe
What makes you think you need to call RunApplicationEventLoop? The host app is presumably running an event loop, probably either using RunApplicationEventLoop or NSApplicationMain. By the way, would your dialog be modal? Modal is easier.
I'm using Sync Services in my application. I'm using the normal way of getting the contacts from the address book (using sync services).
I want to prematurely end a sync session if the user decides to do that, therefore, when the user presses the "cancel" button, I make a call to [driver finishSyncing]
Attached to the ISyncSessionDriver is a delegate which deals with delegate methods typical of a sync session. One of those methods is - (BOOL)sessionDriver:(ISyncSessionDriver *)sender willFinishSessionAndReturnError:(NSError **)outError
The problem is that when calling finishSyncing, the sessionDriver:willFinishSessionAndReturnError: gets repeatedly called, not just once, but hunderds of times. Eventually it will throw an error.
So, how could I fix this, or what better debugging can I do to figure out what the problem is?
Thanks
Use instead - (void)cancelSyncing.
Make sure to release the receiver soon afterward because you cannot continue using a canceled session.
I've been banging my head on walls trying to solve this.
My app uses a subclass of NSDocument, NSDocumentController and also NSWindowController. The issue is that when I create a document and make a modification, and also if I create more than one document the same way, if I choose Quit while documents are unsaved, I get the proper dialogs to ask wether I want to Review unsaved docs, Cancel or Not save, but whenever I select to Review and then save a document, I get to save, but after saving the first document, first, that document is NOT closed, and I am not asked to save the others. On top of this, My App's Quit menu item becomes grayed out.
I created another skeleton app to do the same thing, and of course, all works normally. I checked my connections in the nib file, and cannot see anything wrong, or different from the test app. Although there is a lot more in my app.
I am not currently overriding the reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo: method, but when I do, I get the same problem, since I call Super's version of it after doing some special clean-up work. But again, not overriding this yields the same result.
One thing I do notice, is that in my own App, I get the following messages in the Log as I run it, which I do not get in my test app:
[Switching to process 9997 thread 0x7667]
[Switching to process 9997 thread 0x903]
Which makes it look like I am doing something multi-threaded here without knowing. My test app doesn't switch to another thread.
I'm not sure how to check if all my connexions are ok and why these threads are being switched to and where they come from.
Since I get the error wether or not I override the NSDocumentController methods like the one above or the closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo: I imagine the error comes from somewhere else.
Maybe my NSDocument subclass's saving methods are creating the issue, but they return the appropriate values once the save has occurred, I get no error and the files are all fine.
I'd like to override the -didCloseAllSelector or -didReviewAllSelector, but I'm a bit challenged with this. I'm not sure how to build the method, since this:
- (void)documentController:(NSDocumentController *)controller
didCloseAll:(BOOL)didCloseAll contextInfo:(void *)contextInfo;
{
NSLog(#"All documents closed");
}
is never called. Is this a symptom? Tried the same for the -didReviewAllSelecter which never gets called.
Finally, I was overriding a method in my "NSDocument" subclass which I should not have. Removing this fixed it.
I guess you have to be really careful what you override!
The method was writeToFile:ofType:originalFile:saveOperation: which I no longer had to do.
Not sure exactly what was wrong, but it may help others to know to look there.
I'm now writing a Bonjour service listener class, according to the document here:
Currently, it seems working, I can receive "netServiceBrowserWillSearch:" and "didFindService:moreComing:" correctly. However, after a long wait, I cannot receive " netServiceBrowserDidStopSearch:" or "netServiceBrowser:didNotSearch:". Therefore I don't know that is the proper time for my delegate class to stop showing some UI.
Could anyone have an idea for this? Thanks.
NSNetServiceBrowser doesn't stop browsing (and call the -netServiceBrowserDidStopSearch: delegate method) until you explicitly tell it to by calling -stop. After it's found the initial services, it continues informing you as new matching services are added or old ones disappear.
How you handle this depends on how you want your app to behave. If you have a window that continuously shows the available services (e.g. like the Bonjour window in iChat), then it's best to let it continue, and contiuously update the list in response to delegate messages. If you've got more like a dialog that gets populated and then goes away once the user makes a selection (e.g like the system Add Printer... dialog), then you want to keep the browser running while it's displayed, then call -stop once the user dismisses it. If you're waiting to find just one specific service, then you can call -stop once you've found and resolved it.