如何解决带有委托的 Swift 协议属性
我正在尝试通过协议和扩展在控制器上设置成功/错误视图。
我想要实现的是,我想进入足以在控制器上实现协议的状态,并从那里访问成功视图(没有额外的样板)。
这是我目前所拥有的:
protocol SucessViewProtocol where Self: UIViewController {
func initSuccessView()
var successView: UIView! { get set }
var topConstraint: NSLayoutConstraint! { set get }
func showSuccess()
func hideSucess()
}
extension SucessViewProtocol {
func showSuccess() {
//animate displaying success message
}
func hideSucess() {
//animate hiding success message
}
func initSuccessView() {
successView = UIView()
topConstraint = NSLayoutConstraint()
// init success view and top constraint
}
}
现在,当我在控制器上实现协议时,它看起来像这样:
// MARK: SuccessView
extension ConsumingViewController: SucessViewProtocol {
var successView: UIView! {
get {
//getter
}
set {
//setter
}
}
var topConstraint: NSLayoutConstraint! {
get {
//getter
}
set {
//setter
}
}
}
我想我的问题很明显,因为我在实现 SucessViewProtocol 的控制器中获得了 successView 和 topConstraint 作为属性。我正在从扩展中的协议初始化属性,所以我需要的只是对这些属性的访问(不在我的控制器中再次声明它们)。我想我错过了协议 - 扩展 - 控制器之间的一些“胶水”部分
我希望能够在控制器上实现协议,调用 initSuccessView()
,然后从那里调用 showSuccess
和 hideSuccess
就足够了。
编辑:
这就是我想使用这个结构的方式:
class ConsumingViewController: UIViewController {
func viewDidLoad() {
initSuccessView()
loadData()
}
private func loadData() {
//successfullyloaded
showSuccess()
}
}
// MARK: SuccessView
extension ConsumingViewController: SucessViewProtocol {
var successView: UIView! {
get {
//getter
}
set {
//setter
}
} *PROBLEMATIC*
var topConstraint: NSLayoutConstraint! {
get {
//getter
}
set {
//setter
}
} *PROBLEMATIC*
}
正如我所说,问题是在 ConsumingViewController 中重新声明了属性 successView 和 topConstraing(因为它们是协议的一部分)。我实际上不需要在控制器内可见,而只是在扩展内使用。但是,扩展中的存储属性存在问题......
解决方法
你可能想要这个吗?
protocol SucessViewProtocol {
func showSuccess()
func hideSucess()
}
fileprivate struct Key {
static var runtimeKey: Int = 0
}
extension SucessViewProtocol where Self: UIViewController {
var successView: UIView? {
get {
return objc_getAssociatedObject(self,&Key.runtimeKey) as? UIView
}
set {
objc_setAssociatedObject(self,&Key.runtimeKey,newValue,.OBJC_ASSOCIATION_RETAIN)
}
}
func showSuccess() {
successView = UIView()
//animate displaying success message
view.addSubview(successView)
}
func hideSucess() {
//animate hiding success message
successView?.removeFromSuperview()
}
}
,
像这样在主作用域内添加协议变量而不是扩展作用域 UIViewController。
public class ViewController: UIViewController,SucessViewProtocol {
var successView: UIView!
var topConstraint: NSLayoutConstraint!
}
这样做你不需要为属性定义 getter 和 setter
在 ViewDidLoaded 中你可以 initSuccessView:
public override func viewDidLoad() {
super.viewDidLoad()
self.initSuccessView()
}
并调用自定义函数:
func show() {
self.showSuccess()
}
func hide() {
self.hideSucess()
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。