我正在尝试从定义为类的一部分的 obj-c 块访问类 ivars。这里有什么不明白的?

发布于 2024-10-29 19:36:51 字数 689 浏览 0 评论 0原文

//class definition
@interface class1 : NSObject {
    NSMutableArray *array ;
    void (^test)() ;
}
@property( nonatomic,assign ) NSMutableArray *array  ;
@property( nonatomic,readonly ) void (^test)()  ;
@end

// implementation

@implementation class1

@synthesize array ;
@synthesize test ;

- (id)init
{
    self = [super init];
    a = [NSMutableArray arrayWithObjects:@"1",@"2", nil] ;
    test = ^ () {
        NSLog(@"length of array = %d",(int)[array count]);
    } ;
    return self;
}

// from main

    class1 *c = [[class1 alloc] init] ;

    c.test();

只要函数“c.test()”访问简单的ivars,即char、int等,c.test()就会干净地执行并返回。我尝试访问 obj-c 对象,但出现异常。 我缺少什么?

//class definition
@interface class1 : NSObject {
    NSMutableArray *array ;
    void (^test)() ;
}
@property( nonatomic,assign ) NSMutableArray *array  ;
@property( nonatomic,readonly ) void (^test)()  ;
@end

// implementation

@implementation class1

@synthesize array ;
@synthesize test ;

- (id)init
{
    self = [super init];
    a = [NSMutableArray arrayWithObjects:@"1",@"2", nil] ;
    test = ^ () {
        NSLog(@"length of array = %d",(int)[array count]);
    } ;
    return self;
}

// from main

    class1 *c = [[class1 alloc] init] ;

    c.test();

as long as the function "c.test()" accesses simple ivars, i.e. char, int, etc. c.test() executes and returns cleanly. i try to access an obj-c object, i get exceptions.
what am i missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等风来 2024-11-05 19:36:51

BJ是正确的,您需要遵循内存管理的规则,但是在这种情况下,答案与块有关。

当您的代码当前所示,array的普通属性将起作用,直到当前的Autorelease池排水管为止。如果您为这些“ class1”对象中的一个Alloc/Init,并立即尝试使用array属性,它将起作用(因为在对象的初始化和时间的时间之间不会排干autorelease池您尝试访问数组)。

但是,一旦将块放在那里,情况就不再如此。当您使用^{...}语法声明块时,该块将在呼叫堆栈的当前帧中分配。当您从INIT方法返回时,当前帧将弹出。 Ivar块仍然保留一个内存地址,但是该地址不再存在一个块。当堆栈框架被拆除时,它被破坏了。

避免这种情况的方法是将堆栈从堆栈中复制到堆上,然后使用 块:

test = [^{  NSLog(@"block!"); } copy];

BJ's correct that you need to follow the rules of memory management, but in this case, the answer does have to do with blocks.

As your code currently stands, the normal property of array will work until the current autorelease pool drains. If you alloc/init one of these "class1" objects and immediately attempt to use the array property, it will work (because no autorelease pool will have been drained between the initialization of the object and the time at which you attempt to access the array).

However, once you put the block in there, this is no longer the case. When you declare a block using the ^{ ... } syntax, this block is allocated in the current frame on the call stack. When you return from the init method, the current frame is popped. The block ivar still holds a memory address, but a block no longer exists at that address. It was destroyed when the stack frame was removed.

The way to avoid this is to copy the block off of the stack and onto the heap, and then use that block instead:

test = [^{  NSLog(@"block!"); } copy];
想挽留 2024-11-05 19:36:51

您没有在 init 方法中保留数组,也没有调用 setter 方法。对于块也是如此;如果您希望对象在当前方法的持续时间结束后继续存在,则需要通过调用 setter 方法或调用 retain (或 copy在块的情况下)。

您的错误与块无关,而与内存管理有关。请注意,如果您正在使用垃圾收集,您仍然需要调用 copy 来使块移动到堆中

You're not retaining the array in your init method, and you're not calling the setter method either. Likewise for the block; if you want your objects to stick around past the duration of the current method, you need to take ownership of them, either by calling your setter methods or calling retain (or copy in the case of the block).

Your error has nothing to do with blocks, and everything to do with memory management. Note that if you're using garbage collection, you still need to call copy to cause the block to be moved to the heap

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文