You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何结合filter、compactMap与withoutActuallyEscaping解决lazy闭包问题

解决Lazy序列中显式self的问题,正确使用withoutActuallyEscaping

首先咱们拆解下你的问题核心:

  • 使用lazy序列时,Swift会将filter/compactMap的闭包标记为逃逸闭包,因此强制要求显式写self.createListItem来提醒你注意循环引用风险;
  • 尝试unowned self失败,是因为你的Information是值类型(结构体),而unowned仅支持类/类绑定协议这类引用类型,这个方向自然走不通;
  • 你之前的withoutActuallyEscaping写法错误,主要是参数传递和闭包类型匹配的问题。

正确的withoutActuallyEscaping实现

下面是修正后的代码,我会同步解释逻辑:

// 假设isFirstDay是你外部定义的变量
var firstDay = false

let listItems: [ListItem] = withoutActuallyEscaping(self.createListItem) { nonEscapingCreate in
    openingHours.lazy
        .filter { $0.openingHourOpen.day.lowercased() == day.lowercased() }
        .compactMap { nonEscapingCreate(thisDay: $0, day: day, isFirstDay: &firstDay) }
}

之前代码报错的原因

  1. 参数类型错误:你给withoutActuallyEscaping传的是类型(OpeningHour) -> ListItem,但它需要的是实际的闭包实例(也就是self.createListItem这个方法引用);
  2. 上下文歧义:withoutActuallyEscaping的第二个参数是接收非逃逸闭包的闭包,你需要给传入的闭包起一个明确的名字(比如nonEscapingCreate),让Swift能正确推断类型。

更简洁的替代方案:局部变量捕获

如果觉得withoutActuallyEscaping有点繁琐,也可以用局部变量捕获方法引用,效果完全一致:

var firstDay = false
let createItem = self.createListItem

let listItems: [ListItem] = openingHours.lazy
    .filter { $0.openingHourOpen.day.lowercased() == day.lowercased() }
    .compactMap { createItem(thisDay: $0, day: day, isFirstDay: &firstDay) }

这个写法的本质是通过局部变量,把实例方法的引用转换成非逃逸闭包使用,同样能避免显式写self。

内容的提问来源于stack exchange,提问作者user1898829

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:03:10