Swift 4 闭包 : failing to access another local property from within the closure

标签 swift closures

我一直在尝试在 Swift 中做一些我认为应该相对简单的事情——将闭包作为属性存储在结构中,这样它就可以通过使用结构的另一个属性来过滤数组。但是我遇到了一个障碍——我不能在结构初始化器中添加闭包,因为它想要引用的变量不存在,我不能使它成为一个惰性变量作为协议(protocol)的一部分(不确定如果这仍然有效),并且在初始化结构后我无法分配它,因为它将捕获我从中进行分配的对象的上下文,并尝试将其用于本地属性。一个简化的场景如下:

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: { self.dateRange.contains(date) 中的日期}

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

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

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

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

有人有什么想法吗?

最佳答案

闭包内代码的范围是它写入的对象。而不是它被传递到的对象。

所以在...

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

我认为这会做您正在尝试做的事情。

关于Swift 4 闭包 : failing to access another local property from within the closure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49135978/

相关文章:

ios - 将 Swift 函数转换为 Objective C 并在 swift 中使用返回值

ios - 如何在 Swift 中使用字典构建 URL

php - 从 Laravel 4 中的事务中返回数据

javascript - 一个类的所有成员的onclick函数

unit-testing - 如何比较/匹配模拟中的闭包?

xcode - 动态更改标签栏背景颜色

ios - 绘制的图像不会出现在相机覆盖 Swift 上

swift - 在搜索栏(ModernSearchBar)之后重新加载表格 View

循环内的 JavaScript 闭包——简单实用的例子

Swift - 捕获列表 self 澄清