Skip to content

Commit cb31692

Browse files
jefry-vcuberogerwang
authored andcommitted
[ProgressBar][MacOS] fix crash on Mojave, store progressIndicator using "AssociatedObject"
1 parent 299f28a commit cb31692

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

src/api/nw_window_api_mac.mm

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#import <Appkit/NSImageView.h>
1010
#import <Appkit/NSProgressIndicator.h>
1111
#import <Appkit/NSWindow.h>
12+
#import <objc/runtime.h>
1213

1314
@interface NWProgressBar : NSProgressIndicator
1415
@end
@@ -84,17 +85,22 @@ - (void)drawRect:(NSRect)dirtyRect {
8485
EXTENSION_FUNCTION_VALIDATE(args_);
8586
double progress;
8687
EXTENSION_FUNCTION_VALIDATE(args_->GetDouble(0, &progress));
87-
NSDockTile *dockTile = [NSApp dockTile];
88-
NWProgressBar *progressIndicator = NULL;
8988

90-
if ((dockTile.contentView == NULL || [dockTile.contentView.subviews count] == 0 )&& progress >= 0) {
91-
92-
// create image view to draw application icon
93-
NSImageView *iv = [[NSImageView alloc] init];
94-
[iv setImage:[NSApp applicationIconImage]];
95-
96-
// set dockTile content view to app icon
97-
[dockTile setContentView:iv];
89+
NSDockTile *dockTile = [NSApp dockTile];
90+
static const char kProgressIndicator = '\0';
91+
NWProgressBar *progressIndicator = objc_getAssociatedObject(dockTile, &kProgressIndicator);
92+
static const char kImageView = '\0';
93+
94+
if (progressIndicator == NULL && progress >= 0) {
95+
// contentView might not be NULL, i.e when download progress is running
96+
if (dockTile.contentView == NULL) {
97+
// create image view to draw application icon
98+
NSImageView* iv = [[NSImageView alloc] init];
99+
[iv setImage:[NSApp applicationIconImage]];
100+
// set dockTile content view to app icon
101+
[dockTile setContentView:iv];
102+
objc_setAssociatedObject(dockTile, &kImageView, iv, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
103+
}
98104

99105
progressIndicator = [[NWProgressBar alloc]
100106
initWithFrame:NSMakeRect(0.0f, 0.0f, dockTile.size.width, 15.)];
@@ -108,11 +114,10 @@ - (void)drawRect:(NSRect)dirtyRect {
108114
[progressIndicator setUsesThreadedAnimation:false];
109115

110116
// add progress indicator to image view
111-
[iv addSubview:progressIndicator];
117+
[dockTile.contentView addSubview:progressIndicator];
118+
objc_setAssociatedObject(dockTile, &kProgressIndicator, progressIndicator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
112119
}
113-
114-
progressIndicator = (NWProgressBar*)[dockTile.contentView.subviews objectAtIndex:0];
115-
120+
116121
if(progress >= 0) {
117122
[progressIndicator setIndeterminate:progress > 1];
118123
if(progress > 1) {
@@ -125,11 +130,21 @@ - (void)drawRect:(NSRect)dirtyRect {
125130
[progressIndicator setDoubleValue:progress];
126131
}
127132
}
128-
else {
133+
else if (progressIndicator) {
129134
// progress indicator < 0, destroy it
130-
[[dockTile.contentView.subviews objectAtIndex:0]release];
131-
[dockTile.contentView release];
132-
dockTile.contentView = NULL;
135+
objc_setAssociatedObject(dockTile, &kProgressIndicator, NULL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
136+
[progressIndicator removeFromSuperview];
137+
[progressIndicator release];
138+
progressIndicator = NULL;
139+
140+
// if we the one created the ImageView, we are the one who clean it
141+
NSImageView* iv = objc_getAssociatedObject(dockTile,&kImageView);
142+
if (iv) {
143+
objc_setAssociatedObject(dockTile, &kImageView, NULL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
144+
dockTile.contentView = NULL;
145+
[iv release];
146+
iv = NULL;
147+
}
133148
}
134149

135150
[dockTile display];

0 commit comments

Comments
 (0)