Search code examples
swiftcocoabackground-process

Swift - Using performSelectorOnMainThread


I'm trying to use – performSelectorOnMainThread:withObject:waitUntilDone: for a Cocoa application that I'm developing in Swift. I need the application to wait until the job is done. Anyway, I have the following lines of code.

func recoverData(path:String) -> Void {
    let sheetRect:NSRect = NSMakeRect(0,0,400,114)
    let progSheet:NSWindow = NSWindow.init(contentRect:sheetRect, styleMask:NSTitledWindowMask,backing:NSBackingStoreType.Buffered,`defer`:true)
    let contentView:NSView = NSView.init(frame:sheetRect)
    let progInd:NSProgressIndicator = NSProgressIndicator.init(frame:NSMakeRect(190,74,20,20))
    progInd.style = NSProgressIndicatorStyle.SpinningStyle
    let msgLabel:NSTextField = NSTextField.init(frame:NSMakeRect(20,20,240,46))
    msgLabel.stringValue = "Copying selected file..."
    msgLabel.bezeled = false
    msgLabel.drawsBackground = false
    msgLabel.editable = false
    msgLabel.selectable = false
    contentView.addSubview(msgLabel)
    contentView.addSubview(progInd)
    progSheet.contentView = contentView

    self.window.beginSheet(progSheet) {(NSModalResponse returnCode) -> Void in
        progSheet.makeKeyAndOrderFront(self)
        progInd.startAnimation(self)
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        dispatch_async(dispatch_get_global_queue(priority,0)) {

            //////////////////////////////////////////////////////////////////////////////////////////////////
            self.performSelectorOnMainThread(Selector(self.readData(path)),withObject:path,waitUntilDone:true)
            //////////////////////////////////////////////////////////////////////////////////////////////////

        }

        dispatch_async(dispatch_get_main_queue()) {
            progInd.indeterminate = true
            self.window.endSheet(progSheet)
            progSheet.orderOut(self)
        }
    }
}

func readData(path:String) -> Void {
    print("Hello!?")
}

I'm not sure how I pass path to readData. Xcode requires me to set the argument to something other than nil or nothing. In Objective-C, it would be

[self performSelectorOnMainThread:@selector(readData:) withObject:path waitUntilDone:YES];

Anyway, the application never reaches readData. What am I doing wrong?

Thanks for help.


Solution

  • Why not

    self.window.beginSheet(progSheet) {(returnCode) -> Void in
        dispatch_async(dispatch_get_main_queue()) {
            progInd.startAnimation(self)
            self.readData(path)
            progInd.indeterminate = true
        }
    }
    

    At some point you have to call self.window.endSheet(progSheet) to dismiss the sheet and call the completion handler.

    Edit:

    I guess you actually mean something like this

    ...
      self.window.beginSheet(progSheet) {(returnCode) -> Void in
        progInd.stopAnimation(self)
        progInd.indeterminate = true
    
      }
    
      progInd.startAnimation(self)
      let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
      dispatch_async(dispatch_get_global_queue(priority,0)) {
        self.readData(path) {
          dispatch_async(dispatch_get_main_queue()) {
            self.window.endSheet(progSheet)
          }
        }
      }
    }
    
    func readData(path:String, completion: (()  -> Void))  {
      print("Hello!?")
      completion()
    }