我有UIViewController
并且在viewDidLoad方法中我有一个返回视图的工厂方法。
我正在尝试将UIViewController设置为这些不同视图的委托。但是,每个视图都有不同的委托,当我实际调用工厂方法时,它只返回一个UIView。 UIView当然不了解代表。
我不能很好地将delegate = ViewController
放在ViewFactory本身中,因为这意味着它会了解我的ViewController,这很糟糕。我的另一个想法是,我可以将所有视图转换为它们实际上是什么,所以他们知道代理,但这让我复制了一堆代码,所以我想知道是否有人可以指出我在这里正确的方向?
的ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//This of course would have data to populate it, but I cannot show it here.
let data = [ViewTemplate]()
let someView = ViewFactory.getView((data?[currentCount - 1])!)
//so here is where I thought I could add
//someView.delegate
//but of course it is just a UIView that is returned so it
//doesn't know anything about a delegate
someContainerView.addSubview(someView)
}
}
struct ViewFactory {
static func getView(_ template: ViewTemplate) -> UIView {
switch template.viewType {
case .One:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("OneView", owner: self, options: nil)?.first as! OneView
containerView.label.text = template.text
return containerView
case .Two:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("TwoView", owner: self, options: nil)?.first as! TwoView
containerView.label.text = template.text
return containerView
case .Three:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("ThreeView", owner: self, options: nil)?.first as! ThreeView
containerView.label.text = template.text
return containerView
case .Four:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("FourView", owner: self, options: nil)?.first as! FourView
containerView.label.text = template.text
return containerView
case .Five:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("FiveView", owner: self, options: nil)?.first as! FiveView
containerView.label.text = template.text
return containerView
case .Six:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("SixView", owner: self, options: nil)?.first as! SixView
containerView.label.text = template.text
return containerView
}
}
}
答案 0 :(得分:2)
你有各种选择。您可以使用以下方法:
您可以使UIView
的所有不同自定义子类都来自具有委托属性的公共祖先。 (我们将其称为CustomView
类。)然后,您可以使ViewFactory
返回该类型的对象。
以下是自定义视图的基类:
class CustomView: UIView {
public weak var delegate: AnyObject?
//Put any other shared properties/methods of all CustomView objects here
}
您作为CustomView子类的视图可能如下所示:
class OneView: CustomView {
//Extra properties/methods for a OneView object
}
class TwoView: CustomView {
//Extra properties/methods for a TwoView object
}
最后,重构您的ViewFactory以返回CustomView
类型的视图,而不是普通的UIView
:
struct ViewFactory {
static func getView(_ template: ViewTemplate) -> CustomView {
switch template.viewType {
case .One:
let bundle = Bundle.main
let containerView = bundle.loadNibNamed("OneView", owner: self, options: nil)?.first as! OneView
containerView.label.text = template.text
return containerView
//Your other cases...
}
}
答案 1 :(得分:0)
您可能更好地使用协议,而不是使用类继承。协议仅强制实施类的接口。您可以在一个类中采用多个协议。您只能从一个类继承。
如果您希望在代理中具有通用功能,则为您的委托类创建协议
protocol DelegateProtocol {
func oneView(date: Date)
}
确保所有代表都采用此协议。
class MyDelegate : DelegateProtocol {
func oneView(date: Date) {
}
...
}
创建另一个包含对此委托的引用的协议,并确保所有视图类通过其类定义或类扩展定义采用此协议
class DelegateReferenceProtocol {
var myDelegate : DelegateProtocol? {get set}
}
class OneView : DelegateReferenceProtocol {
var myDelegate : DelegateProtocol? {get {} set(value) {}}
...
}
extension TwoView : DelegateReferenceProtocol {
var myDelegate : DelegateProtocol? {get {} set(value) {}}
...
}
之后,只要您设置了所有视图类以采用DelegateReferenceProtocol协议,您的viewDidLoad函数将如下所示
class ViewController: UIViewController, DelegateProtocol {
override func viewDidLoad() {
super.viewDidLoad()
//This of course would have data to populate it, but I cannot show it here.
let data = [ViewTemplate]()
let someView = ViewFactory.getView((data?[currentCount - 1])!)
someView.myDelegate = self
someContainerView.addSubview(someView)
}
}