Swift 4 Closure:无法从闭包内访问另一个本地属性

问题描述 投票:0回答:1

我一直在尝试在Swift中做一些我认为应该相对简单的事情 - 将闭包存储在结构中作为属性,以便它可以用于通过使用结构的另一个属性来过滤数组。但是我遇到了一个块 - 我不能在struct initialiser中添加闭包,因为它想要引用的变量不存在,我不能把它变成一个懒惰的变量作为它的一部分协议(不确定)如果这无论如何都可以工作),并且在初始化结构之后我无法分配它,因为它将捕获eI进行赋值的对象的上下文,并尝试将其用于本地属性。简化方案如下:

struct EventSpec {
    var dateRange: DateInterval
    var filterClosure: ((Date) -> Bool)?

    init( dateRange: DateInterval) {
        self.dateRange = dateRange
    }

    func provideMatchingEvents(for events: [Event] {
        return events.filters{filterClosure($0.date)}
}

struct Event {
    name: String
    date: Date
}

理想情况下想要初始化

eventSpec = EventSpec(dateRange: aDateRamge, filterClosure: { date in self.dateRange.contains(date)}

但这不起作用,因为此时没有self.dateRange。

尝试之后直接或通过“构建器”函数添加闭包不会起作用,因为它捕获它所涉及的位置的“自我”,而不是访问EventSpec的dateRange属性。

我确定这应该是一个常见的模式,我错过了一些明显的东西,但只能找到引用(很多)将闭包添加为不引用其他属性的变量。

(我意识到如果我在结构中对闭包进行了硬编码,我可以通过标准捕获列表访问局部变量,但是这样就无法在运行时定义过滤器)。

任何想法?

swift closures
1个回答
1
投票

闭包内部的代码范围是在它写入的对象中。不是它传入的对象。

所以......

EventSpec(dateRange: aDateRamge) { date in
    self.dateRange.contains(date)
}

self是创造EventSpec对象的地方。

你能做的就是在封闭本身捕获dateRange

所以你可以像这样重新定义EventSpec ......

struct EventSpec {
    var filterClosure: ((Date) -> Bool)?

    func provideMatchingEvents(for events: [Event]) {
        return events.filters{ filterClosure($0.date) }
    }
}

然后像......那样创建它

let dateRange = //some date range that you have already got
let eventSpec = EventSpec(filterClosure: { dateRange.contains($0) })
// in this line the dateRange is captured by the closure so you don't need to capture it as a separate property

这会做你想做的事情。

© www.soinside.com 2019 - 2024. All rights reserved.