以编程方式重启应用

时间:2014-12-15 08:14:02

标签: macos swift

我想知道是否有任何以编程方式重启我的应用的方法。 这是一个mac os应用程序,我在swift中使用Xcode 6。

程序很简单,在给定时间我想重新启动我的应用程序。我想我需要一个简单的助手,但我不确定。

6 个答案:

答案 0 :(得分:10)

是的,你需要帮助工具。这是程序:

  1. 在项目中创建帮助程序“命令行工具”目标。例如,名为“重新启动

    <强>重新推出/ main.swift

    import AppKit
    
    // KVO helper
    class Observer: NSObject {
    
        let _callback: () -> Void
    
        init(callback: () -> Void) {
            _callback = callback
        }
    
        override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
            _callback()
        }
    }
    
    
    // main
    autoreleasepool {
    
        // the application pid
        let parentPID = atoi(C_ARGV[1])
    
        // get the application instance
        if let app = NSRunningApplication(processIdentifier: parentPID) {
    
            // application URL
            let bundleURL = app.bundleURL!
    
            // terminate() and wait terminated.
            let listener = Observer { CFRunLoopStop(CFRunLoopGetCurrent()) }
            app.addObserver(listener, forKeyPath: "isTerminated", options: nil, context: nil)
            app.terminate()
            CFRunLoopRun() // wait KVO notification
            app.removeObserver(listener, forKeyPath: "isTerminated", context: nil)
    
            // relaunch
            NSWorkspace.sharedWorkspace().launchApplicationAtURL(bundleURL, options: nil, configuration: [:], error: nil)
        }
    }
    
  2. Products/relaunch二进制文件添加到主应用程序目标中的“复制包资源”。

  3. relaunch目标添加到主应用程序目标中的“目标依赖项”。

    screenshot

  4. 在主应用程序中添加relaunch功能。

    例如: NSApplication + Relaunch.swift

    extension NSApplication {
        func relaunch(sender: AnyObject?) {
            let task = NSTask()
            // helper tool path
            task.launchPath = NSBundle.mainBundle().pathForResource("relaunch", ofType: nil)!
            // self PID as a argument
            task.arguments = [String(NSProcessInfo.processInfo().processIdentifier)]
            task.launch()
        }
    }
    
  5. 然后,根据需要致电NSApplication.sharedApplication().relaunch(nil)

答案 1 :(得分:4)

Swift 3版本,基于Rintaro的代码和Cenox Kang的解决方法。
请参阅Rintaro的答案以获取指示。

<强>重新推出/ main.swift:

import AppKit

// KVO helper
class Observer: NSObject {

    let _callback: () -> Void

    init(callback: @escaping () -> Void) {
        _callback = callback
    }

    override func observeValue(forKeyPath keyPath: String?,
                      of object: Any?,
                      change: [NSKeyValueChangeKey : Any]?,
                      context: UnsafeMutableRawPointer?) {
        _callback()
    }
}


// main
autoreleasepool {

    // the application pid
    guard let parentPID = Int32(CommandLine.arguments[1]) else {
        fatalError("Relaunch: parentPID == nil.")
    }

    // get the application instance
    if let app = NSRunningApplication(processIdentifier: parentPID) {

        // application URL
        let bundleURL = app.bundleURL!

        // terminate() and wait terminated.
        let listener = Observer { CFRunLoopStop(CFRunLoopGetCurrent()) }
        app.addObserver(listener, forKeyPath: "isTerminated", context: nil)
        app.terminate()
        CFRunLoopRun() // wait KVO notification
        app.removeObserver(listener, forKeyPath: "isTerminated", context: nil)

        // relaunch
        do {
            try NSWorkspace.shared().launchApplication(at: bundleURL, configuration: [:])
        } catch {
            fatalError("Relaunch: NSWorkspace.shared().launchApplication failed.")
        }
    }
}

<强>的NSApplication + Relaunch.swift:

import AppKit

extension NSApplication {
    func relaunch(sender: AnyObject?) {
        let task = Process()
        // helper tool path
        task.launchPath = Bundle.main.path(forResource: "relaunch", ofType: nil)!
        // self PID as a argument
        task.arguments = [String(ProcessInfo.processInfo.processIdentifier)]
        task.launch()
    }
}

答案 2 :(得分:4)

swift4功能

@objc private func buttonClicked(_ sender: NSButton) {
    if let path = Bundle.main.resourceURL?.deletingLastPathComponent().deletingLastPathComponent().absoluteString {
        NSLog("restart \(path)")
        _ = Process.launchedProcess(launchPath: "/usr/bin/open", arguments: [path])
        NSApp.terminate(self)
    }
}

答案 3 :(得分:1)

在Swift 2中解决rintaro的代码。

// the application pid
let parentPID = atoi(C_ARGV[1])

// the application pid
let parentPID = Int32(Process.arguments[1])

对我有用。

答案 4 :(得分:1)

https://gist.github.com/BenLeggiero/449fb9b1a45b69fb276f4f9ad86cab7a

为我工作

func relaunch(afterDelay seconds: TimeInterval = 0.5) -> Never {
    let task = Process()
    task.launchPath = "/bin/sh"
    task.arguments = ["-c", "sleep \(seconds); open \"\(Bundle.main.bundlePath)\""]
    task.launch()
    
    NSApp.terminate(self)
    exit(0)
}

答案 5 :(得分:0)

谢谢你,我只是简化一下:

func restart()
{
  Process.launchedProcess(launchPath: "/usr/bin/open", arguments: ["-b", Bundle.main.bundleIdentifier!])
  NSApp.terminate(self)
}