Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'NSSecureCoding!' is not a subtype of 'NSURL' using Swift when trying to replace closure argument type

I'm using the loadItemForTypeIdentifier:options:completionHandler: method on an NSItemProvider object to extract a url from Safari via a Share extension in iOS 8.

In Objective-C, this code compiles and works:

    [itemProvider loadItemForTypeIdentifier:(@"public.url" options:nil completionHandler:^(NSURL *url, NSError *error) {
        //My code
    }];

In Swift however, I'm getting "NSSecureCoding!' is not a subtype of 'NSURL" compile error when I try to do something similar:

    itemProvider.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { (urlItem:NSURL, error:NSError!) in
        //My code
    })

If I add the bang to NSURL argument type as in NSURL! I get "Cannot convert the expression's type 'Void' to type 'Void'" compile error. And if I leave the default argument typed as NSSecureCoding!, it compiles, but the block/closure doesn't run.

What am I doing wrong?

like image 549
abc123 Avatar asked Jan 31 '26 15:01

abc123


2 Answers

You don't need to specify the types for urlItem or error as they can be inferred from the declaration of loadItemForTypeIdentifier:options:completionHandler. Just do the following:

itemProvider.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { 
    (urlItem, error) in
    //My code
})

Even better, you can move the closure outside of the method call:

itemProvider.loadItemForTypeIdentifier("public.url", options: nil) {
    (urlItem, error) in
    //My code
}
like image 194
drewag Avatar answered Feb 02 '26 03:02

drewag


This API makes use of reflection internally: it looks at the type of the block’s first parameter to decide what to return. This is dependent on Objective-C’s looser enforcement of the block signature compared to Swift — and therefore does not work in Swift. (Yes, still.) See this discussion on the developer forums.

I recommend filing a bug report with Apple and writing small Objective-C wrapper methods to read each type of data you need.

It’s possible I’ve overlooked something. If someone has found a neat way to make this work in Swift I’m keen to hear it.

like image 22
Douglas Hill Avatar answered Feb 02 '26 05:02

Douglas Hill



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!