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) } }
之前代码报错的原因
- 参数类型错误:你给
withoutActuallyEscaping传的是类型(OpeningHour) -> ListItem,但它需要的是实际的闭包实例(也就是self.createListItem这个方法引用); - 上下文歧义:
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
相关产品推荐
相关产品推荐

