简体   繁体   中英

passing __block parameters to class method (for get request)

I want to create the following class method:

+(void) getValue4Key:(NSString*)p_key andSet:(id)p_variable
{    
    NSString *baseURLString = <<myURL>>;
    @try{
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        [manager GET:baseURLString
          parameters:nil
             success:^(AFHTTPRequestOperation *operation, id responseObject) {
                 NSDictionary* element = responseObject[0];
                 element = [element objectForKey:@"fields"];

                 p_variable = [element objectForKey:@"value"];
             }
             failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                 NSLog(@"getSystemVariableKey error: %@",error);
             }];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@", exception);
    }
}

Two questions:

  1. I get the following error: Variable is not assignable (missing __block type specifier) how can I set a block to the method parameter?
  2. How to call this function should I pass the variable with &self.setMe ?

I don't think the approach of passing an ivar by reference to be set asynchronously at some later time is a good approach. What if the object (referred to in question #2 as the self in self.setMe ) is destroyed before the request completes? You're going to have random crashes.

Instead, you should approach this with a completion block that callers can use to set the ivar:

+ (void)getValue4Key:(NSString*)p_key 
      withCompletion:(void (^)(id value))completion
{    
    NSString *baseURLString = <<myURL>>;
    @try{
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        [manager GET:baseURLString
          parameters:nil
             success:^(AFHTTPRequestOperation *operation, id responseObject) {
                 NSDictionary* element = responseObject[0];
                 element = [element objectForKey:@"fields"];

                 id value = [element objectForKey:@"value"];
                 if (completion) {
                     completion(value);
                 }
             }
             failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                 NSLog(@"getSystemVariableKey error: %@",error);
                 if (completion) {
                     completion(nil);
                 }
             }];
    }
    @catch (NSException *exception) {
        NSLog(@"exception %@", exception);
    }
}

Then you would call this function like this:

YourObject *__weak weakSelf = self;
[YourObject getValue4Key:@"your_key" completion:^(id value){
    weakSelf.setMe = value;
}];

Now, if self gets destroyed, weakSelf will become nil so the callback will be, basically, a no-op.

This has the added advantage of not needing to pass ivar pointers by reference, which you will note, doesn't happen very often at all in the iOS frameworks ( NSError being the only exception I can think of off-hand).

p_variable is a parameter, which is a local variable of the function. Your block is run asynchronously at the end of some operation. By the time the block runs, it is long after the getValue4Key:andSet: has already returned. Therefore, nobody can make use of the p_variable variable even if you can set it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM