12
votes

Est-il possible de créer une catégorie d'objet "bloc" dans l'objectif-c

Je voudrais ajouter des fonctions en créant une catégorie pour les blocs de l'objectif-c. xxx

au lieu de simplement permettre à la normale [copie Ablock] , [Ablock conserver] , [version Ablock] , [Ablock AutoRelease] . Je pourrais faire une chose comme: xxx

catégorie possible xxx


3 commentaires

Incidemment, j'ai commencé à travailler sur une bibliothèque de l'objectif-C qui ajoute une carte et des fonctions associées à Nsarray et nsset : GITUB.COM/MDIPPERY/Collections


@MIPADI: Êtes-vous au courant de la carte existante comme fonctionnalité par ex. -EnumerateObjectSouxBlock: et Valurforkey:


@JeremyP: Oui, mais (a) Ce n'est que sur 10.6, et (b) Je suis en train de mettre en œuvre le reste du protocole de collections SmallTalk, ainsi que certaines fonctionnalités de la classe énumérable de Ruby.


5 Réponses :


-2
votes

La réponse simple est non. Une variable __block est un objet de niveau C et non un objet C objectif C. Vous pouvez appeler [copie ABLOCK], mais cela invoque une fonction de fonction C_copy () non la méthode de copie NsObject. Donc, le type __block est un type C et que vous ne pouvez donc pas ajouter de catégories.

Correction: __ bloc est un identifiant dans le compilateur C pas un typlef.

Je ne suis pas sûr que cela atteindra Ce que vous pensez que cela, n'infort que je ne suis même pas tout à fait sûr de ce qu'il fait: xxx

L'identifiant __block indique à la compliance que la variable doit être mutable dans les blocs de référencement et devrait être préservé si un bloc de référencement est copié sur le tas. Ce qui me confond de votre code est que __block est généralement utilisé pour envelopper une variable, pas un bloc lui-même.


2 commentaires

__ bloc me permet de passer ablock dans le bloc. J'ai renommé le bloc et j'ai oublié de renommer les références fib .


Les blocs sont en réalité des types C et des types d'objectifs. Vous pouvez associer des objets avec eux à l'aide d'API d'exécution OBJC, vous pouvez les mettre dans les collections OBJC, etc. et pourtant elles sont toujours valables dans des programmes C-seul uniquement. C'est un bit net de travail de compatibilité délicat par le compilateur et les gens d'exécution :)



6
votes

Un bloc qui vale d'être une instance de type __ nsglobalblock __ code>, comme on le voit dans l'extrait suivant: xxx pré>

afin de créer une catégorie d'une classe, le Le compilateur doit pouvoir voir l'original @interface code> Déclaration de la classe. Je ne trouve pas la déclaration pour __ nsglobalblock __ code> et probablement pour une bonne raison. P>

cet article et Cet article contient des informations utiles sur la mise en œuvre de blocs. P>

à votre point d'origine, pourquoi ne pas simplement créer une catégorie de nsarray Pour votre MapTo code> Méthode? Il semble être un meilleur endroit pour ce type de fonctionnalité. P>

mis à jour p> p>

Disons que vous pouvez em> Ajouter une catégorie à la Objet block. Comment allez-vous appeler le bloc de la méthode de la catégorie? Au meilleur de ma compréhension, la seule façon d'appeler un bloc est via l'opérateur () code> (E.G., ablock () code>). Je ne pense pas qu'il y ait un moyen de dire à l'objet de bloc, le nombre et les types de paramètres. Donc, quels arguments passeriez-vous à l'invocation des blocs? P>

Je ne vous recommande pas de faire cela, mais les travaux suivants ... P>

@interface NSObject (BlockExtension)
- (void)foo;
@end

@implementation NSObject (BlockExtension)
- (void)foo
{
    // not sure how else to determine if self is a Block since neither
    // __NSGlobalBlock__ nor any of its superclasses (except NSObject) 
    // are accessible to the compiler
    if ([[[self class] description] isEqual:@"__NSGlobalBlock__"])
    {
        NSLog(@"foo");
        // now what?
        // can't call self(), it doesn't compile
        // how else can I invoke this block?
    }
}
@end

...

void (^aBlock)(void) = ^(void) {
    NSLog(@"Hello world");
};

// prints "foo"
[aBlock foo];


2 commentaires

J'utilisais juste Mapto à titre d'exemple. Je peux penser à une demande assez importante pour une telle catégorie: la composition de la fonction, le currying, etc.


Intelligent, oui, mais dangereux. Il n'y a aucune garantie que les différentes classes NSBLOCK inhérentes à NsObject pour toujours ...



13
votes

@PWC est correct en ce que vous ne pouvez pas créer une catégorie pour une classe que vous ne pouvez pas voir.

Cependant ...

Ce que je suis sur le point de vous dire devrait être utilisé. Strictement comme un exercice d'apprentissage et jamais dans une sorte de réglage de la production.
  1. Certaines introspection d'exécution révèlent des informations intéressantes. Il existe un certain nombre de classes contenant le mot "bloc". Certains d'entre eux ont l'air prometteurs: __ nstackblock , __ nsmallocblock , __ nsautoblock et nsblock . .
  2. Une autre introspection montre que les classes prometteuses hériter de nsblock

    Il semble que tout bloc fonctionne d'une instance ou d'une sous-classe de nsblock .

    Vous pouvez créer une méthode sur un objet, comme le cas échéant: xxx

    puis au moment de l'exécution, vous pouvez déplacer cette méthode dans la classe nsblock Classe: xxx

    Après cela, les blocs devraient répondre au message dofoo .

    Utilisez à vos risques et périls, et uniquement pour expérimenter.


4 commentaires

Yikes! :) Une autre option consiste à simplement faire une catégorie sur NsObject , et promettez uniquement de l'utiliser sur des blocs ... De toute façon, c'est un peu effrayant, et je préférerais la sécurité du [Utilitaire Quelque chosewithblock: bloquer] et [ARR Carte: bloquer] sur la peur de [bloquer dosshanging] et [bloquer la carte: arr] < / code> ...


Alien peut-être, mais pas effrayant. Ceci est très courant dans Smalltalk, qui a inspiré l'objectif-c. Il n'y a pas de syntaxe de contrôle dans Smalltalk. Donc, une déclaration IF ressemblerait à [^ bool {retour A> 1} iftrue: ^ {...}] (sauf un nettoyant de lot dans SmallTalk: [A> 1] Sitrue: [...].)


Mais (corrigez-moi si je me trompe), les objets de blocage ne sont pas réellement garantis de descendre de NsObject ...


@Jonathan Je ne suis pas sûr de Garanti , mais l'introspection d'exécution montre que la classe privée nsblock classe est une sous-classe de NsObject . Cela fonctionne donc pour le violon, mais (comme je le dis dans le poteau), il est au-delà de stupide d'utiliser ceci dans n'importe quelle sorte de réglage de la production.



1
votes

Dave Delong a raison, vous ne pouvez pas ajouter une catégorie sur une classe que vous ne pouvez pas voir, mais comme les blocs sont des sous-classes de nsblock Ajout: xxx

maintenant vous peut 'voir' nsblock et ajouter une catégorie dessus, par exemple: xxx

toujours probablement pas la meilleure chose à faire dans le code qui est réellement utilisé en production ...


0 commentaires

0
votes
WRONG: A block winds up being an instance of type __NSGlobalBlock__, as seen in the     
following snippet:

int i = 0;
id o = [class self];

void (^aBlock)(void) = ^(void) {

    [o setValue:0];

    NSLog(@"Hello world %d", i);
};

// prints "type = __NSGlobalBlock__" 

// Now it prints __NSStackBlock__ 
// and when moved into HEAP prints __NSMallocBlock__

NSLog(@"type = %@", [aBlock class]);
It is only OKAY to say that a block winds up being an instance of type "NSGlobalBlock" unless there are no captured variables in the scope, otherwise it will be created in the STACK  and when it is copied that will move the block into HEAP and every reference will be retained!

0 commentaires