简体   繁体   中英

Xcode 10 - NSVisualEffectView added to NSWindow when displayed modally (Mac OS)

I have a NSWindow that I display modally on some other window to display alerts. The code is:

// This code is in MyAlert .m file. MyAlert inherits from NSWindow
- (void)showInWindow:(NSWindow *) {
    [window beginSheet:self completionHandler:NULL];
}

Thing is that when compiled with Xcode 10.1 in a Mac running Mojave I see a gray "blurring" view behind the alert which I don't want there: I want the background window where it's shown to be visible.

Same code compiled with Xcode 9.4.1 does not show this blurring view.

Furthermore, I debugged the UI and there's indeed a NSVisualEffectView inserted in the Xcode 10.1 compiled version which is not there when compiling on 9.4.1, but I can't seem to find a way to get rid of it. Below are screenshots of the UI debugged in both versions.

Xcode 9 UI,无模糊

Xcode 10 UI,模糊

Has someone faced and figured this one out?

Update (Minimal Project reproducing issue of inserted nsvisualeffectview) : http://s000.tinyupload.com/?file_id=43114618701497778758

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{
  // Insert code here to initialize your application
  __weak typeof(self)weakSelf = self;
  NSView *contentView = self.window.contentView;
  contentView.wantsLayer = YES;
  [self.window setOpaque:NO];
  [self.window setHasShadow:NO];
  contentView.layer.backgroundColor = [NSColor redColor].CGColor;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    __strong typeof(weakSelf) strongSelf = weakSelf;
    [strongSelf showAlert];
  });
}

- (void)showAlert {
  DummyAlertWindowController *alertController = [[DummyAlertWindowController alloc] initWithWindowNibName:@"DummyAlertWindowController"];
  [self.window beginSheet:alertController.window completionHandler:^(NSModalResponse returnCode) {
;
}];
}

@implementation DummyAlertWindowController

- (void)windowDidLoad {
    [super windowDidLoad];
  self.properContentView.wantsLayer = YES;
  self.properContentView.layer.backgroundColor = [NSColor blueColor].CGColor;
  [self.window setOpaque:NO];
  [self.window setHasShadow:NO];
  self.window.contentView.wantsLayer = YES;
  self.window.contentView.layer.backgroundColor = [NSColor clearColor].CGColor;
}

@end

You can recover your non-frosted appearance by making your window borderless.

在此处输入图片说明

Add this class to your project.

@interface BorderlessWindow : NSWindow

@end

@implementation BorderlessWindow

- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag {

    self = [super initWithContentRect:contentRect
                            styleMask:NSWindowStyleMaskBorderless
                              backing:backingStoreType
                                defer:flag];

    return self;
}

@end

And set the window class in your XIB to BorderlessWindow

Lastly set the backgroundColor on the window to get the transparency.

@implementation DummyAlertWindowController

- (void)windowDidLoad {
    [super windowDidLoad];
    //stuff
    [self.window setOpaque:NO];
    [self.window setHasShadow:NO];
    [self.window setBackgroundColor:[NSColor clearColor]];
}

@end

As a side note using wantsLayer to get backgroundColors is better served now by using a custom style NSBox with a custom color or using the backgroundColor property on the window.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM