在下面的代码中,基于字符串比较,我决定将显示哪个VC。
<link rel="stylesheet" type="text/css" href="./src/vendors/css/ionicons.min.css">
现在,所有代码都是重复的,除了类名,我想避免这种情况。但是,swift没有func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dataObj = frc.object(at: indexPath) as! Data_Object
var pvc: UIViewController?
if dataObj.type == "X" {
let obj = MainStoryboard().instantiateViewController(withIdentifier: "XVC") as! XVC
obj.data = dataObj
obj.isFull = true
obj.delegate = self
pvc = obj as UIViewController
} else if dataObj.type == "Y" {
let obj = MainStoryboard().instantiateViewController(withIdentifier: "YVC") as! YVC
obj.data = dataObj
obj.isFull = true
obj.delegate = self
pvc = obj as UIViewController
} else {
let obj = MainStoryboard().instantiateViewController(withIdentifier: "ZVC") as! ZVC
obj.data = dataObj
obj.isFull = true
obj.delegate = self
pvc = obj as UIViewController
}
obj.modalPresentationStyle = .popover
let popPVC = pvc?.popoverPresentationController
popPVC?.sourceView = self.view
self.present(pvc!, animated: true, completion: nil)
}
我如何做到这一点?我应该使用泛型/模板吗?任何建议!
如果我在这里遗漏了一些傻话,请提前抱歉。
答案 0 :(得分:3)
删除重复是显而易见的:
let identifier: String
switch dataObj.type {
case "X":
identifier = "XVC"
case "Y":
identifier = "YVC"
default:
identifier = "ZVC"
}
let pvc = MainStoryboard().instantiateViewController(withIdentifier: identifier) as! PVC
pvc.data = dataObj
pvc.isFull = true
pvc.delegate = self
其中PVC
是3个控制器的常见超类,例如:
class PVC : UIViewController {}
class XVC : PVC {}
class YVC : PVC {}
class ZVC : PVC {}
如果您的3个类没有共同的超类,则可以改为使用协议:
protocol PVC : class {
var data: ...
var isFul: ...
weak var delegate: ...
}
并由您的3个班级实施:
简而言之,要删除重复,您需要为3个控制器添加通用接口。使用公共超类或协议。
答案 1 :(得分:2)
修改强>
我更喜欢Sulthan的答案,因为它比我更清洁(不得不承认......)
要完成我的,getControllerFor:type
需要返回父类。忘了提它
我编辑了第一个答案来纠正几个未命中并使其更简洁
第一个回答
你可以这样做:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dataObj = frc.object(at: indexPath) as! Data_Object
var pvc: UIViewController?
let obj = getControllerFor(type: dateObj.type)
obj.data = dataObj
obj.isFull = true
obj.delegate = self
pvc = obj as UIViewController
obj.modalPresentationStyle = .popover
let popPVC = pvc?.popoverPresentationController
popPVC?.sourceView = self.view
self.present(pvc!, animated: true, completion: nil)
}
func getControllerFor(type : String) -> SuperType? {
switch type {
case "X": return XVC()
case "Y": return YVC()
case "Z": return ZVC()
default: return nil
}
}
与
class SuperType {}
class XVC: SuperType {}
class YVC: SuperType {}
class ZVC: SuperType {}
理想情况下,type
不是String
,而是Enum
答案 2 :(得分:2)
你可以用枚举很好地完成这项工作。您只需要使每个ViewControllers符合CustomViewController。
enum ViewControllers: String {
case x = "X"
case y = "Y"
case z = "Z"
func getViewController<T>(dataObj: Data_Object, delegate: YourDelegate?) -> T where T: UIViewController, T: CustomViewController {
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: self.rawValue) as! T
viewController.data = dataObj
viewController.isFull = true
viewController.delegate = delegate
return viewController
}
}
protocol CustomViewController: class {
var data: Data_Object! { get set }
var isFull: Bool! { get set }
weak var delegate: YourDelegate? { get set }
}
然后你会像这样使用它:
if dataObj.type == "X" {
let vc: XVC = ViewControllers.x.getViewController(dataObj: dataObj, delegate: self)
pvc = vc
}
答案 3 :(得分:0)
您可以创建一个获取标识符并返回viewcontroller的函数。由于你的XVC,YVC,ZVC确实有相似之处,你也可以将它们作为其他具有data, isFull,...
此外,您可以使用与NSClassFromString
类似的String(describing: SomeViewController.self)
将返回SomeViewController