C'est une excellente question et bien que Chris Lattner ne veuille intentionnellement pas supporter cette fonctionnalité, je ne peux pas, comme beaucoup de développeurs, abandonner mes sentiments venant d'autres langues où c'est une tâche triviale. Il y a beaucoup d' unsafeBitCast
exemples, la plupart d'entre eux ne montrent pas l'image complète, en voici un plus détaillé :
typealias SwfBlock = () -> ()
typealias ObjBlock = @convention(block) () -> ()
func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
let objA = unsafeBitCast(a, AnyObject.self)
let objB = unsafeBitCast(b, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testAnyBlock(a: Any?, _ b: Any?) -> String {
if !(a is ObjBlock) || !(b is ObjBlock) {
return "a nor b are ObjBlock, they are not equal"
}
let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
class Foo
{
lazy var swfBlock: ObjBlock = self.swf
func swf() { print("swf") }
@objc func obj() { print("obj") }
}
let swfBlock: SwfBlock = { print("swf") }
let objBlock: ObjBlock = { print("obj") }
let foo: Foo = Foo()
print(testSwfBlock(swfBlock, swfBlock))
print(testSwfBlock(objBlock, objBlock))
print(testObjBlock(swfBlock, swfBlock))
print(testObjBlock(objBlock, objBlock))
print(testAnyBlock(swfBlock, swfBlock))
print(testAnyBlock(objBlock, objBlock))
print(testObjBlock(foo.swf, foo.swf))
print(testSwfBlock(foo.obj, foo.obj))
print(testAnyBlock(foo.swf, foo.swf))
print(testAnyBlock(foo.swfBlock, foo.swfBlock))
La partie intéressante est la façon dont Swift convertit librement SwfBlock en ObjBlock, mais en réalité, deux blocs SwfBlock coulés auront toujours des valeurs différentes, contrairement à ObjBlocks. Lorsque nous convertissons ObjBlock en SwfBlock, la même chose leur arrive, ils deviennent deux valeurs différentes. Ainsi, afin de préserver la référence, ce type de casting doit être évité.
Je comprends toujours tout ce sujet, mais une chose que j'ai laissée espérer est la possibilité d'utiliser @convention(block)
des méthodes de classe / structure, j'ai donc déposé une demande de fonctionnalité qui nécessite un vote ascendant ou expliquant pourquoi c'est une mauvaise idée. J'ai aussi le sentiment que cette approche pourrait être mauvaise dans l'ensemble, si oui, quelqu'un peut-il expliquer pourquoi?
MyClass.self
)