11
votes

Fermeture rapide comme anyobject

im essayant d'utiliser cette méthode: class_addmethod () qui dans obj-c est utilisé comme suit: xxx

et je l'utilise comme ceci à Swift: xxx

Il s'agit d'une extension pour uibarbuttonitem comme vous l'avez peut-être affiché.

imp_implementationwithblock prend un paramètre de type anyobject!

Comment puis-je lancer () -> () dans

J'ai essayé de la jeter comme ceci: gestionnaire comme anyobject mais cela me donne une erreur disant: () -> () ne se conforme pas au protocole 'NyObject'


1 commentaires

Avez-vous essayé d'utiliser réinterpretcast () ?


7 Réponses :


4
votes

Vous ne pouvez pas. Vous ne pouvez le mettre que sur tout .

  • anyobject peut représenter une instance de n'importe quel type de classe.
  • tout peut représenter une instance de n'importe quel type, y compris les types de fonctions.

    Apple Inc. "Le langage de programmation rapide". Ibooks. https://itun.es/de/jeuh0.l


5 commentaires

Mais y a-t-il une autre façon de le faire de quelque manière que ce soit?


Avez-vous essayé de passer sélecteur ("gestionnaire") ? Pouvez-vous montrer la signature de imp_implementatationwithblock ?


L'erreur n'est pas la partie sélecteur, c'est l'IMP_IMPLEVEMENTATIONAlue () qui provoque une confusion


imp_implementatationwithblock (bloc: anyobject!) Ne prend qu'un paramètre AnyObject en tant que paramètre et retourne un IMP


Son trouvé dans les références d'exécution de l'objectif-c



11
votes

Comment puis-je lancer () -> () code> dans anyObject code>? p>

AVERTISSEMENT FORT>: Cette réponse comprend une fonctionnalité non documentée et dangereuse à Swift. Je doute que cela passe la revue d'AppStore. P>

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

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


7 commentaires

Qu'est-ce que 'F'? Est-ce la fermeture?


Alors pourquoi APPLE A FUNC IMP_IMPLEVEMENTATIONWIBLOCK (_ Block: anyObject!) -> IMP dans la référence LIB Si vous avez besoin de ce code que vous avez posté? Bogue?


Le code Obj-C peut passer des blocs à Swift AnyObject Type Paramètre.


Si vous souhaitez ajouter ceci comme une extension, vous êtes libre de l'utiliser: Extension UIBARBUTTONITEM {COMPIENCE INIT (Titre: String?, Style: UibarbuttonItemStyle, Hangler: () -> () -> ()) {Imple Imp = Imp_ImplementaationwithBlock (Infarebitcast (Handler comme @OBJC_Block () -> (), anyobject.elf)) Class_addmethod (Uibarbuttonitem.elf, "Handler", Imp, "V @:") Self.Init (Titre: Titre, Style: Style, Target: Nil , action: "gestionnaire") self.target = auto}}


Je ne suis pas sûr que cette extension fonctionne comme prévu. Pour autant que je sache, la méthode est une propriété de classe, pas une instance locale. Donc, je pense que ces résultats chaque instance partage le même gestionnaire, non?


HMM peut-être que la méthode sera créée pour chaque sauf que celles que j'ajoute le gestionnaire pour essayer de l'appeler. Mais je vais le tester plus loin.


Devrait utiliser @convention au lieu de @OBJC_block



2
votes

Cela a fonctionné pour moi:

let myBlock: @objc_block () -> Void = { 
}
var mf : AnyObject = unsafeBitCast(myBlock, AnyObject.self)


0 commentaires

8
votes

Vous pouvez écrire une enveloppe, puis transmettez-la à la fonction

class ObjectWrapper<T> {
    let value :T
    init(value:T) {
       self.value = value
    }
}

let action = ObjectWarpper(value: {()->() in    
    // something
})


0 commentaires

5
votes

Dans Swift 2, vous devez utiliser @convention code> au lieu de @OBJC_block code>. Voir Attribut de type

func swizzle(type: AnyClass, original: Selector, methodType: MethodType, block: () -> Void) {
    let originalMethod = method(type, original: original, methodType: methodType)

    let castedBlock: AnyObject = unsafeBitCast(block as @convention(block) () -> Void, AnyObject.self)

    let swizzledImplementation = imp_implementationWithBlock(castedBlock)
    // More code goes here
}


0 commentaires

0
votes

Utiliser tout objet (le protocole sur lequel tous les types sont conformes implicitement) xxx


0 commentaires

1
votes

Dans Swift 4.x (je pense que fonctionne aussi dans 3.x), déclarant simplement la fermeture comme @convention (bloc) code> devrait suffire à lutter contre la compatibilité:

// define the new implementation
let handler: @convention(block) (UIBarButtonItem) -> Void = { _ in }

// inject it into the class
class_addMethod(NSClassFromString("UIBarButtonItem"), sel_registerName("handler"), imp_implementationWithBlock(handler), "v@:")


0 commentaires