- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我读了这篇文章: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
。请注意 b1
和 b2
只共享一个 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/
我遵循了一本名为“Sitepoint Full Stack Javascript with MEAN”的书中的教程,我刚刚完成了第 6 章,应该已经创建了一个带有“数据库”的“服务器”。数据库只不过是
在 Jquery 中,我创建两个数组,一个嵌入另一个数组,就像这样...... arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arra
这个问题在这里已经有了答案: What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wa
我被放在别人的代码上,有一个类用作其他组件的基础。当我尝试 ng serve --aot(或 build --prod)时,我得到以下信息。 @Component({ ...,
我正在测试一些代码,并使用数据创建了一个 json 文件。 问题是我在警报中收到“[object Object],[object Object]”。没有数据。 我做错了什么? 这是代码:
我想打印 [object Object],[object Object] 以明智地 "[[{ 'x': '1', 'y': '0' }, { 'x': '2', 'y': '1' }]]"; 在 ja
我有一个功能 View ,我正在尝试以特殊格式的方式输出。但我无法让列表功能正常工作。 我得到的唯一返回是[object Object][object Object] [object Object]
在使用优秀的 Sim.js 和 Three.js 库处理 WebGL 项目时,我偶然发现了下一个问题: 一路走来,它使用了 THREE.Ray 的下一个构造函数: var ray = new THRE
我正在使用 Material UI 进行多重选择。这是我的代码。 {listStates.map(col => (
我的代码使用ajax: $("#keyword").keyup(function() { var keyword = $("#keyword").val(); if (keyword.
我遇到了下一个错误,无法理解如何解决它。 Can't resolve all parameters for AuthenticationService: ([object Object], ?, [o
我正在尝试创建一个显示动态复选框的表单,至少应选中其中一个才能继续。我还需要获取一组选中的复选框。 这是组件的代码: import { Component, OnInit } from '@angul
我正在开发 NodeJs 应用程序,它是博客应用程序。我使用了快速验证器,我尝试在 UI 端使用快速闪存消息将帖子保存在数据库中之前使用闪存消息验证数据,我成功地将数据保存在数据库中,但在提交表单后消
我知道有些人问了同样的问题并得到了解答。我已经查看了所有这些,但仍然无法解决我的问题。我有一个 jquery snipet,它将值发送到处理程序,处理程序处理来自 JS 的值并将数据作为 JSON 数
我继承了一个非常草率的项目,我的任务是解释为什么它不好。我注意到他们在整个代码中都进行了这样的比较 (IQueryable).FirstOrDefault(x => x.Facility == fac
我只是在删除数组中的对象时偶然发现了这一点。 代码如下: friends = []; friends.push( { a: 'Nexus', b: 'Muffi
这两个代码片段有什么区别: object = nil; [object release] 对比 [object release]; object = nil; 哪个是最佳实践? 最佳答案 object
我应该为其他人将从中继承的第一个父对象传递哪个参数,哪个参数更有效 Object.create(Object.prototype) Object.create(Object) Object.creat
我在不同的对象上安排不同的选择器 [self performSelector:@selector(doSmth) withObject:objectA afterDelay:1]; [self per
NSLog(@"%p", &object); 和 NSLog(@"%p", object); 有什么区别? 两者似乎都打印出一个内存地址,但我不确定哪个是对象的实际内存地址。 最佳答案 这就是我喜欢的
我是一名优秀的程序员,十分优秀!