【问题标题】:Why when I set a ^block variable in .m file, I receive an error message saying Thread_1 EXC_BAD_ACCESS为什么当我在 .m 文件中设置 ^block 变量时,我收到一条错误消息,说 Thread_1 EXC_BAD_ACCESS
【发布时间】:2016-02-08 01:21:25
【问题描述】:

我正在尝试实现发布在 StackOverflow 上的这个答案

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

【问题讨论】:

    标签: ios objective-c xcode objective-c-blocks


    【解决方案1】:

    您有一个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(此时此视图控制器的另一个实例被实例化)时,此新实例的somethingHappenedInModalVCnil,因此尝试调用该块将崩溃.

    您通常在prepareForSegue 中设置此目标控制器的属性(或者如果您手动实例化SecondViewController,则在此处手动设置)。您还没有向我们展示您是如何过渡到第二个视图控制器的,因此我们无法告诉您在您的示例中哪种方式是正确的。

    例如,您的第一个视图控制器中可能有一个prepareForSegue,当您执行对SecondViewController 的segue 时会自动调用它:

    - (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);
            };
        }
    }
    

    请注意,这假设您已将情节提要 ID 提供给执行到第二个视图控制器的转换的 segue。确保代码 sn-p 中的标识符与您在故事板中提供给 segue 的故事板 ID 匹配。

    【讨论】:

    • 因为我在 SecondViewController (模态视图)中声明了块。在那里,我使用 IBAction 将其解散,将在视图被解散之前调用该类的 prepareForSegue。我应该实现哪个视图控制器(来自上述两个)segue 方法来传递这个块变量以及如何传递。
    • prepareForSegue 在第一个视图控制器中实现,并在第一个视图控制器与第二个视图控制器连接时调用。因此,当您从第一个切换到第二个时,我们设置了 block 属性,因此该属性将在第二个视图控制器的 IBAction 被调用时可用。当然,这假设您为 segue 正确设置了故事板 ID。
    【解决方案2】:

    问题是,您正在创建SecondViewController 的新实例并将块设置为新创建的实例,而不是当前(将要)显示的实际实例。因此,在您实际的 SecondViewController 对象中,该块仍将是 nil,这就是它崩溃的原因。

    在处理块时,您应该始终在调用它之前进行nil 检查:

    if (somethingHappenedInModalVC)
    {
       somethingHappenedInModalVC(@"Sending the message");
    }
    

    为了解决逻辑问题,您应该使用SecondViewController 的实际实例,而不是在viewDidLoad 中创建新实例。

    【讨论】:

      猜你喜欢
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      相关资源
      最近更新 更多