Search code examples
swift3xcode8finderscripting-bridgemacos-sierra

ScriptingBridge code errors in Xcode 8.0 and swift 3.0


This is the code I used in Xcode 7.3.1 and that worked fine:

    var selectedFiles = NSMutableArray(capacity:1)
    let  finder: AnyObject! = SBApplication(bundleIdentifier:"com.apple.finder")
    let finderObject = finder.selection as! SBObject
    let selection: AnyObject! = finderObject.get()
    let items = selection.arrayByApplyingSelector(Selector("URL"))

    let filteredfiles = (items as NSArray).pathsMatchingExtensions(["ai","pdf","ap","paf","pafsc"])
    for  item in filteredfiles {
        let url = NSURL(string:item ,relativeToURL:nil)
        selectedFiles.addObject(url!)
    }

This is the code corrected for Xcode 8.0 and that does not work: the error is generated for the last line

error = Cannot call value of non-function type '[Any]!'

    var selectedFiles = NSMutableArray(capacity:1)
    let  finder: AnyObject! = SBApplication(bundleIdentifier:"com.apple.finder")
    let finderObject = finder.selection as! SBObject
    if let selection = finderObject.get()  as AnyObject?{
        let items =  selection.array(#selector(getter: NSTextCheckingResult.url))
        let filteredfiles = (items as NSArray).pathsMatchingExtensions(["ai","pdf","ap","paf","pafsc"])
        for  item in filteredfiles {
          let url = NSURL(string:item ,relativeToURL:nil)
          selectedFiles.addObject(url!)
       }
    }

I have tried many solutions, but unfortunately cannot find a clue. I guess this is because Swift 3.0x APIs have changed drastically.... Any help is welcome!


Solution

  • This is a slightly different approach using a couple of native Swift functions for Swift 3

    var selectedFiles = [URL]()
    let  finder : AnyObject = SBApplication(bundleIdentifier:"com.apple.finder")!
    let finderObject = finder.selection as! SBObject
    if let selection = finderObject.get() as? [SBObject] {
      selection.forEach { item in
          let url = URL(string: item.value(forKey:"URL") as! String)!
          selectedFiles.append(url)
        }
    
      let goodExtensions = ["ai","pdf","ap","paf","pafsc"]
      let filteredURLs = selectedFiles.filter({goodExtensions.contains($0.pathExtension)})
      print(filteredURLs)
    }
    

    PS: I highly recommend to use AppleScriptObjC. It's so much easier to use.

    PPS: valueForKey is intentionally used because KVC is really needed to get the property value.