NES_4Life NES_4Life - 2 months ago 8
Objective-C Question

Simultaneously deminiaturize an array of NSWindows programmatically?

In Cocoa (Objective-C) how can you programmatically simultaneously deminiaturize a group of NSWindow instances without using a background thread?

If you call 'deminiaturize:' on an NSWindow instance it will block the main thread for the duration of the deminiaturization process (about 0.3 seconds). If you instruct an array of windows to deminiaturize they will do so one at a time, cumulatively taking quite a while, all the time blocking the main thread. The desired affect can be achieved using a background thread but this (rightly) throws console log errors.

The ability to safely deminiaturize a group of 5+ windows in 0.3 seconds or less would be ideal. Is there a way to remove the animation from the deminiaturization in order to speed up the process? Is there another way to restore windows to the screen without calling 'deminiaturize:'?

Answer

By using a combination of setReleasedWhenClosed:, close, and makeKeyAndOrderFront:, it is possible to effectively deminiaturize an array of NSWindows without any animation (i.e. instantly) - and without actually deallocating the objects.

Objective-C:

void deminiaturizeWindowsWithoutAnimation(NSArray<NSWindow *> *windows) {
    for (NSWindow * window in windows) {
        if ([window isMiniaturized]) {
            BOOL old_isReleasedWhenClosed = [window isReleasedWhenClosed];
            [window setReleasedWhenClosed:false];
            [window close];
            [window makeKeyAndOrderFront: nil];
            [window setReleasedWhenClosed:old_isReleasedWhenClosed];
        }
    }
}

Swift:

func deminiaturizeWithoutAnimation(windows: [NSWindow]) {
    for window in windows {
        guard window.isMiniaturized else { continue }
        let old_isReleasedWhenClosed = window.isReleasedWhenClosed
        window.isReleasedWhenClosed = false
        window.close()
        window.makeKeyAndOrderFront(nil)
        window.isReleasedWhenClosed = old_isReleasedWhenClosed
    }
}

These functions can be called from the main thread. Tested on macOS Sierra.

If you'd like, you can replace makeKeyAndOrderFront: with orderFront: or orderBack: to avoid changing the key window. (Although makeKeyAndOrderFront's behavior replicates that of deminiaturize:, which results in the window becoming the key window.)

Comments