Swift Closure as Anyobject

Swift closure as AnyObject

How can I cast ()->() into AnyObject ?

Warning: This answer includes undocumented and unsafe feature in Swift. I doubt this passes AppStore review.

let f: ()->() = {
println("test")
}

let imp = imp_implementationWithBlock(
unsafeBitCast(
f as @objc_block ()->(),
AnyObject.self
)
)

Convert a swift closure into a block

It should be something like this:

-(void) testMethod:(void(^) (id gbRequest, ServiceStatus *serviceStatus, id response) ) blockName {

}

Swift's AnyObject equivalent is id in Objective-C.

Swift Cast AnyObject to Block

The best way to handle this situation is to create your own typealias for your block:

 typealias MyFunBlock = @objc_block (dataResponse :AnyObject!) -> Void;

Then you can use that to unsafebitcast:

var block: MyFunBlock = unsafeBitCast(completeBlock, MyFunBlock.self) as MyFunBlock;

Closure inference in Swift

I don't think this has anything to do with closures or inference. It seems to be a simple matter of types and casting.

You cannot "sideways cast" an AnyObject to a Dictionary (or to anything else for that matter). You have to force-cast it, using as!

Plus, there is no such thing in Swift as a Dictionary plain and simple, because it is a generic. The most general type of dictionary is [AnyHashable:Any].

So the initial cast of s needs to be:

(s as! [AnyHashable:Any])

And by the same token you cannot "sideways cast" the resulting value taken from the dictionary; you must force-cast it:

as! [AnyObject]

Now you can write the whole line as:

return (s as! [AnyHashable:Any])["availabilities"] as! [AnyObject]

Of course, what you're doing here seems completely crazy; you should not be turning anything into an AnyObject. But perhaps this is a toy example drawn from some other context, e.g. you've got JSON coming in? But in that case you should be using Codable to organize the JSON into real objects.

Pass a swift closure to an objective-C function which takes a block as parameter

I think this could be a shortcut to your problem:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void){
let objCObject = ObjectiveCClass()

objCObject.fetchChannelListForWatch { (dict) -> Void in
replyHandler(dict as! [String : AnyObject]?)
}
}

Swift closure as values in Dictionary

Your basic problem is that in Objective-C closures (aka blocks) are represented as NSObject (or more precisely are transparently converted to NSObjects) while in Swift there is no such mapping. This means that closures can not be directly stored in a Dictionary (short of using objective-c glue)

The closest I can come up with is something along the lines of wrapping the value in an enum:

enum DataType {
case AsString(String)
case AsClosure((AnyObject)->String)
}

var dict:Dictionary<String,DataType> = [
"string":DataType.AsString("value"),
"closure":DataType.AsClosure({(argument:AnyObject) -> String in
return "value"
}
)
]

Which is probably a better solution anyway, because this way you have an explicit typing associated with individual arguments instead of it being implicit using some sort of inflection.

Alternatively, you could only wrap the closure and use a dictionary of type Dictionary<String,Any>.

Convert Swift 2 closure to Objective-C block

EDIT : As of Swift 3, this is completely unnecessary (and doesn't even work). Adding closures to Objective-C arrays works out of the box in Swift 3. The answer below is valid for Swift 2 only.

I know this is a duplicate but I will still post a refactored answer from swift-closure-as-anyobject and cast-closures-blocks in case anyone lands on this one first.

The solution is to use the unsafeBitCast function to convert the Swift closure to an Objective-C compatible object before adding it to an NSArray and back before using it in Swift.

// The `@convention(block)` is important here in order to get
// Objective-C like memory management
typealias CompletionBlock = @convention(block) () -> Void

let aBlock:CompletionBlock = {
print("Hello world!")
}
let nsArray = NSMutableArray()
let blockObject = unsafeBitCast(aBlock, AnyObject.self)
nsArray.addObject(blockObject)

let closureObject = nsArray[0]
let closure = unsafeBitCast(closureObject, CompletionBlock.self)
closure()


Related Topics



Leave a reply



Submit