Obj-C:__block变量

时间:2012-01-16 10:03:28

标签: iphone objective-c ios ipad ios5

是否可以为局部变量分配一个范围在块之外且保留其值的值?特别是,我正在为iOS编码,我在另一个块中有一个嵌套块,我想在块内为一个NSString赋值一个值,然后(在块外)使用它。我尝试使用__block坚果,当我在块之后引用NSString时出现错误的访问错误。我使用ARC是重要的。例如:

__block NSString *str;

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

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

我在做某些概念错误或不允许的事情或者什么?非常感谢帮助。

编辑:

这是实际的代码,基本上代码获取作为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 个答案:

答案 0 :(得分:3)

您只是定义该块,但不执行它。致电someBlock(valueForParam1);来执行你的阻止。否则,您的str指针指向某些垃圾,并且调用getCharAtIndex:会导致您的应用崩溃。

答案 1 :(得分:1)

首先,str仅在块执行后才会更新。因此,除非您在该行使用dispatch_sync,否则此行:[str getCharAtIndex:1];该块不太可能被执行,str将不会更新。

其次,如果您不使用ARC,则_block变量不会被块对象自动保留。这意味着如果您没有保留它,那么当您访问str时,str可能会被解除分配,并导致您的应用崩溃。

答案 2 :(得分:1)

你只是定义你的块而不是调用它。

试试这个:)

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

在这种情况下,我直接调用它,但通常块本身是某个方法或函数的参数。