1

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!

Kader Mokhefi
  • 341
  • 4
  • 15

1 Answers1

2

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.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thanks for the lightning fast answer. It works very well. I used to make my projects with AppleScriptObjC, but I try in most cases to use native Swift with a minimum of other helpers. Sometimes it is not possible otherwise! – Kader Mokhefi Sep 29 '16 at 17:35
  • The reason folk recommend using AppleScriptObjC is that ScriptingBridge is riddled with bugs and crippled/missing features than cause many commands that work perfectly in AS to fail in SB. That said, both are more fiddly to use in Swift than ObjC due to Swift's much stricter typing. FWIW I'm currently developing a native [Swift-to-AppleEvent bridge](https://bitbucket.org/hhas/swiftae) as a true Swift-friendly alternative to AppleScript that you're welcome to play with, although be aware that my long-term support for it will depend on how much backing it can attract amongst Apple/Swift devs. – foo Oct 06 '16 at 17:30
  • Regarding "highly recommend to use `AppleScriptObjC`", what would a Swift `AppleScriptObjC` selectedFinderFiles implementation look like? Would a Swift `AppleScriptObjC` implementation be possible without adding any Objective-C or AppleScript code? – marc-medley Dec 06 '16 at 16:48
  • 1
    Using `AppleScriptObjC` in a Swift app needs a tiny ObjC bridge but all code related to AppleScript can be native AppleScript (can be mixed with a kind of Objective-C syntax). A benefit is that you can easily call native AppleScript handlers from Swift code. Look [here](http://stackoverflow.com/questions/32081748/parsing-excel-data-in-apple-swift/32083098#32083098) for an example – vadian Dec 06 '16 at 16:59