[英]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.