【问题标题】:Obj-C: __block variablesObj-C:__block 变量
【发布时间】:2012-02-11 07:07:14
【问题描述】:

是否可以为局部变量分配一个范围在块之外的值并让它保留其值?特别是,我正在为 iOS 编码,并且我在另一个块内有一个嵌套块,我想在块内为 NSString 分配一个值,然后(在块外)使用它。当我在块后引用 NSString 时,我尝试使用 __block nut,我得到一个错误的访问错误。我正在使用 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

也感谢大家的帮助

【问题讨论】:

    标签: iphone objective-c ios ipad ios5


    【解决方案1】:

    你只是定义了那个块,而不是执行它。调用someBlock(valueForParam1); 来执行你的块。否则你的str 指针指向一些垃圾,调用getCharAtIndex: 会使你的应用程序崩溃。

    【讨论】:

    • str 实际上不会指向垃圾,它会指向 nil,因为 ARC 会将对象指针清零。
    • 你是对的。我忽略了启用 ARC 的事实。
    【解决方案2】:

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

    其次,如果你不使用 ARC,__block 变量不会被块对象自动保留。这意味着如果您不保留它,那么当您访问 str 时,str 可能是一个已释放的对象并导致您的应用程序崩溃。

    【讨论】:

      【解决方案3】:

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

      试试这个:)

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多