Questa è una grande domanda e anche se Chris Lattner non vuole intenzionalmente supportare questa funzione, io, come molti sviluppatori, non posso lasciare andare i miei sentimenti provenienti da altre lingue in cui questo è un compito banale. Ci sono molti unsafeBitCast
esempi, la maggior parte di loro non mostra il quadro completo, eccone uno più dettagliato :
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 parte interessante è come swift lancia liberamente SwfBlock su ObjBlock, ma in realtà due blocchi SwfBlock lanciati avranno sempre valori diversi, mentre ObjBlocks no. Quando lanciamo ObjBlock a SwfBlock, succede loro la stessa cosa, diventano due valori diversi. Quindi, al fine di preservare il riferimento, questo tipo di fusione dovrebbe essere evitato.
Sto ancora comprendendo l'intero argomento, ma una cosa che ho lasciato desiderare è la capacità di utilizzare @convention(block)
sui metodi class / struct, quindi ho presentato una richiesta di funzionalità che necessita di un voto positivo o di spiegare perché è una cattiva idea. Ho anche la sensazione che questo approccio potrebbe essere cattivo tutto insieme, se è così, qualcuno può spiegare perché?
MyClass.self
)