RBSplitView has delayed reload of autosaved view positions - cocoa

I really enjoy using RBSplitView, an open source replacement for NSSplitView, but I have a problem in my shipping app and am experiencing it again in a new project.
The problem is I'm telling the RBSplitView to autosave its position state by giving it an autosave name. When my app launches the RBSplitView doesn't seem to honor the saved state till a second after the window is drawn.
I've spent the night trying to debug the behavior but have had little success. Anyone out there use this lib and have some advice?
You can scrub this quicktime movie to the issue at work:
http://media.clickablebliss.com/billable/interface_experiments/rbsplitview_delayed_autosave_reload2.mov

I've still been unable to figure out why this is happening but I do have a workaround.
First, make sure your main window is not visible at launch and then at the end of applicationDidFinishLaunching in your app delegate add something like:
[mainWindow performSelector:#selector(makeKeyAndOrderFront:) withObject:self afterDelay: 0.1];
The delay is the key. If you just tell the window to makeKeyAndOrderFront: I still see the issue. However as long as it has a beat of time it looks good.

This likely is happening because the RBSplitView instance needs to wait until it's first moment to get to set its frame to the autosaved value, which happens to be after the user can see it. This 0.0-delay trick simply delays showing the window until the very next runloop, which gives the split view a chance to do its magic (and other views) so that when the user sees the window, it's already nice and sexy. So just do the delay at 0.0 and you'll be fine.

I have a similar, but slightly different workaround in my app that uses RBSplitView. In applicationDidFinishLaunching:, I call adjustSubviews on the split view before calling makeKeyAndOrderFront: on the window that contains it. This seems to knock the split view in to order before it gets displayed on the screen.

Related

NSTextView setNeedsDisplay not working under Mavericks?

My MacOS Cocoa application displays a window of static text, meaning it should not be changed by the user, should not be first responder, etcetera. The only thing that happens to the text is that each word of it changes color (from "idleColor" to "highlightColor", and then back again) at a specific point in time. It is similar to a Karaoke display - individual words change color, and then change back, under program control, based on a list of timed events.
All of this works beautifully under MacOS 10.7 and 10.8. BUT, under 10.9, the text color does NOT change UNLESS I click in the window and continually move the cursor around, so I am manually highlighting (and un-highlighting) some of the text, continuously. If I do this, the regular words behave as intended. Essentially, it feels like the OS is refusing to update the window under program control, unless I am forcing it to update by manually performing something that requires the UI to respond.
The code that performs the color changes is as follows:
if (sEvent.attribute == HIGHLIGHT_ON) {
[sTextView setTextColor:highlightColor range: currentRange];
textIsLitUp = YES;
}
else {
[sTextView setTextColor:idleColor range: currentRange];
textIsLitUp = NO;
}
[sTextView setNeedsDisplay:YES];
(sTextView is a subclass of NSTextView.)
Now, if I comment out that last line, then I get the same, incorrect behavior under 10.7 and 10.8. In other words, under 10.9, the setNeedsDisplay method is not working, or not working the same way.
Does anyone have any ideas about working around this, or have any other light to shed on the problem? Or am I doing something terribly wrong? It is CRITICAL to the application that the changes to the textColor happen without latency!
EDITING MY QUESTION - to answer it:
Found the answer elsewhere here! I needed to call setNeedsDisplay on the main thread - it was in a secondary thread. The weird thing is that it always seemed to work fine under 10.7 and 10.8. It only broke under 10.9. So I just changed this:
[myTextField setNeedsDisplay:YES];
To this:
dispatch_async(dispatch_get_main_queue(), ^{[myTextField setNeedsDisplay:YES];});
…and it seem to have worked. Hope this helps someone else…
You don’t want to do any of the changing of AppKit objects in non-main threads—it’ll work sometimes, maybe even often, but then every once in a while it’ll crash, and you’ll wonder why. So:
[sTextView setTextColor:idleColor range: currentRange];
needs to be on the main thread, too.

Using GUI causes "Sleep?" making Audio stutter/stop

Okay, as Title says.
For example, i use NAudio to playback what i record (loopback if you want).
And if i click on the GUI (the top part, so i can move the window).
It will cause a "sleep", and when that happens the current activity (Audio playback) stops.
And then it continues afterwards.
But i want to remove that, as i don´t know any other application that has it, so it´s probably something to do with how i am programming.
Please keep it simple, i am extremely new to c#.
I am guessing on Bakckgroundworker or something, but i couldn´t get it to work.
So hopping for a more concrete answer.
This was just me not understanding that using the Main Thread in a window form will cause anything on the GUI to be run on it.
Meaning, if i move the GUI, that movement will be Priority over the rest of the code, so everything else will get paused if run on that thread.
Perhaps it differ from object to object, but in this scenario it was the case, so i just moved it to a separate thread and it´s solved.

Applescript and Microsoft Word

I'm working on a applescript to update the content of a document in Microsoft Word. The updating process is quite long (might take more than 5s). So I want to prevent users to change anything during the updating. Do you know whether Microsoft or Applescript a function like that?
In Windows, I can just display a User Form (which is a dialog telling that "we are updating... ") and close that form when it's done. However, I don't know whether I can do the same in Mac (with Applescript alone).
When you say "applescript", I don't know if you mean "plain" applescript or the AppleScriptObjC version. If you mean the latter, then I know ways to do it.
One way I've used during slow processes is to put an overlay view over the whole content view of the window. I make it translucent white to partially obscure the window, and put some kind of message (and maybe a progress indicator) on it. You can just use an NSBox (of the custom type) in IB to make this, and then make a subclass of NSBox to color the view and override mouseDown:. MouseDown:, doesn't need to have any code in it, just by overriding it, you capture any key and mouse events so they don't accumulate on the event queue, and get used by the view below after your overlay goes away. Here's code I've used:
script Overlay
property parent : class "NSBox"
on awakeFromNib()
set overlayColor to current application's NSColor's colorWithCalibratedWhite_alpha_(1,.8)
setFillColor_(overlayColor)
end
on mouseDown_(theEvent)
--log "mouseDown"
end
end script
I have this view as the top most view in the view hierarchy, and set its hidden property to true until I want to show it.

Hide window until the top window is displayed

I am facing a little annoying design problem. Not easy to give a title of my question.
I must display two windows, one over another one. The first one is a Cocoa window, the second is made with Qt. In the second window, an action is performed, but the user can choose to close this window. He must fall back on the first window.
To display my first window, which is actually a SFAuthorizationPluginView, I do:
[myview displayView];
then, to display the window made with Qt on top of first window:
QWidget* w = openMyScreen();
NSView* v = (NSView*)w->winId();
[[v window] setLevel:2003];
This works well, however there is a small delay before the second window is displayed. We can thus see for a very short time the first window.
I need that the second window stays on top of the first window, because the user can close the second window and must have access to the first window.
Any ideas on a trick how to hide the first window, just the time, the second window appears?
Thanks in advance
NSDisableScreenUpdates and NSEnableScreenUpdates (link) might be useful in this situation. The documentation says:
You typically call this function so that operations on multiple windows appear atomic to the user.
which seems to describe your situation.
A word of unrelated advice though: Don't go setting window levels willy-nilly. A window level of 2003 will likely cause the window to appear over things like the dock or even the menu bar, which would definitely be strange. You should stick to the standard levels declared in NSWindow.h unless you have good reason. NSFloatingWindowLevel might be appropriate (although I'm not sure what level the SFAuthorizationPluginView window is displayed at).
Starting with MacOS 10.4, you can use :
[NSWindow disableScreenUpdatesUntilFlush];

NSDocument Subclass not closed by NSWindowController?

Okay, I'm fairly new to Cocoa and Objective-C, and to OOP in general.
As background, I'm working on an extensible editor that stores the user's documents in a package. This of course required some "fun" to get around some issues with NSFileWrapper (i.e. a somewhat sneaky writing and loading process to avoid making NSFileWrappers for every single document within the bundle). The solution I arrived at was to essentially treat my NSDocument subclass as just a shell -- use it to make the folder for the bundle, and then pass off writing the actual content of the document to other methods.
Unfortunately, at some point I seem to have completely screwed the pooch. I don't know how this happened, but closing the document window no longer releases the document. The document object doesn't seem to receive a "close" message -- or any related messages -- even though the window closes successfully.
The end result is that if I start my app, create a new document, save it, then close it, and try to reopen it, the document window never appears. With some creative subclassing and NSLogging, I managed to figure out that the document object was still in memory, and still attached to the NSDocumentController instance, and so trying to open the document never got past the NSDocumentController's "hmm, currently have that one open" check.
I did have an NSWindowController and NSDocumentController instance, but I've purged them from my project completely. I've overridden nearly every method for NSDocument trying to find out where the issue is. So far as I know, my Interface Builder bindings are all correct -- "Close" in the main menu is attached to performClose: of the First Responder, etc, and I've tried with fresh unsullied MainMenu and Document xibs as well.
I thought that it might be something strange with my bundle writing code, so I basically deleted it all and started from scratch, but that didn't seem to work. I took out my -init method overrides, and that didn't help either. I don't have the source of any simple document apps here, so I didn't try the next logical step (to substitute known-working code for mine in the readFromUrl and writeToUrl methods).
I've had this problem for about sixteen hours of uninterrupted troubleshooting now, and needless to say, I'm at the end of my rope. If I can't figure it out, I guess I'm going to try the project from scratch with a lot more code and intensity based around the bundle-document mess.
Hard to tell without code but I would suggest sending:
closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:
... to the document controller and then looking at the controller as it is passed to the delegate to see how its state changes.
If the controller closes the document when you send the explicit message then your problem is with the binding to the window.

Resources