2016-12-16 5 views
4

Swiftのすべてのハイライト可能なビューに対して共通の祖先を作成したいとします。私は、すでにhighlightedプロパティは、箱から出して働いていた実装のUIKitクラスを既存のことを望んでいたのでthis answerを読んで、私はこれに、プロトコルの定義を変更しthe Objective-C getter is defined as isHighlightedことを確認した後:Objective-Cプロパティゲッターを使用したSwiftプロトコルの実装

@objc protocol Highlightable { 
    var highlighted: Bool { @objc(isHighlighted) get set } 
} 

のでUILabelUIControlのためのプロトコル実装のようにありますこのような単純な:これは素晴らしい作品

extension UILabel: Highlightable {} 
extension UIControl: Highlightable {} 

、私がアクセスしHighlightableインスタンスとしてスウィフトからhighlightedプロパティを設定することができます。私はこのような最も単純な実装で私スウィフトクラスのプロトコルを実装しようとすると、しかし、私はそれが仕事を得ることができ

Objective-C method 'highlighted' provided by getter for 'highlighted' does not match the requirement's selector ('isHighlighted')

唯一の方法:

class HighlightableView: UIView, Highlightable { 
    var highlighted: Bool = false 
} 

私はこのコンパイル・エラーが発生します計算されたプロパティを使用していますが、それは私が望むものではありません。

class HighlightableView: UIView, Highlightable { 
    var highlighted: Bool { @objc(isHighlighted) get { return true } set {} } 
} 

私の環境はXcode 8.0とSwift 3です.XCode 8.2にアップデートされ、エラーが続く。


私の現在の回避策は、Objective-CとSwiftの命名の競合を完全に回避することです。しかし、これは理想からかけ離れている:

@objc protocol Highlightable { 
    var _highlighted: Bool { get set } 
} 

extension UILabel: Highlightable { 
    var _highlighted: Bool { 
     get { return isHighlighted } 
     set { isHighlighted = newValue } 
    } 
} 
extension UIControl: Highlightable { 
    var _highlighted: Bool { 
     get { return isHighlighted } 
     set { isHighlighted = newValue } 
    } 
} 
class HighlightableView: UIView, Highlightable { 
    var _highlighted: Bool = false 
} 

答えて

1

あなたUILabelUIControlの拡張機能は、あなたのプロトコルを作成した方法を満たします。

HighlightableViewは、ゲッターに@objc(isHighlighted)という要件があるため、Highlightableプロトコルの採用を満たしていません。

これを満たすには、計算されたプロパティを使用する必要があります。ただし、highlightedプロパティのバッキングストアも必要です。 private var _highlighted = falseのようなものです。

これは望ましくないため、ご使用のプロトコルの@objc属性を削除することができます。

protocol Highlightable: class { 
    var highlighted: Bool { get set } 
} 

extension UILabel: Highlightable { } 
extension UIControl: Highlightable { } 

class HighlightableView: UIView, Highlightable { 
    var highlighted = false 
} 

let label = UILabel() 
label.isHighlighted // Prior to iOS 10, this property is called "highlighted" 

let view = HighlightableView() 
view.highlighted 

let highlightables: [Highlightable] = [ label, view ] 

for highlightable in highlightables { 
    print(highlightable.highlighted) 
} 

// Prints: 
// false 
// false 

ただし、プロパティ名はコンクリートタイプ全体で一貫しません。ここで

は別のアプローチである:まだHighlightableに準拠しながら、

@objc protocol Highlightable: class { 
    var isHighlighted: Bool { @objc(isHighlighted)get @objc(setHighlighted:)set } 
} 

extension UILabel: Highlightable { } 
extension UIControl: Highlightable { } 

class HighlightableView: UIView, Highlightable { 
    private var _isHighlighted = false 
    var isHighlighted: Bool { 
     @objc(isHighlighted) get { 
      return _isHighlighted 
     } 
     @objc(setHighlighted:) set { 
      _isHighlighted = newValue 
     } 
    } 
} 

let label = UILabel() 
label.isHighlighted = true 

let view = HighlightableView() 
view.isHighlighted 

let highlightables: [Highlightable] = [ label, view ] 

for highlightable in highlightables { 
    print(highlightable.isHighlighted) 
} 

// Prints: 
// false 
// false 

これは、具体的なタイプのすべてにわたって一貫したisHighlightedプロパティを公開します。ここでの欠点は、@objc属性がコンテキスト内でより普及し、必要ではないはずであるということです。つまり、@objc属性はSwiftプロトコルをObjective-Cコードに公開するために使用されていません。

EDIT:

スウィフトのためのiOS 10 APIの差分を見て(とXcode 7.2でいくつかのテストをやって)、UILabelUIControlisHighlightedプロパティは、以前highlighted命名されました。上記のコードをiOS SDK 9.3以下とリンクして使用すると、コンパイル時にエラーが発生します。

最初の例では、label.isHighlighted行の名前をlabel.highlightedに変更すると、これらのエラーを修正できます。

isHighlightedのすべてのインスタンスの名前をhighlightedに変更することで、これらのエラーを修正できます(@objc属性の角括弧内にあるものを除く)。

9.3からiOS 10.0 APIの相違点:https://developer.apple.com/library/content/releasenotes/General/iOS10APIDiffs/index.html

+0

最初のサンプルをテストしましたか?私はそれをコンパイルすることができません – redent84

+0

@ redent84はい。それは私のためにうまくコンパイルされます(Xcode 8.2)。エラーを共有できますか? –

+0

XCode 8.0では動作しませんが、XCode 8.2では動作します。 – redent84

0

は、私は解決策を持っているが、それはあなたが望むよりも少し大きいです、しかし、私はそれはあなたを助けると思います。

あなたが迅速なプロトコルを行うと、あなたは

protocol Highlightable: class { 
    var highlighted: Bool { get set } 
} 

extension Highlightable where Self: UILabel { 
    var highlighted: Bool { 
     get { 
      return isHighlighted 
     } 
     set { 
      isHighlighted = newValue 
     } 
    } 
} 

extension Highlightable where Self: UIControl { 
    var highlighted: Bool { 
     get { 
      return isHighlighted 
     } 
     set { 
      isHighlighted = newValue 
     } 
    } 
} 

を必要とするもののクラスのデフォルトの実装を決定する必要がありますだから、私はそれがあなたの役に立てば幸い

extension UILabel: Highlightable {} 
extension UIControl: Highlightable {} 

class CustomView: UIView, Highlightable { 
    var highlighted: Bool = false 
} 

それを実装することができます。彼らはすでにゲッターアクセサメソッドisHighlightedですhighlightedと呼ばれる性質を持っているので、

関連する問題