避免在swift中重复代码

时间:2017-02-21 09:28:55

标签: ios swift generics redundancy

在下面的代码中,基于字符串比较,我决定将显示哪个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) }

我如何做到这一点?我应该使用泛型/模板吗?任何建议!

如果我在这里遗漏了一些傻话,请提前抱歉。

4 个答案:

答案 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,...

属性的VC的子类。

此外,您可以使用与NSClassFromString类似的String(describing: SomeViewController.self)将返回SomeViewController