swift - 在 Swift 中,你能写一个扩展,它返回扩展所在类的类型化实例吗?

标签 swift casting swift-extensions

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

我正在为我的类开发一个“流畅/链接”风格的 API,以允许您通过可以链接在一起的函数来设置属性,这样您就不必对初始化程序发疯了。此外,它在使用共享相同 API 的 map、filter 和 reduce 等函数时更加方便。

考虑这个 RowManager 扩展...

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

        return self
    }
}

这完全符合人们的预期。但是这里有一个问题……如果您正在使用 RowManager 的子类,这会将对象向下转换回 RowManager,从而丢失所有特定于子类的详细信息。

“别担心!”我想。 “我将只使用 Selfself 来处理类型!”所以我把它改成了这个...

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 上的其他问题也讨论了这些情况下的特定错误。也许这是编译器的错误,因为正如其他人正确指出的那样,这段代码在独立测试中运行良好,但一旦在我们的代码中进行更改,就会出现段错误。

回想起与返回该类型实例的类函数类似的事情,我想起了您必须如何使用私有(private)泛型函数来进行实际的转换,所以我尝试将该模式与以下内容匹配...

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
}

不幸的是,这也不起作用。

作为引用,这里是基于类的代码,我试图以此为基础(className 是另一个扩展,它只返回您调用它的类的名称的字符串表示形式)...

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
    }
}

最佳答案

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

关于swift - 在 Swift 中,你能写一个扩展,它返回扩展所在类的类型化实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44007332/

相关文章:

ios - 如何从另一个 ViewController 中的按钮更改单独 ViewController 中的 textView?

ios - 如何以编程方式更改或制作新的启动图像?

c - C语言中将字符转换为字符串的API

json - 为从 JSON 读取的数据分配适当的类型

数组中数组的 Swift 通用扩展

objective-c - Swift Extension 无法向 Objective-C 类添加重载方法

ios - 如何在类型扩展方法中实例化类型?

json - 如何使用 NSURLSession 在 Swift 中解析 JSON

swift - 从 API Array of array 解析

Java:字节到整数数学求和转换。相同的操作会导致允许和不允许的操作