2012-01-16 2 views
2

Можно ли присвоить локальную переменную значение, объем которого находится вне блока и сохранить его значение? В частности, я кодирую iOS, и у меня есть вложенный блок внутри других блоков, и я хочу назначить NSString значение внутри блока, а затем (за пределами блоков) использовать его. Я пробовал использовать гайку __block, когда я обращаюсь к NSString после того, как блоки получают ошибку плохого доступа. Я использую ARC, это важно. Например:Obj-C: переменные __block

__block NSString *str; 

someBlock ^(id param1) 
{ 
    str = @"iPhone"; 
} 

[str getCharAtIndex:1]; //or w/e 

Я делаю что-то концептуально неправильно или это не разрешено или что? Помощь очень ценится.

Edit:

вот фактический код, в основном код получает чирикать как объект JSON, то все, что я Тринг делать это отображение текста. в коде я не извлеченный текст из JSON, я пытался сделать доказательство концепции

- (IBAction)getTweet:(id)sender 
{ 
    __block NSString *displayStr; 

    //account instance 
    ACAccountStore *store = [[ACAccountStore alloc] init]; 
    ACAccountType *twitterAcountType = 
       [store accountTypeWithAccountTypeIdentifier: ACAccountTypeIdentifierTwitter]; 

    //request access 
    [store requestAccessToAccountsWithType: twitterAcountType withCompletionHandler: 
    ^(BOOL granted, NSError *error) 
    { 
     if (!granted) { 
      //display error on textView 
     } 
     else 
     { 
      //get available accounts 
      NSArray *twitterAccounts = [store accountsWithAccountType: twitterAcountType]; 

      if([twitterAccounts count] > 0) 
      { 
       //get first account 
       ACAccount *account = [twitterAccounts objectAtIndex: 0]; 

       ////make authenticated request to twitter 
       //set-up params 
       NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 
       [params setObject:@"1" forKey:@"include_entities"]; 
       [params setObject:@"1" forKey:@"count"]; 

       //which REST thing to call 
       NSURL *url = 
       [NSURL URLWithString:@"http://api.twitter.com/1/statuses/home_timeline.json"]; 

       //create request 
       TWRequest *request = 
       [[TWRequest alloc] 
         initWithURL:url parameters:params requestMethod:TWRequestMethodGET]; 

       //attach account info 
       [request setAccount: account]; 
       [request performRequestWithHandler: 
        ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) 
        { 
        if(error != nil) 
        { 
         //display error 
        } 
        else 
        { 
         NSError *jsonError; 
         NSArray *timeline = 
          [NSJSONSerialization 
            JSONObjectWithData: responseData 
            options: NSJSONReadingMutableLeaves 
            error: &jsonError]; 

         if (jsonError == nil) 
         { 
          /////////////////////////// 
          ///heres the src of error// 
          /////////////////////////// 
          //display data 
          NSLog(@"array: %@", timeline); 
          displayStr = @"whats the deal with this"; 

     //i tried this but i think ARC takes care of this 
          [displayStr retain]; 
         } 
         else 
         { 
          //display error 
         } 
        } 

        }];//end block de request 
      } 
      else 
      { 
       //display error 
      } 
     } 
    }];//end block de store 

    ///////then heres where i get the bad access error 
    [self.lastTweetText setText:displayStr]; 


}//end getTweet 

также благодарит за помощь, ребята

ответ

1

Во-первых, str будет обновляться только после выполнения блока. Поэтому, если вы не используете dispatch_sync для этого блока, иначе в этой строке: [str getCharAtIndex:1]; блок вряд ли будет выполнен, а str не будет обновляться.

Во-вторых, переменная __block не будет автоматически сохранена блочным объектом, если вы не используете ARC. Это означает, что если вы не сохраните его, то к тому времени, как вы получите доступ к str, str может быть освобожденным объектом и свернуть приложение.

3

Вы просто определение этого блока, но не выполняя его. вызовите someBlock(valueForParam1);, чтобы выполнить свой блок. В противном случае ваш указатель str указывает на какой-то мусор и вызывается getCharAtIndex: сбой вашего приложения.

+0

'str' на самом деле не укажет на мусор, он будет указывать на ноль, поскольку ARC нули указатели объектов. – hypercrypt

+0

Вы правы. Я упустил из виду тот факт, что с поддержкой ARC. – V1ru8

1

Вы просто определяете свой блок, но не называете его.

Попробуйте это :)

__block NSString *str; 
void (^someBlock)(id) = ^(id param1) 
{ 
    str = @"iPhone"; 
}; 
someBlock(nil); 
[str getCharAtIndex:1]; 

В этом случае я называю это непосредственно, но, как правило, сам блок является параметром некоторого метода или функции.