iOS(Objective-C)。从数组中获取块时应用程序崩溃

iOS(Objective-C). Application crash when getting block from array

对 objective-c 中的块有疑问。 例如,我有一个动作列表。 我正在初始化一个块数组:

self.actions =  @[
                   ^() { [self showObject:self.object_1]; },
                   ^() { [self showObject:self.object_2]; },
                   ^() { [self showObject:self.object_3]; }
];

并在按下某行时调用它们:

- (void)pressedRowAtIndex:(NSInteger)index {
    if (index < actions.count) {
        void (^action)() = [actions objectAtIndex:index];
        if (action != nil) {
            action();
        }
    }
}

一切正常,没有问题。但是当我使用 initWithObjects 方法初始化我的动作数组时:

self.actions =  [NSArray alloc] initWithObjects:
                   ^() { [self showObject:self.object_1]; },
                   ^() { [self showObject:self.object_2]; },
                   ^() { [self showObject:self.object_3]; },
                       nil
    ];

然后我在尝试使用 NSArray class 的 objectAtIndex 方法按索引执行操作时崩溃了 class。

我理解这个 inits 之间的区别。第一个不像第一个那样增加引用计数。但是有人可以解释为什么它会崩溃吗?

编辑:

我发现的一切。也许我很笨,其他地方是另一个有用的信息。

终端中没有崩溃信息:

Onik IV 代码:

小例子:

@interface ViewController () {
    NSArray *actions;
}

@property (nonatomic, strong) NSString *object1;
@property (nonatomic, strong) NSString *object2;
@property (nonatomic, strong) NSString *object3;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.


    actions =  [[NSArray alloc] initWithObjects:
                ^() { [self showObject:self.object1];},
                ^() { [self showObject:self.object2]; },
                ^() {[self showObject:self.object3]; },
                nil];



}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    self.object1 = @"object 1";
    self.object2 = @"object 2";
    self.object3 = @"object 3";

    void(^firsSimpleBlock)(void) = [actions lastObject];

    firsSimpleBlock();

    void(^simpleBlock)(void) = [actions firstObject];


    simpleBlock();
}

-(void)showObject:(NSString *)object
{
    NSLog(@"Show: %@",object);
}

@end

也是一样,你一定是有别的问题(sintax?)。

试试这个:

@interface ViewController ()

@property (nonatomic, strong) NSString *object1;
@property (nonatomic, strong) NSString *object2;
@property (nonatomic, strong) NSString *object3;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.object1 = @"object 1";
self.object2 = @"object 2";
self.object3 = @"object 3";


NSArray *actions =  @[^() { [self showObject:self.object1];},
                            ^() { [self showObject:self.object2]; },
                            ^() {[self showObject:self.object3]; }
                            ];

NSArray *secondActions = [[NSArray alloc] initWithObjects:
^() { [self showObject:self.object1];},
^() { [self showObject:self.object2]; },
^() { [self showObject:self.object3];},
nil
];

void(^firsSimpleBlock)(void) = [actions lastObject];

firsSimpleBlock();

void(^simpleBlock)(void) = [secondActions firstObject];


simpleBlock();


}

-(void)showObject:(NSString *)object
{
NSLog(@"Show: %@",object);
}

@end

尝试这样的事情。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    (^someBlock)(void) = ^void(void){
        self.object1; 
    };
    actions =  [[NSArray alloc] initWithObjects:
                [someBlock copy],
                [someOtherBlock copy],
                [anotherBlock copy],
                nil];



}

块分配在堆栈上,因此当从堆栈中删除帧时,块将被删除,导致指向该块的所有指针的 sail 指针。当您分配带有文字“@”符号的 object 时,object 分配在池中,因此 "same" 的所有文字都指向同一实例并且永远不会被释放。

NSString *a = @"A";
NSString *b = @"A";

指向同一个字符串实例,而:

NSString *a = [NSString stringWithFormat:@"A"];
NSString *b = [NSString stringWithFormat:@"A"];

是两个不同的object。

因此它在您创建文字数组时有效,但是当您动态添加块时,它们将在需要使用它们时被删除,因此 BAD_ACCESS。解决方案是发送 "copy" 消息到块,该块将把它复制到堆中,块不会被释放。