2017-02-21 4 views
1

Dans le code suivant, basé sur la comparaison de chaîne, je décide sur quel VC sera montré. Maintenant, tout le code est répétitif sauf le nom de la classe et je veux éviter cela. Mais, rapide n'a pas NSClassFromStringÉviter le code répétitif dans swift

Comment puis-je accomplir cela? Dois-je utiliser Génériques/Modèles? Aucune suggestion!

Désolé d'avance, s'il me manque quelque chose d'idiot ici.

+1

Oui, vous pouvez créer la fonction simple pour accomplir cette chaîne (décrivant: SomeViewController.self) –

Répondre

3

La suppression de duplication est évidente:

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 est la superclasse commune de vos 3 contrôleurs, par exemple :

class PVC : UIViewController {} 
class XVC : PVC {} 
class YVC : PVC {} 
class ZVC : PVC {} 

Si vos 3 classes ne sont pas une superclasse commune, vous pouvez utiliser un protocole à la place:

protocol PVC : class { 
    var data: ... 
    var isFul: ... 
    weak var delegate: ... 
} 

et la mettre en œuvre par vos 3 classes:

En bref, à supprimer la duplication, vous devez ajouter une interface commune aux 3 contrôleurs. Soit en utilisant une superclasse ou un protocole commun.

+0

Merci pour votre temps. Cela m'a beaucoup aidé. :) –

0

Vous pouvez simplement créer une fonction qui récupère l'identifiant et renvoie le viewcontroller. Depuis votre XVC, YVC, ZVC n'ont similitude, vous pouvez aussi les faire sous-classé d'autres VC qui ont leur propriété comme data, isFull,...

En outre, vous pouvez utiliser similaire à NSClassFromString avec String(describing: SomeViewController.self) retournera SomeViewController

2

Modifier

Je préfère la réponse de Sulthan car il est plus propre que la mienne (Je dois admettre ...)

Pour terminer le mien, getControllerFor:type besoin de retourner une classe parente. Vous avez oublié de mentionner

J'edited réponse d'abord à corriger plusieurs misses et de le rendre plus concis

Première réponse

Vous pourriez faire quelque chose comme ça:

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 
    } 
} 

avec

class SuperType {} 
class XVC: SuperType {} 
class YVC: SuperType {} 
class ZVC: SuperType {} 

Idéalement, type n'est pas un String mais un Enum

+0

Merci pour votre temps :) –

2

Vous pouvez le faire très bien avec une énumération. Vous avez juste besoin que chacun de vos ViewControllers soit conforme à 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 } 
} 

Vous pouvez ensuite l'utiliser comme ceci:

if dataObj.type == "X" { 
    let vc: XVC = ViewControllers.x.getViewController(dataObj: dataObj, delegate: self) 
    pvc = vc 
}