最近、コードをSwift 4に移行しました。私が直面している問題がありますextensions、つまり:
拡張機能からの宣言はまだオーバーライドできません
この問題に関する複数の投稿を既に読んでいます。ただし、それらのいずれも、以下に説明するシナリオを楽しませません。
_class BaseCell: UITableViewCell
{
//Some code here...
}
extension BaseCell
{
func isValid() -> String?
{
//Some code here...
}
}
class SampleCell: BaseCell
{
//Some code here...
override func isValid() -> String? //ERROR..!!!
{
//Some code here...
}
}
_
Appleによると、
拡張機能は、新しい機能を型に追加できますが、既存の機能を上書きすることはできません。
しかし、上記のシナリオでは、拡張機能でisValid()
メソッドをオーバーライドしていません。 SampleCell
クラス定義自体でオーバーライドされます。それでも、エラーが発生しています。
しかし、上記のシナリオでは、拡張機能でメソッド
isValid()
をオーバーライドしていません。
isValid
はextensionで宣言されます。
このエラーは、関数がこのように宣言されている場合、オーバーライドできないと言っています。
このステートメントは、拡張機能からと拡張機能からの両方に有効です。
プロトコルを@objc
する限り、拡張機能からの宣言をオーバーライドできます。 In Swift 4.2:
class BaseClass {}
class SubclassOfBaseClass: BaseClass {}
@objc protocol IsValidable {
func isValid() -> Bool
}
extension BaseClass: IsValidable {
func isValid() -> Bool { return false }
}
extension SubclassOfBaseClass {
override func isValid() -> Bool { return !super.isValid() }
}
BaseClass().isValid() // -> false
SubclassOfBaseClass().isValid() // -> true
Swift 3では、拡張機能がObjective-Cから派生したクラスの場合、拡張機能をオーバーライドできました( http://blog.flaviocaetano.com/post/this-is-how-to-override-extension-methods / )、しかしSwift 4.では不可能だと思います。もちろん、次のようなことができます:
protocol Validity {
func isValid() -> String?
}
class BaseCell: UITableViewCell, Validity {
}
extension Validity
{
func isValid() -> String? {
return "false"
}
}
class SampleCell: BaseCell {
func isValid() -> String? {
return "true"
}
}
let base = BaseCell()
base.isValid() // prints false
let sample = SampleCell()
sample.isValid() // prints true
これは一目瞭然だと思います。 宣言[〜#〜] from [〜#〜]拡張機能はまだオーバーライドできません
override
クラス自体ではなく、extension
のBaseCell
内で宣言された関数func isValid() -> String?
をBaseCell
しようとしています。
拡張機能内で宣言されたものをオーバーライドできないことを明確に言っています。
お役に立てば幸いです。
私もSwift 3コードの巨大な遺産を持っていたので、この古いトリックを使用して望みを達成したため、Swift 4に移動してこれらのエラーを取得し始めたとき、私は多少苦しみました。 。恐れないで、解決策があります。
このエラーは、Swift 4がクラスをコンパイルする方法と、Objective-Cのクラスと関数を処理する新しい方法に関係しています。 Swift 3の下で、クラスがNSObjectから派生している場合、そのクラスのすべての変数と関数は、Objective-Cの動的な命名規則と検索規則を使用します。このアプローチは、コードを最適化し、コードのパフォーマンスとサイズを改善するSwiftの機能を阻害しました。
これらのペナルティを克服するために、Swift 4では、@objc
で明示的にタグ付けされた変数と関数のみがObjective-C処理を取得し、他のすべては標準のSwift規則を使用します:したがってエラー。
この知識を備えた問題の解決策は、オーバーライドする拡張機能の関数に@objc
のタグを付け、次に子クラスで関数をオーバーライドすることです。ただし、@objc
タグは、実行時にコードが呼び出されるようにします。
[〜#〜] warning [〜#〜]これはちょっとした落とし穴です。@objc
をoverride
に含めるのを忘れても、コンパイラは文句を言いません。ただし、コードには動的ルックアップがないため、実行時に呼び出されることはありません。
したがって、コードは次のようになります。
class BaseCell: UITableViewCell {
//Some code here...
}
extension BaseCell {
@objc func isValid() -> String? {
//Some code here...
}
}
class SampleCell: BaseCell {
//Some code here...
@objc override func isValid() -> String? {
//Some code here...
}
}
Swiftでは無効ですが、Objective-Cでは無効です。したがって、メソッドシグネチャで許可されている場合(objcで禁止されている構造はありません)、@objc func myMethod()
を宣言して、Swiftで自由にオーバーライドできます。