frazman
frazman

Reputation: 33293

swifty way of doing if else

I am a newbie in swift and I smell a bad code in the following logic

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if let dest = segue.destination as? VC1,
        let index =  collectionView?.indexPathsForSelectedItems?.first{
        dest.selection = self.cellLabels[index.row]
    }
    if let dest2 = segue.destination as? VC2,
        let index2 =  collectionView?.indexPathsForSelectedItems?.first{
        dest2.selection = self.cellLabels[index2.row]
    }
    if let dest3 = segue.destination as? VC3,
        let index3 =  collectionView?.indexPathsForSelectedItems?.first{
        dest3.selection = self.cellLabels[index3.row]
    }

}

Essentially, I have multiple view controllers which I am trying to reach to depending on which Cell is tapped to.

Why I feel this is bad code is because there is a lot of code repeation. Is there a better way to structure this?

Upvotes: 9

Views: 1386

Answers (4)

Rob
Rob

Reputation: 438307

I'd define protocol:

protocol YourProtocolName: class {
    var selection: String? { get set }  // obviously, use whatever type that is appropriate in your case
}

Have your three view controller classes conform to that protocol, e.g.:

class VC1: UIViewController, YourProtocolName {
    var selection: String?

    ...
}

And then:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let dest = segue.destination as? YourProtocolName,
        let index =  collectionView?.indexPathsForSelectedItems?.first {
        dest.selection = cellLabels[index.row]
    }
}

Upvotes: 17

Farkhad Gojazadeh
Farkhad Gojazadeh

Reputation: 96

I would do it using parent class for all three ViewController classes and place the shared variables in the parent class. e.g.

class ParentViewControllerClass: UIViewController{
    var selection: Int?
}

class VC1: ParentViewControllerClass{
}
class VC2: ParentViewControllerClass{
}
class VC3: ParentViewControllerClass{
}

and then you should be able to assign value once. Like:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.destination as? ParentViewControllerClass, 
let index = collectionView?.indexPathsForSelectedItems?.first {
  dest.selection = index
}

This way no matter which of three child view controllers is called the statement will be satisfied

Upvotes: 2

ouni
ouni

Reputation: 3373

guard let index = collectionView?.indexPathsForSelectedItems?.first else { return }
switch segue.destination {
case let dest1 as VC1: dest1.selection = cellLabels[index.row]
case let dest2 as VC2: dest2.selection = cellLabels[index.row]
case let dest3 as VC3: dest3.selection = cellLabels[index.row]
}

Upvotes: 4

ahagbani
ahagbani

Reputation: 132

Try this:

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    self.performSegue(withIdentifier: "segueIdentifier", sender: collectionView.cellForItem(at: indexPath))
}

Upvotes: 1

Related Questions