[Résolu] utilisation d'une méthode "map" dans un block

LouLou Membre
octobre 2014 modifié dans API UIKit #1

Salut,


si on devait réécrire la fonction "map" du block, qu'est-ce que ça donnerait? Apparemment, ce code parcourt chaque élément du dictionnaire *json, et remplace chaque item par un objet MTLJsonAdapter ? J'ai vu que pour créer un block, le code ressemble à  quelque chose comme ... map(monDic); dans la fonction prévue au préalable, et le résultat se fait dans le callback. Mais comment la fonction "map" a été écrite pour faire une boucle sur chaque item du dictionnaire?


 


La ligne est à  [list map:^ ...


le tuto est sur le site de raywenderlich : lien  ;)



- (RACSignal *)fetchDailyForecastForLocation:(CLLocationCoordinate2D)coordinate {
NSString *urlString = [NSString stringWithFormat:@http://api.openweathermap.org/data/2.5/forecast/daily?lat=%f&lon=%f&units=imperial&cnt=7,coordinate.latitude, coordinate.longitude];
NSURL *url = [NSURL URLWithString:urlString];

// Use the generic fetch method and map results to convert into an array of Mantle objects
return [[self fetchJSONFromURL:url] map:^(NSDictionary *json) {
// Build a sequence from the list of raw JSON
RACSequence *list = [json[@list] rac_sequence];

// Use a function to map results from JSON to Mantle objects
return [[list map:^(NSDictionary *item) {
return [MTLJSONAdapter modelOfClass:[WXDailyForecast class] fromJSONDictionary:item error:nil];
}] array];
}];
}

Merci :)


Réponses

  • colas_colas_ Membre
    octobre 2014 modifié #2

    Imagine que tu as une classe MyObject qui a une @property (strong) NSArray *array.


     


    Alors, tu coderas une méthode - (void)map:(void(^)(id obj)myBlock comme suit



    - (void)map:(void(^)(id obj)myBlock
    {
    for (id obj in self.array)
    {
    myBlock(obj) ;
    }
    }

    Ce lien m'aide souvent : http://fuckingblocksyntax.com/


     


     


    PS : avant d'utiliser un block, il vaut mieux tester s'il n'est pas nil. D'où :



    - (void)map:(void(^)(id obj)myBlock
    {
    if (!myBlock)
    {
    return ;
    }

    for (id obj in self.array)
    {
    myBlock(obj) ;
    }
    }
  • D'accord, merci, alors:


    - le "obj" de :" (id obj)myBlock " représente quoi?


    - Dans notre cas, self.array serait en fait la "list"?


  • colas_colas_ Membre
    octobre 2014 modifié #4

    Le obj représente le paramètre passé à  ton block.


    Si tu sais que ton NSArray * est composé que de NSString, tu aurais pu faire :



    - (void)map:(void(^)(NSString * name)myBlock
    {
    if (!myBlock)
    {
    return ;
    }

    for (NSString * name in self.array)
    {
    myBlock(name) ;
    }
    }

    Tu peux créer de telles méthodes sur n'importe quel objet.


    Ici, c'est une méthode d'instance sur la classe RACSequence.


  • D'accord, merci :)


  • AliGatorAliGator Membre, Modérateur
    octobre 2014 modifié #6
    colas tu oublies systématiquement une parenthèse fermante dans tes codes précédents dans ta syntaxe de blocks. Forcément, ça ne peut que dérouter.
    La bonne syntaxe est la suivante en fait :
    - (void)map:( void(^)(id item) )block
    Et sinon une implémentation de map serait plutôt du genre de celle-ci, puisque map est sensé retourner un NSArray des objets mappés :
    @interface NSArray (Map)
    /**
    Returns a new array in which items are the result of applying
    the block to each item of the original array

    Example:
    NSArray* orig = @[;@Hello,@World];
    NSArray* mapped = [orig map:^(id item) {
    return @( [item uppercaseString] );
    }];
    // --> mapped = @[;@HELLO,@WORLD]
    */
    - (NSArray*)map:( void(^)(id item) )block;
    @end
    @implementation NSArray (Map)
    - (NSArray*)map:( void(^)(id item) )block
    {
    NSParameterAssert(myBlock != nil);
    NSMutableArray* mappedArray = [[NSMutableArray alloc] initWithCapacity:self.count];
    for(id item in self) {
    [mappedArray addObject:block(item)];
    }
    return [mappedArray copy];
    }
    @end
  • Top, merci de vos réponses ;)


  • Alors... je suis pas certain d'avoir compris un truc: le "name" de l'exemple de colas, ici : (NSString * name)myBlock , veut dire que le paramètre de myBlock(name) sera un string? Est-ce que le nom "name" doit être le même, même si on redéfinit le type "NSString *" dans la boucle for ? : for (NSString * name in self.array) 


     (J'espère avoir été assez clair :) )


  • AliGatorAliGator Membre, Modérateur
    Oui ça veut bien dire que ça sera un NSString. Et non on n'est pas obligé d'utiliser le même.

    D'ailleurs, quand on ne fait que déclarer le bloc, on n'est même pas obligé de préciser un nom au paramètre (mais on aime bien le faire pour que ça soit plus lisible " si on peut parler de lisibilité avec cette syntaxe pourrie des blocks ^^)

    - (NSArray*)map:(  void(^)(NSString* pouetpouetbadaboum)  )block
    {
    ...
    // on itère sur self (un NSArray), et à  chaque itération, la variable qui contiendra l'élément courant va s'appeler "item"
    for(NSString* item in self)
    {
    block(item); // Et donc là  on appelle block sur cet élément courant item
    }
    ...
    }
    On aurait pu écrire aussi ceci, sans même mettre de nom au paramètre NSString, ce qui importe au compilateur c'est que "map" est une méthode qui prend en paramètre "void(^)(NSString*)", autrement dit "un block qui prend une NSString* en paramètre et retourne void", il s'en fiche du nom que tu donnes à  la variable qui contiendra le paramètre à  ce moment :

    - (NSArray*)map:( void(^)(NSString*) )block
    {
    ...
    }
    Par contre quand toi tu vas appeler map et lui passer un block, tu auras certainement besoin de manipuler ce paramètre (pour dire ce que tu vas vouloir lui faire faire, à  cet élément sur lequel tu itères) :

    [array map:^(NSString* eachItem) {
    NSLog(@Iteration sur : %@", eachItem);
    }];
    Là  localement j'ai appelé mon paramètre eachItem, alors que dans la déclaration de "map:" j'ai même pas donné de nom, et que dans l'implémentation de "map:" quand j'applique ma boucle for j'ai utilisé encore un autre nom de variable pour itérer sur chaque élément de mon tableau.
  • OK parfait, merci !


  • Les affres du copier/coller et de la fu....ing syntax des blocks !


Connectez-vous ou Inscrivez-vous pour répondre.