2

I'm overriding NSDocumentControllers reviewUnsavedDocuments(withAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo:) in Swift. The documentation says that the didReviewAllSelector has this signature, note it has 3 arguments:

- (void)documentController:(NSDocumentController *)docController  didReviewAll: (BOOL)didReviewAll contextInfo:(void *)contextInfo

So I need to invoke the selector on delegate with three arguments. The problem I'm facing is that I cant seem to find a neat way to do this in swift.

The closest match I can find is that NSObject has perform(aSelector:with:with:) taking 2 parameters. Is there something like this with 3 arguments?

Examaple code

func reviewUnsavedDocuments(withAlertTitle title: String?, cancellable: Bool, delegate: Any?, didReviewAllSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {

  if let object = delegate as? NSObject {
    object.perform(didReviewAllSelector, with: self, with: true ... and
              now I need to add contextInfo as a third paramenter here?
  }
}

I have done this successfully in obj-c using NSInvocation. But thats not available from swift :(

Craigt
  • 3,418
  • 6
  • 40
  • 56
  • 1
    I don't have control of `delegate` or `selector`. It's passed to me from a framework. This is a system method I'm overriding on NSDocumentController. – Craigt Aug 23 '19 at 06:54
  • I ended up writing an obj-c class that uses NSInvocation. – Craigt Aug 26 '19 at 08:59

1 Answers1

0

Using @convention(c) available since Swift 3

let methodIMP: IMP! = object.method(for: didReviewAllSelector)
unsafeBitCast(methodIMP,to:(@convention(c)(Any?,Selector,Any?,Bool, OpaquePointer)->Void).self)(object,didReviewAllSelector,self,true,OpaquePointer(contextInfo)) 

More info and examples covered in my answer here.

I believe OpaquePointer should work for your 3rd arg, but let me know if you run into any problems.

Kamil.S
  • 5,205
  • 2
  • 22
  • 51