Esta é uma ótima pergunta e, embora Chris Lattner intencionalmente não queira oferecer suporte a esse recurso, eu, como muitos desenvolvedores, também não posso deixar de lado meus sentimentos vindos de outras linguagens onde esta é uma tarefa trivial. Existem muitos unsafeBitCast
exemplos, a maioria deles não mostra a imagem completa, aqui está um mais detalhado :
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))
A parte interessante é como o Swift transmite livremente SwfBlock para ObjBlock, mas na realidade dois blocos SwfBlock fundidos sempre terão valores diferentes, enquanto ObjBlocks não. Quando lançamos ObjBlock para SwfBlock, a mesma coisa acontece com eles, eles se tornam dois valores diferentes. Portanto, para preservar a referência, esse tipo de fundição deve ser evitado.
Ainda estou compreendendo todo esse assunto, mas uma coisa que deixei de desejar é a capacidade de usar @convention(block)
métodos de classe / estrutura, então preenchi uma solicitação de recurso que precisa ser votada ou explicada por que é uma má ideia. Também tenho a sensação de que essa abordagem pode ser ruim, se for o caso, alguém pode explicar por quê?
MyClass.self
)