gpt4 book ai didi

ios - Objective-C:存储在集合中的 block 的初始化

转载 作者:行者123 更新时间:2023-11-28 23:28:37 26 4
gpt4 key购买 nike

我读了这篇文章:Storing Blocks in an Array并想澄清一些时刻。

考虑下一个代码:

NSMutableArray* storage1;
NSMutableArray* storage2;
-(id)init{
self=[super init];
if(self){
storage1=[NSMutableArray new];
storage2=[NSMutableArray new];
}
return self;
}
-(void) f1{
__block int x=1;

dispatch_block_t b0=^{
i++;
i++;
sleep_indefinitely
};
[storage1 addObject:b0];
dispatch_async(global_concurrent_thread,b0());
[storage2 addObject:[storage1 objectAtIndex:0]];
}

问题是:storage2 是否会包含 更新 值为 i 的 block ?如果我想拥有 2 个独立的实例,是否有必要在将其存储在集合中之前复制 block ?如果是,那么在复制过程中如何初始化带有 __block 说明符的变量?

最佳答案

您的问题的答案在于理解生命周期 - 在程序中创建的每个变量和对象都有一个生命周期,它决定了变量或对象的存活时间。 __block 属性修改了它所应用的变量的生命周期,可能会增加它。

关于血淋淋的细节(会有变量和对象的死尸乱扔答案;-))从一个简单函数中声明的变量开始:

int answer1(void)
{
int x = 21; // variable x is created with a fixed lifetime of the end of the function
// invocation – each function invocation creates a new distinct variable x
return x * 2;
// end of the function, x dies
}

调用 answer1() 返回 42。在该调用期间,一个变量被创建和销毁,调用后它不再存在。每次调用 answer1() 都会创建一个新的不同变量,然后在调用返回时将其销毁。

标准局部变量的生命周期与创建它们的函数、方法或 block 语句有关。

动态创建的对象的生命周期不受创建它们的函数/方法/ block 语句的限制,只要存在对它们的强引用就一直存在。

int answer2(void)
{
NSMutableArray *x = [NSMutableArray new]; // variable x is created with a fixed lifetime
// of the end of the function
// an NSMutableArray object is created with an
// indeterminate lifetime – it will live as long
// as there exists a strong refernece to it
// a strong reference to this object is stored in x
[x addObject:@21];
return [x[0] intValue] * 2;
// end of the function, x dies
// as x contained the only strong reference to the array object
// so that object is now longer wanted and can now be culled
// – its lifetime is now over as well
}

调用 answer2() 也会返回 42。重要提示:调用期间创建的数组对象已死亡,不是因为调用已返回,变量 x 死亡的原因,而是因为不再有任何强引用存储在任何地方 - 不需要它被剔除。

现在让我们看看 block 。创建时, block 对象包含它引用的任何局部变量中的值的副本:

typedef int (^IntBlock)(void);   // for convenience

int answer3(void)
{
int x = 20; // variable x is created with a fixed lifetime of the end of the function

IntBlock b1 = ^{ return x; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in x,
// i.e. 20

x += 2;

IntBlock b2 = ^{ return x; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in x,
// i.e. 22

return b1() + b2();
// end of function
// x, b1 and b2 all die
// as b1 & b2 contained the only strong references to the two block objects
// they can now be culled – their lifetimes are over
}

answer3() 的调用返回 42(多么令人惊讶 ;-))。在调用 answer3() 期间,创建了两个不同的 block ,尽管代码主体相同,但它们包含 不同 x 的值。

最后我们来到 __block,局部变量的生命周期增强属性,任何在出生时被赋予此属性的局部变量都不会在其创建函数/方法/ block 结束时被委托(delegate)死亡声明:

typedef void (^VoidBlock)(void);

IntBlock answer4(void)
{
__block int x = 42; // variable x is created with a lifetime the longer of:
// * the lifetime of the current invocation of answer4()
// * the lifetime of the longest living block which
// uses x

VoidBlock b1 = ^{ x = x / 2; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a reference to the *variable* in x

IntBlock b2 = ^{ return x * 2; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a reference to the *variable* in x
b1(); // call b1(), alters the value in x
return b2; // return a reference to the second block
// end of function
// b1 dies
// as b1 contained the only strong reference to the first block it can now be culled
// b2 also dies
// however a reference to the block it referenced is returned by the function, so
// that block lives
// the returned block references x so it to lives
}

void test4(void)
{
IntBlock b1 = answer4(); // a reference to a block is returned by answer4() and stored in b1
NSLog(@"The answer is %d", b1()); // outputs 42
// end of function
// b1 dies
// as b1 contained the onlyt surviving reference to the block returned by answer4()
// that block may now be culled
// as that block contains the only surviving reference to the variable x
// that variable may now be culled
}

调用 test4() 输出 The answer is 42。请注意 b1b2 只共享一个 x

进一步注意局部变量 x 的生命周期如何延长到调用 answer4() 之后,因为它被返回的 block 对象捕获。然而,一旦 block 对象的时间到了,x 就会被剔除——就像一个对象,它的生命周期取决于对它感兴趣的东西。

x 的生命周期条件与对象的生命周期条件非常相似,这是否是巧合?不,下一个示例是有效(即精确细节会有所不同,可见行为是相同的)编译器如何处理 answer4():

@interface LifetimeExtenderObject5 : NSObject
@property int x;
@end
@implementation LifetimeExtenderObject5
@end

IntBlock answer5(void)
{
LifetimeExtenderObject5 *leo = [LifetimeExtenderObject5 new]; // variable leo is created with a lifetime of
// the end of the function
// a LifetimeExtenderObject5 is created with
// an indeterminate lifetime and a reference
// to it stored in leo
leo.x = 42;

VoidBlock b1 = ^{ leo.x = leo.x / 2; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in leo
// this value is a strong reference to the created
// LifetimeExtenderObject5, so now there are two strong
// references to that object

IntBlock b2 = ^{ return leo.x * 2; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in leo
// this value is a strong reference to the created
// LifetimeExtenderObject5, so now there are three strong
// references to that object
b1(); // call b1(), alters the value in x
return b2; // return a reference to the second block
// end of function
// leo dies, but the LifetimeExtenderObject5 object it references has other strong
// references so it lives
// b1 dies
// as b1 contained the only strong reference to the first block it can now be culled
// that block contained a string reference to created LifetimeExtenderObject5 object,
// but there are still remaining strong references to that object so it lives
// b2 also dies
// however a reference to the block it referenced is returned by the function, so
// that block lives
// that block contains a strong reference, the last one, to the created
// LifetimeExtenderObject5 object, so it still lives.
}

void test5(void)
{
IntBlock b1 = answer5(); // a reference to a block is returned by answer5() and stored in b1
NSLog(@"The answer is %d", b1()); // outputs 42
// end of function
// b1 dies
// as b1 contained the only surviving reference to the block returned by answer5()
// that block may now be culled
// as that block contains the only surviving reference to the created
// LifetimeExtenderObject5 object that object may now be culled
}

你问:

Is it necessary to copy block before storing it in collection if I want to have 2 independent instances?

上面的内容希望告诉您,复制不会为您提供捕获的 __block 变量的两个独立实例。为此,您需要 distinct __block 变量来捕获,您可以从声明它们的函数的不同调用中获得这些变量。每次调用 answer4() 上面返回一个 block ,该 block 捕获了 __block 属性变量 x 的不同/“独立实例”。

HTH 不仅仅是令人困惑!

关于ios - Objective-C:存储在集合中的 block 的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57643577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com