gpt4 book ai didi

ios - 使用 Objective-C 属性 getter 实现 Swift 协议(protocol)

转载 作者:搜寻专家 更新时间:2023-10-31 19:37:25 24 4
gpt4 key购买 nike

我想为 Swift 中所有可突出显示的 View 创建一个共同的祖先。我希望已经存在的实现 highlighted 属性的 UIKit 类开箱即用,所以在阅读 this answer 之后并检查 the Objective-C getter is defined as isHighlighted我将协议(protocol)定义更改为:

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

所以 UILabelUIControl 的协议(protocol)实现就这么简单:

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

效果很好,我可以从 Swift 访问 highlighted 属性并将其设置为 Highlightable 实例。但是,当我尝试使用如下最简单的实现在我的 Swift 类上实现协议(protocol)时:

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
}

最佳答案

您的 UILabelUIControl 扩展满足您创建协议(protocol)的方式,因为它们已经有一个名为 highlighted 的属性,其 getter 访问器方法是 isHighlighted.

您的 HighlightableView 不满足您的 Highlightable 协议(protocol)的采用,因为您对 getter 有 @objc(isHighlighted) 要求。

您必须使用计算属性来满足这一点。但是,这意味着您还需要一个用于 highlighted 属性的后备存储。类似于 private var _highlighted = false

在您的情况下,由于这是不可取的,您可以删除协议(protocol)中的 @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 协议(protocol)公开给 Objective-C 代码。

编辑:

查看 Swift 的 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

关于ios - 使用 Objective-C 属性 getter 实现 Swift 协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41186225/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com