- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读 Big Nerd Ranch iOS 教科书第 19 章,我不清楚他们为什么要在那里重新分配指针以避免强引用循环。基本上他们有一个代码块,actionBlock
,它对类 BNRItemCell
有一个强引用,并且引用在 block 的生命周期之后仍然存在。 BNRItemCell
通过 @property
引用 block :@property (strong, nonatomic) void (^actionBlock)(void)
。显然,这会产生强大的引用循环。为了避免这种情况,他们在 block 外定义了一个 __weak BNRItemCell *weakCell = cell
,然后在 block 内定义了一个 BNRItemCell *strongCell = weakCell
。他们说 strongCell
应该在 block 执行时持续存在,并且在 block 完成时将被销毁。我不明白 block 内的重新分配,BNRItemCell *strongCell = weakCell
,以及指针为 __weak
的意义何在。比方说,如果我们只执行 BNRItemCell *strongCell = cell
,其中 cell
是对类的强引用,难道不是可以吗? strongCell
在 block 执行完毕后仍会被销毁。
我试图想象正在发生的事情,而他们正在做的事情对我来说没有意义。为了清楚起见,
__weak someClass *weakPointer = strongPointer_1;
someObject.actionBlock = ^{
someClass *strongPointer_2 = weakPoiter;
// Here we are using strongPointer_2
}
和
someObject.actionBlock = ^{
someClass *strongPointer_2 = strongPointer_1;
// Here we are using strongPointer_2
}
?
我就是看不出区别,所以我想,我对幕后发生的事情没有清楚的了解。
完整代码如下:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get a new or recycled cell
BNRItemCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"BNRItemCell"
forIndexPath:indexPath];
// Set the text on the cell with the description of the item
// that is the nth index of items, where n = row this cell
// will appear in on the tableview
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *item = items[indexPath.row];
// Configure the cell with the BNRItem
cell.nameLabel.text = item.itemName;
cell.serialNumberLabel.text = item.serialNumber;
cell.valueLabel.text = [NSString stringWithFormat:@"$%d", item.valueInDollars];
cell.thumbnailView.image = item.thumbnail;
__weak BNRItemCell *weakCell = cell;
cell.actionBlock = ^{
NSLog(@"Going to show image for %@", item);
BNRItemCell *strongCell = weakCell;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
NSString *itemKey = item.itemKey;
// if there is no image, we don't need to display anything
UIImage *img = [[BNRImageStore sharedStore] imageForKey:itemKey];
if (!img) {
return;
}
BNRImageViewController *ivc = [[BNRImageViewController alloc] init];
ivc.image = img;
ivc.modalPresentationStyle = UIModalPresentationPopover;
ivc.preferredContentSize = CGSizeMake(380, 300);
CGRect frame = [self.view convertRect:strongCell.thumbnailView.bounds
toView:self.view];
// frame.origin.y -= 150;
UIPopoverPresentationController *popoverController = ivc.popoverPresentationController;
popoverController.permittedArrowDirections = UIPopoverArrowDirectionUp;
popoverController.sourceView = cell.thumbnailView;
popoverController.sourceRect = frame;
[self.navigationController presentViewController:ivc animated:YES completion:nil];
}
};
return cell;
}
最佳答案
重要的是要理解为什么捕获 self
或 block 中的其他一些引用的“正常”情况会导致保留周期。
如果您有一个实例变量持有对 block 的强引用,则该 block 将不会被释放,直到该引用被nil
ed。如果该 block 捕获对引用该 block 的实例的强引用,则该实例将不会被解除分配
,直到该引用被nil
ed。如果实例和 block 同时持有这些引用,那么您就有了经典循环,除非其中一个明确地nil
引用了另一个。
这里的关键是 block 对类实例的引用保存在捕获数据中。只要区 block 存在,这些数据就会一直存在。
现在我们可以明白为什么捕获弱指针会有帮助了。如果问题是捕获数据,而不是 block 本身中的引用,则弱指针会很好地处理我们的循环。现在可以独立于 block 解除分配
类实例,因为 block 没有强引用。
现在的问题是,为什么在 block 本身的主体中有一个强引用?这只是为了确保在 block 执行时实例不会被dealloc
ed。对于所有在主线程上运行的东西来说,这不是一个真正的问题,但该 block 可能正在分派(dispatch)到后台线程。
为什么这(重新)创建一个保留周期?嗯,确实如此,但只是暂时的。 block 内的强引用捕获弱指针,可以将其nil
。强引用是一个 block 范围的变量,当 block 退出时将被清除。 ARC 确保此类引用在从 block 返回之前被释放
,从而停止循环。
关于ios - Big Nerd Ranch,第 19 章,通过重新分配指针避免强引用循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33793374/
这个问题在这里已经有了答案: How does Scala's apply() method magic work? (3 个回答) 9年前关闭。 假设我在 scala 中有一个 MyList 类,其
这个问题在这里已经有了答案: What is a non-capturing group in regular expressions? (18 个回答) Reference - What does
这个问题是针对嵌入式系统的! 我有以下选项来初始化一个对象: Object* o = new Object(arg); 这会将对象放入堆中并返回指向它的指针。我不喜欢在嵌入式软件中使用动态分配。 Ob
我自己搜索过,没能成功的正则表达式。 我有一个 html 文件,其中包含 [] 之间的变量我想把每一个字都写进去。 [client_name][client_company] [cl
我是 Python 新手。我不明白为什么这段代码不起作用: reOptions = re.search( "[\s+@twitter\s+(?P\w+):(?P.*?)\s+]", d
在过去 7 个月左右的时间里,我几乎一直在使用 .NET C# 进行编程。在那之前,我的大部分编程都是用 C++(从学校里学的)。在工作中,我可能需要在接下来的几个月里做一大堆 C 语言。我对 C 的
我是 RE 的新手,我正在尝试获取歌词并分离出歌词标题、和声和主唱: 下面是一些歌词的例子: [Intro] D.A. got that dope! [Chorus: Travis Scott] Ic
这可能是不可能的,但我想检查是否可以用一种简单的方式表达这样的事情: // obviously doesn't work class Foo : IFoo where T: Bar {
我们的应用程序中有“user”和“study”实体,存储在它们各自的表中。一项研究代表一种研究和已收集的数据。它们是多对多的关系,所以我们需要一个链接表:studies_users。 我们为用户分配角
将测试条件添加到 Visual Studio 2010 数据库单元测试(对于 SQL Server 2008)时,这些条件称为例如rowCountCondition1、rowCountConditio
在模拟器上,我可以从设置中卸载 SD 卡。 然后我可以将它安装到我的操作系统上,然后正常卸载它。 我一直无法弄清楚如何在模拟器上重新安装它(无需重新启动)。 提示: adb 命令 remount 是无
假设在一个分支上执行了一系列提交,但该分支尚未与主干重新同步。是否可以从提交中生成全局补丁?是否可以从一系列提交中生成“分组”补丁?如果是,如何? 最佳答案 svn diff -rXXX:YYY UR
在某些情况下,我想在我的应用程序中锁定调整大小功能,为此我尝试对属性进行数据绑定(bind),并且不允许在某些情况下更改它,但没有成功。 有没有办法这样做? 这是我不成功的尝试: XAML: Vie
当我的计算机连接多个显示器时,我可以检测它们,并根据从获取的值设置位置来向它们绘制图形 get(0, 'MonitorPositions') 但是,当我在 MATLAB 运行时断开监视器时,此属性不会
我们有一个grails应用程序,该应用程序在grails数据库中存储了各种域对象。该应用程序连接到第二个数据库,运行一些原始sql,并在表中显示结果。它基本上是一个报告服务器。 我们通过在DataSo
无法比较来自不同容器的迭代器(参见这里的示例: https://stackoverflow.com/a/4664519/225186 )(或者从技术上讲,它不需要有意义。) 这就提出了另一个问题,来自
我有以下情况: 家长 Activity : ParentActivityClass { private Intent intent; @Override public void onCreate(Bu
我经常将元素与附加功能 Hook ,例如: $('.myfav').autocomplete(); $('.myfav').datepicker(); $('.myfav').click(somefu
因此,我将 tooltipster.js 库用于工具提示,并尝试更改工具提示在不同屏幕尺寸上的默认距离。 所以这是默认的 init 的样子: $(inputTooltipTrigger).tool
我在 ARM7 嵌入式环境中工作。我使用的编译器不支持完整的 C++ 功能。它不支持的一项功能是动态类型转换。 有没有办法实现dynamic_cast<>() ? 我使用 Google 寻找代码,但到
我是一名优秀的程序员,十分优秀!