2016-02-11 17 views
9

Tôi cần viết chức năng bổ sung ứng dụng của mình vào mục Khởi động trên OS X 10.11. Đó là những gì tôi tìm thấy vào lúc này:Khởi chạy ứng dụng Swift Cocoa khi khởi động trên OS X 10.11

func applicationIsInStartUpItems() -> Bool { 
    return (itemReferencesInLoginItems().existingReference != nil) 
} 

func itemReferencesInLoginItems() -> (existingReference: LSSharedFileListItemRef?, lastReference: LSSharedFileListItemRef?) { 

    if let appUrl : NSURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { 
     let loginItemsRef = LSSharedFileListCreate(nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? 
     if loginItemsRef != nil { 
      let loginItems: NSArray = LSSharedFileListCopySnapshot(loginItemsRef, nil).takeRetainedValue() as NSArray 
      if(loginItems.count > 0) { 
       let lastItemRef: LSSharedFileListItemRef = loginItems.lastObject as! LSSharedFileListItemRef 
       for var i = 0; i < loginItems.count; ++i { 
        let currentItemRef: LSSharedFileListItemRef = loginItems.objectAtIndex(i) as! LSSharedFileListItemRef 
        if let itemURL = LSSharedFileListItemCopyResolvedURL(currentItemRef, 0, nil) { 
         if (itemURL.takeRetainedValue() as NSURL).isEqual(appUrl) { 
          return (currentItemRef, lastItemRef) 
         } 
        } 
       } 
       return (nil, lastItemRef) 
      } else { 
       let addatstart: LSSharedFileListItemRef = kLSSharedFileListItemBeforeFirst.takeRetainedValue() 
       return(nil,addatstart) 
      } 
     } 
    } 
    return (nil, nil) 
} 

func toggleLaunchAtStartup() { 
    let itemReferences = itemReferencesInLoginItems() 
    let shouldBeToggled = (itemReferences.existingReference == nil) 
    if let loginItemsRef = LSSharedFileListCreate(nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? { 
     if shouldBeToggled { 
      if let appUrl : CFURLRef = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { 
       LSSharedFileListInsertItemURL(loginItemsRef, itemReferences.lastReference, nil, nil, appUrl, nil, nil) 
      } 
     } else { 
      if let itemRef = itemReferences.existingReference { 
       LSSharedFileListItemRemove(loginItemsRef,itemRef); 
      } 
     } 
    } 
} 

Nhưng LSSharedFileListCreate, LSSharedFileListInsertItemURL, LSSharedFileListItemRemove, kLSSharedFileListItemBeforeFirst, LSSharedFileListItemCopyResolvedURL, LSSharedFileListCopySnapshot, kLSSharedFileListSessionLoginItems được tán thành trong OS X 10.11. Cách thực hiện công việc này trên phiên bản Mac OS mới nhất? Làm thế nào để thay đổi hoặc viết lại mã này?

Trả lời

5

Trong Swift 3.0 có dạng như sau:

Trong ứng dụng chính của bạn AppDelegate:

func applicationDidFinishLaunching(_ aNotification: Notification) { 
    // Check if the launcher app is started 
    var startedAtLogin = false 
    for app in NSWorkspace.shared().runningApplications { 
     if app.bundleIdentifier == NCConstants.launcherApplicationIdentifier { 
      startedAtLogin = true 
     } 
    } 

    // If the app's started, post to the notification center to kill the launcher app 
    if startedAtLogin { 
     DistributedNotificationCenter.default().postNotificationName(NCConstants.KILLME, object: Bundle.main.bundleIdentifier, userInfo: nil, options: DistributedNotificationCenter.Options.deliverImmediately) 
    } 
} 

Trong ứng dụng appdelegate Launcher:

func applicationDidFinishLaunching(_ aNotification: Notification) { 

    let mainAppIdentifier = "<main-app-bundle-id>" 
    let running = NSWorkspace.shared().runningApplications 
    var alreadyRunning = false 

    // loop through running apps - check if the Main application is running 
    for app in running { 
     if app.bundleIdentifier == mainAppIdentifier { 
      alreadyRunning = true 
      break 
     } 
    } 

    if !alreadyRunning { 
     // Register for the notification killme 
     DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.terminate), name: NCConstants.KILLME, object: mainAppIdentifier) 

     // Get the path of the current app and navigate through them to find the Main Application 
     let path = Bundle.main.bundlePath as NSString 
     var components = path.pathComponents 
     components.removeLast(3) 
     components.append("MacOS") 
     components.append("<your-app-name>") 

     let newPath = NSString.path(withComponents: components) 

     // Launch the Main application 
     NSWorkspace.shared().launchApplication(newPath) 
    } 
    else { 
     // Main application is already running 
     self.terminate() 
    } 

} 

func terminate() { 
    print("Terminate application") 
    NSApp.terminate(nil) 
} 

Cuối cùng, trong việc áp dụng chính tôi đã thêm một giao diện người dùng với một nút bật tắt. Người dùng có thể chọn khởi chạy ứng dụng khi đăng nhập hay không. Lựa chọn được lưu vào UserDefaults. Trong Trình điều khiển chế độ xem:

@IBAction func toggleLaunchAtLogin(_ sender: Any) { 
    if toggleOpenAppLogin.selectedSegment == 0 { 
     if !SMLoginItemSetEnabled(NCConstants.launcherApplicationIdentifier as CFString, true) { 
      print("The login item was not successfull") 
      toggleOpenAppLogin.setSelected(true, forSegment: 1) 
     } 
     else { 
      UserDefaults.standard.set("true", forKey: "appLoginStart") 
     } 
    } 
    else { 
     if !SMLoginItemSetEnabled(NCConstants.launcherApplicationIdentifier as CFString, false) { 
      print("The login item was not successfull") 
      toggleOpenAppLogin.setSelected(true, forSegment: 0) 
     } 
     else { 
      UserDefaults.standard.set("false", forKey: "appLoginStart") 
     } 
    } 

} 

Tôi hy vọng điều này có thể giúp ai đó.

+0

Câu trả lời hay và thực sự giúp ích, ngay cả sau rất nhiều thời gian! –

+0

'NCConstants.KILLME' được định nghĩa ở đâu? –

+0

Trong ứng dụng trình khởi chạy VÀ ứng dụng chính. Bạn có thể định nghĩa nó như sau: Lớp NCConstants { // Thông báo hằng số static let KILLME = Notification.Name ("killme")} – Thomas

10

Bạn phải sử dụng khung Quản lý dịch vụ ngay bây giờ. Bạn tạo một ứng dụng trợ giúp mà bạn thêm vào gói ứng dụng của mình và công việc của nó là chạy mã để khởi chạy ứng dụng chính của bạn. Một số nguồn lực dành cho bạn:

  • Tim Schröder có excellent blog bài về cách thức này được thực hiện
  • Alex Zielenski có open source project để hỗ trợ với điều này
  • Tôi đã thực hiện một video tutorial vào việc tạo ra nó bằng tay
+0

Câu trả lời không phải là Swift liên quan, nhưng đưa ra hướng chung – zxcat

+0

Hướng dẫn của bạn thật tuyệt vời. Tôi đã thử nó ngay bây giờ và tất cả mọi thứ hoạt động như mô tả, ngoại trừ một thực tế nhỏ bé rằng nó không hoạt động. Tôi có lỗi này trên giao diện điều khiển 'Không thể giải quyết CFBundleIdentifier được chỉ định bởi service' theo sau là định danh của tập tin trợ giúp của tôi mà tôi đã kiểm tra ba được gõ một cách chính xác. Đó là mong đợi bởi vì trong kinh nghiệm của tôi không phải là một API duy nhất từ ​​Apple hoạt động như mong đợi khi bạn lần đầu tiên thử. – SpaceDog

+0

@SpaceDog Bạn đã thử kéo nguồn từ GitHub và thử dự án đó chưa? –

Các vấn đề liên quan