在 Swift 中,您可以编写一个扩展,其中 returns 是 class 扩展的类型化实例吗?

In Swift, can you write an extension which returns a typed instance of the class the extension is on?

这是看起来足够简单的事情之一,但并不像您期望的那样工作。

我正在为我的 classes 开发一种 'fluent/chaining' 风格的 API 以允许您通过可以链接在一起的函数来设置属性,这样您就不必疯狂使用初始化器。此外,它在使用共享相同类型 API.

的 map、filter 和 reduce 等函数时更加方便

考虑这个 RowManager 扩展...

extension RowManager
{
    @discardableResult
    public func isVisible(_ isVisible:Bool) -> RowManager
    {
        self.isVisible = isVisible

        return self
    }
}

这完全符合人们的预期。但是这里有一个问题......如果你正在使用 RowManager 的子 class,这会将对象向下转换回 RowManager,丢失所有子 class -具体细节。

"No worries!"我想。 "I'll just use Self and self to handle the type!"所以我把它改成了这个...

extension RowManager
{
    @discardableResult
    public func isVisible(_ isVisible:Bool) -> Self // Note the capitalization representing the type, not instance
    {
        self.isVisible = isVisible

        return self // Note the lowercase representing the instance, not type
    }
}

...但由于某种原因甚至无法编译并给出以下错误...

Command failed due to signal: Segmentation fault: 11

更新

多研究一下,这似乎是因为我们的代码既在动态库中,也使用动态库。 SO 上的其他问题也讨论了这些情况下的特定错误。也许这是编译器的一个错误,因为正如其他人正确指出的那样,这段代码在独立测试中运行良好,但一旦我们的代码进行更改,就会出现分段错误。

记得与 class 函数类似的东西 return 该类型的一个实例,我想起了你必须如何使用私有泛型函数来进行实际的转换,所以我试图匹配它具有以下模式...

extension RowManager
{
    @discardableResult
    public func isVisible(_ isVisible:Bool) -> Self // Note the capitalization
    {
        self.isVisible = isVisible

        return getTypedSelf()
    }
}

private func getTypedSelf<T:RowManager>() -> T
{
    guard let typedSelfInstance = self as? T
    else
    {
        fatalError() // Technically this should never be reachable.
    }

    return typedSelfInstance
}

不幸的是,这也没有用。

作为参考,这里是基于 class 的代码,我试图将其作为基础(className 是另一个扩展名,它只是 returns 名称的字符串表示class 你调用它的)...

extension UITableViewCell
{
    /// Attempts to dequeue a UITableViewCell from a table, implicitly using the class name as the reuse identifier
    /// Returns a strongly-typed optional
    class func dequeue(from tableView:UITableView) -> Self?
    {
        return self.dequeue(from:tableView, withReuseIdentifier:className)
    }

    /// Attempts to dequeue a UITableViewCell from a table based on the specified reuse identifier
    /// Returns a strongly-typed optional
    class func dequeue(from tableView:UITableView, withReuseIdentifier reuseIdentifier:String) -> Self?
    {
        return self.dequeue_Worker(tableView:tableView, reuseIdentifier:reuseIdentifier)
    }

    // Private implementation
    private class func dequeue_Worker<T:UITableViewCell>(tableView:UITableView, reuseIdentifier:String) -> T?
    {
        return tableView.dequeueReusableCell(withIdentifier: reuseIdentifier) as? T
    }
}

在 WWDC Apple 确认这是一个 Swift 编译器问题,我们的代码库中的其他东西正在触发,添加在任何情况下都不应该出现编译器中出现 Seg11 错误的情况,所以这问题实际上是无效的。现在关闭它,但如果他们解决了它,我会报告回来。