我正在编写一个macOS Objective-C应用程序,它在启动时有一个登录屏幕。在设置中,有相应的“注销”功能。在这种情况下,我决定强制重新启动应用程序,这样我就不必报道新的情况,并使我更确信注销不会产生不必要的副作用。因此,我实施了我在网上找到的解决方案之一,具体如下:
- (void)automaticallyRestartApp:(id)sender {
Relaunch([[NSBundle mainBundle] bundleURL].path);
dispatch_async( dispatch_get_main_queue(), ^{
[NSApp terminate:self];
});
}
重新启动功能为:
static void Relaunch(NSString *destinationPath) {
// The shell script waits until the original app process terminates.
// This is done so that the relaunched app opens as the front-most app.
int pid = [[NSProcessInfo processInfo] processIdentifier];
// Command run just before running open /final/path
NSString *preOpenCmd = @"";
NSString *deletePrefsCmd = @"rm";
NSString *wevpnPreferencesPath = [[[[[[NSProcessInfo processInfo] environment] objectForKey:@"HOME"] stringByAppendingPathComponent:@"Library"] stringByAppendingPathComponent:@"Preferences"] stringByAppendingPathComponent:@"com.vpn.osx.alfonso.plist"];
NSString *quotedDestinationPath = ShellQuotedString(destinationPath);
// OS X >=10.5:
// Before we launch the new app, clear xattr:com.apple.quarantine to avoid
// duplicate "scary file from the internet" dialog.
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) {
// Add the -r flag on 10.6
preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d -r com.apple.quarantine %@", quotedDestinationPath];
}
else {
preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d com.apple.quarantine %@", quotedDestinationPath];
}
NSString *script = [NSString stringWithFormat:@"(while /bin/kill -0 %d >&/dev/null; do /bin/sleep 0.1; done; %@ %@; %@; /usr/bin/open %@) &", pid, deletePrefsCmd, ShellQuotedString(preferencesPath), preOpenCmd, quotedDestinationPath];
[NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]];
}
直到最近,我一直对这种实现感到高兴,因为我发现我的应用程序在重新启动时,内存使用率非常高,特别是当用户在输入凭据后单击登录时。内存占用保持1500Mb大约3秒钟,然后,当用户登录时,它会恢复正常。当用户第一次启动应用程序时,内存占用没有增加。首先,在某种意义上,我认为这是由于重新启动功能非常脏造成的。所以我在网上找到了这个
page
,其中相同的重新启动行为通过助手守护程序实现。我认为这看起来肯定更优雅,可以解决这个问题,但不幸的是,同样的情况也发生了。登录时自动重新启动时占用大量内存。
我的应用程序已经使用了一个守护进程,所以我在XPC与守护进程的通信中添加了一个方法。这是我对XPC协议中相关方法的实现:
- (void)askServiceToRelaunchHostAppAtPath:(NSString *)hostAppPath withReply:(void (^)(BOOL))reply {
self.relaunchHostAppExecutablePath = hostAppPath;
self.shouldRelaunchHostAppOnNextHostAppQuit = YES;
reply(YES);
}
然后,在主机应用退出时调用的守护进程的方法中,有:
if (self.shouldRelaunchHostAppOnNextHostAppQuit) {
self.shouldRelaunchHostAppOnNextHostAppQuit = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSError *error;
NSRunningApplication __unused *relaunchedHostApp = [[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL fileURLWithPath:self.relaunchHostAppExecutablePath] options:0 configuration:@{} error:&error];
self.relaunchHostAppExecutablePath = nil;
});
}
如上所述,这种完全不同的方法得到了完全相同的坏记忆结果。你会读到守护程序代码,我试图让守护程序在重新启动应用程序之前等待25秒。不幸的是,这也无济于事。任何可能的建议都将不胜感激。谢谢你的关注。