2

The Problem: I have a view controller, that holds two variables, without which the controller isn't able to work. So, by concept, those variables are mandatory or non-optional.

However, I declared them optional, which results in guard statement in the first lines of nearly every single method. The reason for making them optional is:

  • I'm not able to give them reasonable default values, they need to be set from outside during initialization
  • I initialize the controller with storyboard?.instantiateViewControllerWithIdentifier so there is no way (as far as I know) to define my own initializer which takes the necessary values. This would, obviously my favorite solution.
  • I don't want to make them non-optional just by declaration (!), to avoid runtime problems, that could be solved by them compiler

Variable declaration:

    var dataSource : MyDataSource?
    var cellAndHeaderManager: MyCellAndHeaderManager?

Typical method start:

    guard let cellAndHeaderManager = cellAndHeaderManager else {return UICollectionReusableView()}
    let header = cellAndHeaderManager.headerForSection(collectionView, indexPath: indexPath)
    guard let dataSource = dataSource else {return header}

Initialization:

     if let newController = storyboard?.instantiateViewControllerWithIdentifier("MyViewController") as? MyCollectionViewController {
            newController.dataSource = dataSource
            newController = cellAndHeaderManager
        }

What I'd like to do:

newController = MyCollectionViewController(dataSource, cellAndHeaderManager)

Any ideas?

4
  • Why not to initialize them as in var dataSource : MyDataSource = MyDataSource() to avoid optionals Commented Sep 28, 2015 at 8:54
  • Because it's a generic view controller which gets its specific behavior via different implementations of data sources and cell managers, i.e. every instance of a view controller gets its own data source/cell manger, which are instances of different classes. Commented Sep 28, 2015 at 9:50
  • You can not instantiate view controller from Storyboard with initializer because there is no suitable initializer in UIViewController. So the only option is class func as in my answer. Commented Sep 28, 2015 at 10:06
  • Someone down-voted this question as well as @mixel 's good answer without leaving a comment... This is very helpful! Commented Sep 28, 2015 at 10:54

1 Answer 1

2

You can write class func for your view controller:

class MyViewController {
    // ...
    class func instantiate(dataSource: MyDataSource, cellAndHeaderManager: MyCellAndHeaderManager) -> MyViewController {
        let vc = UIStoryboard(name: "Storyboard", bundle: nil).instantiateViewControllerWithIdentifier("MyViewController") as! MyViewController
        vc.dataSource = dataSource
        vc.cellAndHeaderManager = cellAndHeaderManager
        return vc
    }
}

So you can instantiate it with:

let vc = MyViewController.instantiate(dataSource: dataSource, cellAndHeaderManager: cellAndHeaderManager)

You can not instantiate view controller from Storyboard with initializer because there is no suitable initializer in UIViewController.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. Looks like a suitable solution. Together with private override of public initializers, that should do the job.
What about initializers , xcode giving error that no initializers
@SudhanshuGupta Implement them developer.apple.com/documentation/uikit/uiviewcontroller#topics. Just call super.init(...) in their body.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.