简体   繁体   English

使用块时的iPhone EXC_BAD_ACCESS

[英]iPhone EXC_BAD_ACCESS when using blocks

Im trying to create a simple callback using blocks. 我试图使用块创建一个简单的回调。 I have a MainViewController which addSubView another DatePickerViewController.view i created a block like this 我有一个MainViewController addSubView另一个DatePickerViewController.view我创建了一个像这样的块

typedef void(^DateChangedBlock)(NSDate*);

And i have a method on my DatePickerViewController called 我在我的DatePickerViewController上调用了一个方法

setOnDateChangedCallback:(DateChangedBlock)callback

I store the callback in a property of the DatePickerViewController. 我将回调存储在DatePickerViewController的属性中。 The DatePickerViewController's view is a UIDatePicker instance, ive bound an IBAction to the value changed to a method that does this. DatePickerViewController的视图是一个UIDatePicker实例,我已将IBAction绑定到更改为执行此操作的方法的值。

- (IBAction)dateChanged:(id)sender {

    if (dateChangedCallback != nil)
    {
        dateChangedCallback(nil);
    }
}

Here is how i register the block in the MainViewController 以下是我在MainViewController中注册块的方法

DatePickerViewController *dateController = [[DatePickerViewController alloc] initWithNibName:@"DatePickerView" bundle:nil];

self.datePicker = dateController;
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 100, 200)];
[self.view addSubview:textView];
DateChangedBlock myBlock = ^(NSDate *newDate) {
 textView.text = @"testing";
};

[self.datePicker setOnDateChanged: myBlock];
[self.datePicker dateChanged:self]; // force trigger (this works).

When i force trigger the dateChanged method on the DatePickerViewController it works no problem. 当我强制触发DatePickerViewController上的dateChanged方法时,它没有问题。 But when the datepicker itself triggers the method thru the IBAction i get a EXC_BAD_ACCESS error. 但是当datepicker本身通过IBAction触发方法时,我得到一个EXC_BAD_ACCESS错误。 The error occurs in this method on the "int retVal" line. 此方法在“int retVal”行上发生错误。

#import <UIKit/UIKit.h>

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil); // THREAD 1: program received EXC_BAD_ACCCESS.**
    [pool release];
    return retVal;
}

What am i doing wrong? 我究竟做错了什么?

You should copy your block when passing it to other method (such as attribute setter in your situation). 您应该在将块传递给其他方法时复制块(例如在您的情况下使用属性设置器)。 So when setting the callback block do this: 因此,在设置回调块时,请执行以下操作:

[self.datePicker setOnDateChanged:[[myBlock copy] autorelease]];

You get the EXC_BAD_ACCESS cause block's variables used when creating the block don't get retained by the block itself. 您在创建块时使用的EXC_BAD_ACCESS原因块变量不会被块本身保留。 So when calling the block - variables do not exist anymore. 因此,当调用块时 - 变量不再存在。

The accepted answer is wrong. 接受的答案是错误的。 You don't need to copy it in your MainViewController . 您无需在MainViewController复制它。 Rather, the setOnDateChangedCallback: method which takes a block argument is responsible for copying it if it needs to store it in an instance variable (which I see it is doing, in the variable dateChangedCallback that is later used by another method). 相反,带有块参数的setOnDateChangedCallback:方法负责复制它,如果它需要将它存储在一个实例变量中(我看到它正在做,在后来被另一个方法使用的变量dateChangedCallback中)。 If dateChangedCallback is a synthesized property, you can accomplish this by declaring the property as copy instead of retain . 如果dateChangedCallback是合成属性,则可以通过将属性声明为copy而不是retain来完成此操作。

You can only update the UI from the UI thread. 您只能从UI线程更新UI。 Since your block is running on another thread, you're getting the exception when updating the text of the textView . 由于您的块在另一个线程上运行,因此在更新textView的文本时会出现异常。 You can run code on the UI thread from within a block by using the main queue ( dispatch_get_main_queue() ). 您可以使用主队列( dispatch_get_main_queue() )在块中运行UI线程上的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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