2016-12-16 67 views
4

我想爲Swift中的所有highlightable視圖創建一個共同的祖先。我想是實現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 {} 

這個偉大的工程,我可以訪問和設置雨燕highlighted財產Highlightable實例。然而,當我試圖實現協議上我的雨燕班,也不像這個最簡單的實現:

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

我得到這個編譯錯誤:

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

我能得到它的工作的唯一辦法正在使用計算的屬性,但它不是我想要的。

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擴展滿足您創建協議的方式,因爲他們已經有一個名爲highlighted其吸氣訪問方法是isHighlighted財產。

您的HighlightableView不符合採用您的Highlightable協議,因爲您對吸氣劑有@objc(isHighlighted)要求。

你必須使用計算屬性來滿足這一點。但是,這意味着您還需要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 

但是,屬性名稱在所有具體類型中都不一致。

這是一種替代方法:

@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特性,同時仍符合Highlightable。這裏的缺點是@objc屬性在不應該有必要的上下文中更普遍。也就是說,@objc屬性未用於將Swift協議公開給Objective-C代碼。

編輯:

看着斯威夫特對於iOS的10 API的diff(和在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 
} 

我希望它可以幫助你什麼。