为什么当我在 .m 文件中设置 ^block 变量时,我收到一条错误消息说 Thread_1 EXC_BAD_ACCESS
Why when I set a ^block variable in .m file, I receive an error message saying Thread_1 EXC_BAD_ACCESS
我正在尝试实现发布在 Whosebug 上的这个答案
use block to pass data from modal view to parent view
当我尝试在我的 SecondViewController(模态视图)实现中将 vale 设置为阻塞时。我收到错误的内存访问错误。
我仍在学习 Objective C 并使用协议我可以做到这一点,但阻止似乎更有效。 谁能告诉我我在哪里犯了错误。这是我的 StoryBoard 的代码和图像。
FirstViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
@interface FirstViewController : UIViewController
@end
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
@interface FirstViewController ()
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
SecondViewController *second = [[SecondViewController alloc]init];
second.somethingHappenedInModalVC = ^(NSString *response) {
NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
};
}
@end
SecondViewController.h //模态视图
#import <UIKit/UIKit.h>
#import "FirstViewController.h"
@interface SecondViewController : UIViewController
@property (nonatomic, copy) void (^somethingHappenedInModalVC)(NSString *response);
@end
SecondViewController.m
#import "SecondViewController.h"
@interface SecondViewController ()
@property (strong, nonatomic) IBOutlet UITextField *textField;
@end
@implementation SecondViewController
- (IBAction)closeView:(id)sender {
self.somethingHappenedInModalVC(@"Sending the message"); //here memory warning display.
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
您有一个执行以下操作的 viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
SecondViewController *second = [[SecondViewController alloc]init];
second.somethingHappenedInModalVC = ^(NSString *response) {
NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
};
}
创建一个 SecondViewController
,设置 somethingHappenedInModalVC
属性,但随后让第二个视图控制器实例超出范围,因此将被释放(从而丢弃该块属性 还有)。
因此,当您最终转换到 SecondViewController
(此时此视图控制器的另一个实例被实例化)时,此新实例的 somethingHappenedInModalVC
是 nil
,因此尝试调用该块将会崩溃。
您通常在 prepareForSegue
中在此目标控制器中设置属性(或者如果您手动实例化 SecondViewController
,请在此处手动设置)。您还没有向我们展示您是如何过渡到第二个视图控制器的,因此我们无法告诉您示例中哪种方式是正确的。
例如,您的第一个视图控制器中可能有一个 prepareForSegue
,当您对 SecondViewController
:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"IdForSegue"]) {
SecondViewController *destination = segue.destinationViewController;
destination.somethingHappenedInModalVC = ^(NSString *response) {
NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
};
}
}
请注意,这假设您已经向执行到第二个视图控制器的转换的 segue 提供了故事板 ID。确保代码片段中的标识符与您为故事板中的 segue 提供的故事板 ID 匹配。
问题是,您正在创建 SecondViewController
的新实例并将块设置为新创建的实例,而不是当前(将要)显示的实际实例。因此,在您的实际 SecondViewController
对象中,该块将仍然是 nil
,这就是它崩溃的原因。
在处理块时,你应该总是在调用它之前进行 nil
检查:
if (somethingHappenedInModalVC)
{
somethingHappenedInModalVC(@"Sending the message");
}
并且为了解决逻辑问题,您应该使用 SecondViewController
的实际实例,而不是在 viewDidLoad
.