2014-10-20 24 views
15

Trong vài tuần qua tôi đã viết một ứng dụng mac nhanh chóng, cả hai để tham gia lập trình mac và thực hành nhanh khi chúng tôi di chuyển sang nơi làm việc. Tôi hiện đang cố gắng để có được một số mã hoạt động để thêm ứng dụng của tôi dưới dạng ứng dụng "Khởi chạy khi khởi động" bằng cách điều chỉnh mã vui lòng được cung cấp trên BDungan's blogSwift - khởi chạy ứng dụng Mac để khởi động khi khởi động

Cho đến giờ sau khi làm phiền trong nhiều giờ, tôi đã đưa ra những điều sau:

func itemRefInLoginItems() -> LSSharedFileListItemRef? 
{ 
    var itemRef: LSSharedFileListItemRef? = nil 
    var itemURL: Unmanaged<CFURLRef>? 

    let appURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) 


    if let loginItemsRef = LSSharedFileListCreate(kCFAllocatorDefault,kLSSharedFileListSessionLoginItems.takeRetainedValue(),NSMutableDictionary()) { 

     var unretainedLoginItemsRef = loginItemsRef.takeUnretainedValue() 

     if var loginItems = LSSharedFileListCopySnapshot(unretainedLoginItemsRef, nil) { 

      for item in (loginItems.takeRetainedValue() as NSArray) { 

       let currentItemRef = item as LSSharedFileListItemRef 

       var outRef: FSRef 
       if (LSSharedFileListItemResolve(currentItemRef, 0, &itemURL, nil) == noErr) { 

        if (appURL?.isEqual(itemURL?.takeRetainedValue()) != nil) { //PROBLEM 1 

         itemRef = currentItemRef 
        } 
       } 
      } 
     } 
    } 

    return itemRef 
} 

func isLaunchAtStartup() -> Bool { 

    let itemRef = self.itemRefInLoginItems() 
    return itemRef != nil 
} 

func makeLaunchAtStartup() { // Compile seems to fall down on this line... 

    if !self.isLaunchAtStartup() { 

     let loginItemsRef = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListSessionLoginItems.takeRetainedValue(), NSMutableDictionary()) 

     let appURL = NSURL(fileURLWithPath: NSBundle.mainBundle().bundlePath) as CFURLRef 
     let itemRef = LSSharedFileListInsertItemURL(loginItemsRef.takeRetainedValue(), kLSSharedFileListItemLast.takeRetainedValue(), nil, nil, appURL, nil, nil) 
    } 
} 

Tuy nhiên, tôi đang gặp hai vấn đề.

Vấn đề 1

Swift không muốn tôi để so sánh một NSURL đến một CFURLRef ... bây giờ tôi đã đi với một gợi ý Xcode chỉ để có được các ứng dụng đang chạy, nhưng tôi chắc chắn 100% nó không làm những gì tôi nghĩ. (xem // VẤN ĐỀ 1).

Trong mục tiêu-c có vẻ như cầu nối miễn phí được phép giữa NSURL và CFURLRef (hoặc CFURL), tuy nhiên, cố gắng truyền, cast có điều kiện hoặc bất kỳ sự nhanh chóng nào (Chèn ký tự đúng ở đây) tiếp cận mã của tôi chắc chắn sẽ không ' t xây dựng. Tôi nhận được lỗi như:

Switch không phải là một subtype của NSURL: if appURL as Unmanaged<CFURLRef> == itemURL

e.t.c.

Vấn đề 2

Mặc dù mã này hiện không đưa ra cảnh báo hoặc lỗi ... khi cố gắng biên soạn tôi nhận được một Command failed due to signal: Segmentation fault: 11, để được thẳng thắn ... là ngoài tôi.

Trả lời

11

Tôi đã cố gắng thực hiện công việc này dựa trên phương pháp tiếp cận mục tiêu C của Brian Dunagan. Tôi cũng chạy vào vấn đề lỗi biên dịch seg của bạn nhưng điều này đã được gây ra bởi cố gắng phôi để loại không hợp lệ; việc chỉnh sửa đúng loại vấn đề.

Tôi không thể nhận được kLSSharedFileListItemLast để trả về đúng tham chiếu mục tệp cuối cùng vì nó luôn gây ra lỗi seg. Để giải quyết vấn đề này, tôi đã sửa đổi hàm itemReferencesInLoginItems để trả về một bộ tham chiếu mục.

Mục đầu tiên trong bộ dữ liệu là tham chiếu ứng dụng hiện có nếu nó tồn tại, mục thứ hai là tham chiếu cuối cùng của danh sách. Sử dụng cách tiếp cận này, chúng ta có thể tránh phải dựa vào kLSSharedFileListItemLast.

Đây là mã, vui lòng sử dụng nó! Tôi rất muốn biết nếu có cách nào để có được kLSSharedFileListItemLast để hoạt động.

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

func itemReferencesInLoginItems() -> (existingReference: LSSharedFileListItemRef?, lastReference: LSSharedFileListItemRef?) { 
    var itemUrl : UnsafeMutablePointer<Unmanaged<CFURL>?> = UnsafeMutablePointer<Unmanaged<CFURL>?>.alloc(1) 
    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 
      println("There are \(loginItems.count) login items") 
      let lastItemRef: LSSharedFileListItemRef = loginItems.lastObject as LSSharedFileListItemRef 
      for var i = 0; i < loginItems.count; ++i { 
       let currentItemRef: LSSharedFileListItemRef = loginItems.objectAtIndex(i) as LSSharedFileListItemRef 
       if LSSharedFileListItemResolve(currentItemRef, 0, itemUrl, nil) == noErr { 
        if let urlRef: NSURL = itemUrl.memory?.takeRetainedValue() { 
         println("URL Ref: \(urlRef.lastPathComponent)") 
         if urlRef.isEqual(appUrl) { 
          return (currentItemRef, lastItemRef) 
         } 
        } 
       } else { 
        println("Unknown login application") 
       } 
      } 
      //The application was not found in the startup list 
      return (nil, lastItemRef) 
     } 
    } 
    return (nil, nil) 
} 

func toggleLaunchAtStartup() { 
    let itemReferences = itemReferencesInLoginItems() 
    let shouldBeToggled = (itemReferences.existingReference == nil) 
    let loginItemsRef = LSSharedFileListCreate(
     nil, 
     kLSSharedFileListSessionLoginItems.takeRetainedValue(), 
     nil 
     ).takeRetainedValue() as LSSharedFileListRef? 
    if loginItemsRef != nil { 
     if shouldBeToggled { 
      if let appUrl : CFURLRef = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { 
       LSSharedFileListInsertItemURL(
        loginItemsRef, 
        itemReferences.lastReference, 
        nil, 
        nil, 
        appUrl, 
        nil, 
        nil 
       ) 
       println("Application was added to login items") 
      } 
     } else { 
      if let itemRef = itemReferences.existingReference { 
       LSSharedFileListItemRemove(loginItemsRef,itemRef); 
       println("Application was removed from login items") 
      } 
     } 
    } 
} 
+1

gì sau sandbox Bật ? – ak2g

4

câu trả lời tuyệt vời nhưng bạn quên một câu lệnh if để kiểm tra ngăn chặn một lỗi từ unwraping một giá trị rỗng nếu không có mục nào tồn tại

Dưới đây là một giải pháp nhanh chóng cho một trong những chức năng, hy vọng nó sẽ giúp người

func itemReferencesInLoginItems() -> (existingReference: LSSharedFileListItemRef?, lastReference: LSSharedFileListItemRef?) { 
    var itemUrl : UnsafeMutablePointer<Unmanaged<CFURL>?> = UnsafeMutablePointer<Unmanaged<CFURL>?>.alloc(1) 
    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 
      println("There are \(loginItems.count) login items") 
      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 LSSharedFileListItemResolve(currentItemRef, 0, itemUrl, nil) == noErr { 
        if let urlRef: NSURL = itemUrl.memory?.takeRetainedValue() { 
         println("URL Ref: \(urlRef.lastPathComponent)") 
         if urlRef.isEqual(appUrl) { 
          return (currentItemRef, lastItemRef) 
         } 
        } 
       } 
       else { 
        println("Unknown login application") 
       } 
      } 
      //The application was not found in the startup list 
      return (nil, lastItemRef) 
      } 
      else 
      { 
       let addatstart: LSSharedFileListItemRef = kLSSharedFileListItemBeforeFirst.takeRetainedValue() 

       return(nil,addatstart) 
      } 
     } 
    } 
    return (nil, nil) 
} 

Lưu ý chỉ được thêm vào trong câu lệnh if sau

let loginItems: NSArray = LSSharedFileListCopySnapshot(loginItemsRef, nil).takeRetainedValue() as NSArray 

chức năng là dài cho một chú thích và tôi nghĩ rằng điều này sẽ có nhiều hữu ích hơn một vài dòng bình luận

Lưu ý: Cũng đã phải thay đổi giá trị trả về cho các danh sách rỗng

else 
{ 
    let addatstart: LSSharedFileListItemRef = kLSSharedFileListItemBeforeFirst.takeRetainedValue() 
    return(nil,addatstart) 
} 
+4

Lưu ý rằng trong OS X 10.10, 'LSSharedFileListItemResolve' không được chấp nhận. Tôi đã phải so sánh trực tiếp 'LSSharedFileListItemCopyResolvedURL (currentItemRef, 0, nil) .takeRetainedValue()' với 'currentItemUrl' để làm việc này (sau khi làm theo các gợi ý khác của XCode. – JacobEvelyn

+0

@JacobEvelyn Bạn có thể trình bày một ví dụ chính xác không? 'CurrentItemUrl' không phải là một phần của mã ban đầu và tôi không tìm ra những gì thực sự cần phải được so sánh – udondan

+2

Hình như mã của tôi là 'let currentItemUrl = LSSharedFileListItemCopyResolvedURL (currentItemRef, 0, nil) .takeRetainedValue()' nhưng tôi tin rằng điều này đã cho tôi lỗi trong một số trường hợp Công việc hacky của tôi: https://github.com/ComputeForHumanity/compute-for-humanity-app/commit/bd7369d4b07114a7eb7081d37e6a9bf025f5bb3f – JacobEvelyn

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