我有BaseViewController
我的SearchViewController
是子类。我需要将超类中的按钮的目标分配给子类中的方法。我在超类中有一个名为addBackButton(_:)
的方法,它为navigationView(自定义视图)添加了一个按钮。我从子类中调用此方法。
上面的方法接受一个viewcontroller对象,我通过将self
传递给方法从子类中调用它。这样它工作正常。方法定义如下:
func addBackButton(from vc: AnyObject) {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 10, y: 20, width: 44, height: 44)
button.setImage(UIImage(named: "back")?.withRenderingMode(.alwaysTemplate), for: UIControlState())
button.tintColor = currentTheme.navButtonTintColor
if vc.isKind(of:SearchViewController.self) {
let controller: SearchViewController = self as! SearchViewController
button.addTarget(controller, action: #selector(controller.backButtonTapped(_:)), for: .touchUpInside)
}
navigationBarView.addSubview(button)
}
我有两个问题:
'vc is SearchViewController'
和'vc.isKind(of:SearchViewController.self)'
,两者都可以正常工作。哪个是从超类中识别子类的正确方法?根据anbu.karthiks评论,我使用超类中的self来识别子类。
func addBackButton() {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 10, y: 20, width: 44, height: 44)
button.setImage(UIImage(named: "back")?.withRenderingMode(.alwaysTemplate), for: UIControlState())
button.tintColor = currentTheme.navButtonTintColor
switch self {
case is SearchViewController:
let controller: SearchViewController = self as! SearchViewController
button.addTarget(controller, action: #selector(controller.backButtonTapped(_:)), for: .touchUpInside)
break
case is HelpViewController:
let controller: HelpViewController = self as! HelpViewController
button.addTarget(controller, action: #selector(controller.backButtonTapped(_:)), for: .touchUpInside)
break
default:
break
}
navigationBarView.addSubview(button)
}
答案 0 :(得分:2)
是的,你做的方式工作正常,是一种方法。另一种方法是:
if let controller = vc as? SearchViewController {
// use controller in here which is casted to your class and ready to be used
}
所以你的代码:
func addBackButton(from vc: AnyObject) {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 10, y: 20, width: 44, height: 44)
button.setImage(UIImage(named: "back")?.withRenderingMode(.alwaysTemplate), for: UIControlState())
button.tintColor = currentTheme.navButtonTintColor
if let controller = vc as? SearchViewController {
button.addTarget(controller, action: #selector(controller.backButtonTapped(_:)), for: .touchUpInside)
}
navigationBarView.addSubview(button)
}
超类与子类之间的正确通信方式是什么?
没有什么是对或错,但有些方法比其他方法更好。请查看上面的示例,了解如何执行此操作的一个示例。
答案 1 :(得分:0)
这不是在子类和超类之间进行通信的正确方法, 实际上,这种方法是面向对象的。
在超类中的addBackButton()
函数中进行向下转换与面向对象的思想冲突。
在超类中,应放置与所有子类相符的通用代码,如果需要在特定的类中添加一些额外的代码,则应覆盖该函数并将特定代码写入特定的子类,然后调用超级。“ functionName”(如果需要)。
在您的代码中,您可以在超类中创建一个名为backButtonTapped()的函数。 并在任何子类中覆盖此函数,并编写所需的特定代码。
例如以下示例:
class SuperClass: UIViewController {
let navigationBarView = UINavigationBar()
func addBackButton(from vc: AnyObject) {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 10, y: 20, width: 44, height: 44)
button.setImage(UIImage(named: "back")?.withRenderingMode(.alwaysTemplate), for: UIControlState())
button.tintColor = .white
button.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
navigationBarView.addSubview(button)
}
@objc func backButtonTapped() {
//every subClass will override this funcion and handle it
}
}
class Subclass: SuperClass {
override func backButtonTapped() {
//Do your specific code....
}
}
我希望这会有所帮助。