gpt4 book ai didi

ios - RAC 和单元重用 : putting deliverOn: in the right place?

转载 作者:搜寻专家 更新时间:2023-10-30 20:16:59 25 4
gpt4 key购买 nike

我在玩 RAC,尤其是 Colin Eberhardt 的 Twitter 搜索 example ,并遇到了我无法向自己解释的崩溃。

这是一个sample project我创建是为了说明问题并以此为基础提出问题。

该应用使用带有可重用单元格的 UITableView;每个单元格上都有一个 UIImageView,它的图像是通过某个 URL 下载的。
还定义了一个用于在后台队列上下载图像的信号:

- (RACSignal *)signalForLoadingImage:(NSString *)imageURLString
{
RACScheduler *scheduler = [RACScheduler
schedulerWithPriority:RACSchedulerPriorityBackground];

return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURLString]];
UIImage *image = [UIImage imageWithData:data];
[subscriber sendNext:image];
[subscriber sendCompleted];
return nil;
}] subscribeOn:scheduler];
}

cellForRowAtIndexPath: 中,我使用 RAC 宏将加载信号绑定(bind)到 ImageView 的 image 属性:

RAC(cell.kittenImageView, image) =
[[[self signalForLoadingImage:self.imageURLs[indexPath.row]]
takeUntil:cell.rac_prepareForReuseSignal] // Crashes on multiple binding assertion!
deliverOn:[RACScheduler mainThreadScheduler]]; // Swap these two lines to 'fix'

现在,当我运行应用程序并开始上下滚动 TableView 时,应用程序崩溃并显示断言消息:

Signal <RACDynamicSignal: 0x7f9110485470> name:  is already bound to key path "image" on object <UIImageView: <...>>, adding signal <RACDynamicSignal: 0x7f9110454510> name:  is undefined behavior

但是,如果我先将图像加载信号包装到 deliverOn: 中,然后再包装到 takeUntil: 中,单元重用将正常工作很好:

RAC(cell.kittenImageView, image) =
[[[self signalForLoadingImage:self.imageURLs[indexPath.row]]
deliverOn:[RACScheduler mainThreadScheduler]]
takeUntil:cell.rac_prepareForReuseSignal]; // No issue

所以我的问题是:

  1. 如何解释为什么后者有效而前者无效?显然存在一些竞争条件导致新信号在现有信号完成之前绑定(bind)到 image 属性,但我完全不确定它究竟是如何发生的。
  2. 我应该记住什么以避免在我的 RAC 驱动代码中出现此类微妙之处?我是否遗漏了上面代码中的一些基本原则,或者是否有任何经验法则可以应用(当然,假设 RAC 本身没有错误)?

感谢阅读到这里:-)

最佳答案

我还没有证实这一点,但这里有一个可能的解释:

  1. Cell X 投入使用,开始下载图像。
  2. 在图像下载完成之前,Cell X 滚动到屏幕外。
  3. 单元格 X 被重用,prepareForReuse 被调用。
  4. Cell X 的 rac_prepareForReuseSignal 发送一个值。
  5. 由于 deliverTo:,值被分派(dispatch)到主队列,引入了运行循环延迟。值得注意的是,这会阻止图像属性的同步/立即解除绑定(bind)。
  6. 单元格 X 重新被使用 cellForRowAtIndexPath:
  7. 调用新图像绑定(bind)并导致警告
  8. ……下一个运行循环……
  9. 原始绑定(bind)现在终于被销毁了,但为时已晚。

所以基本上信号应该在 4 和 6 之间解除绑定(bind),但是 -deliverTo: 重新排序解除绑定(bind)以稍后出现。

关于ios - RAC 和单元重用 : putting deliverOn: in the right place?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27172874/

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