快速覆盖文件私有扩展名中的打开变量时发出警告

Posted

技术标签:

【中文标题】快速覆盖文件私有扩展名中的打开变量时发出警告【英文标题】:Warning when Overriding an open var inside a fileprivate extension in swift 【发布时间】:2017-01-18 16:03:01 【问题描述】:

考虑以下问题。

fileprivate extension UIButton 
    override open var isSelected: Bool 
        didSet 
            self.titleLabel?.font = isSelected ? UIFont(name: "HelveticaNeue-Medium", size: 14) : UIFont(name: "HelveticaNeue-Light", size: 14)
        
    

过了一会儿,xcode 中出现了一个警告,要求我将“open”更改为 fileprivate。当然,如果我这样做,那么我不会从 UIButton 覆盖相同的 isSelected 变量,我会收到错误消息。

这是一个 XCode 错误吗?我无法将扩展设置为公开或内部的,因为该行为会改变应用程序中的所有 UIButtons。 有什么想法吗?

更新:

确切的警告是这样的。

【问题讨论】:

你得到的确切警告是什么? 声明完全有效并且按预期工作。警告是错误的。 警告消息是错误的,因为编译器的消息文件中存在错误,它应该是“在文件私有扩展中声明 OPEN var”,类似问题请参见 ***.com/questions/40983010/…。作为解决方案,您可以从 extension 中删除 fileprivate 【参考方案1】:

有趣的是,Swift 实际上允许你这样做。我相信你不能在私有(fileprivate)上下文中覆盖公共方法是故意的。

你真正想要的东西模棱两可:

在您的情况下,您在仅适用于文件本身的上下文中覆盖该方法。有人可能认为覆盖仅适用于该文件中的按钮,但事实并非如此。现在,您的应用程序中的每个按钮实际上都将具有覆盖的方法(已对其进行测试)。因此,您的解决方案肯定是在公开的扩展中覆盖此方法。

注意:我知道它是一个属性而不是一个方法,但在幕后,这是一个在调用对象的 setter 后触发的方法。

【讨论】:

我的心都碎了。它确实无处不在!那为什么还存在 fileprivate 扩展呢? @L_Sonic 不用于覆盖。它用于子类化或创建文件私有类。甚至对于公共协议实现也不行。在您的情况下使用子类。另外让我与您分享一个您很少看到的建议:当涉及到对不属于您的类(例如 UIButton)进行扩展时,不惜一切代价避免!说真的,除非真的没有其他方法可以产生您的解决方案,否则永远不要这样做。 似乎比为了更改字体而对整个类进行子类化更简洁。感谢您的建议! @L_Sonic 我能感觉到你,但不幸的是,这些事情不是那样工作的。但是,如果他们确实只是问自己一件事:扩​​展什么时候才能真正起作用?如果按钮是在这个文件中创建的?如果在此文件中调用了 setter?如果此文件中使用了按钮实例?一般来说,我练习拥有一个按钮的自定义子类,然后在整个应用程序中使用它。然后,您可以轻松添加其他属性或逻辑。您甚至可以添加 IB 检查项以在 IB 中控制它们。

以上是关于快速覆盖文件私有扩展名中的打开变量时发出警告的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖私有方法并快速调用超级?

发出注释处理器的实时错误和警告

方法不会覆盖 Eclipse 中的包可见方法

从测试访问私有变量并完成覆盖功能

覆盖(非)静态类中的私有方法

有没有办法快速覆盖框架中的应用程序委托?