Obj-C: __block переменные - PullRequest
       3

Obj-C: __block переменные

2 голосов
/ 16 января 2012

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

__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

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

Ответы [ 3 ]

3 голосов
/ 16 января 2012

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

1 голос
/ 16 января 2012

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

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

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

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

1 голос
/ 16 января 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...