Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom init for UIViewController in Swift with interface setup in storyboard

I'm having issue for writing custom init for subclass of UIViewController, basically I want to pass the dependency through the init method for viewController rather than setting property directly like viewControllerB.property = value

So I made a custom init for my viewController and call super designated init

init(meme: Meme?) {         self.meme = meme         super.init(nibName: nil, bundle: nil)     } 

The view controller interface resides in storyboard, I've also make the interface for custom class to be my view controller. And Swift requires to call this init method even if you are not doing anything within this method. Otherwise the compiler will complain...

required init?(coder aDecoder: NSCoder) {         super.init(coder: aDecoder)     } 

The problem is when I try to call my custom init with MyViewController(meme: meme) it doesn't init properties in my viewController at all...

I was trying to debug, I found in my viewController, init(coder aDecoder: NSCoder) get called first, then my custom init get called later. However these two init method return different self memory addresses.

I'm suspecting something wrong with the init for my viewController, and it will always return self with the init?(coder aDecoder: NSCoder), which, has no implementation.

Does anyone know how to make custom init for your viewController correctly ? Note: my viewController's interface is set up in storyboard

here is my viewController code:

class MemeDetailVC : UIViewController {      var meme : Meme!      @IBOutlet weak var editedImage: UIImageView!      // TODO: incorrect init     init(meme: Meme?) {         self.meme = meme         super.init(nibName: nil, bundle: nil)     }      required init?(coder aDecoder: NSCoder) {         super.init(coder: aDecoder)     }      override func viewDidLoad() {         /// setup nav title         title = "Detail Meme"          super.viewDidLoad()     }      override func viewWillAppear(animated: Bool) {         super.viewWillAppear(animated)         editedImage = UIImageView(image: meme.editedImage)     }  } 
like image 813
Pigfly Avatar asked Feb 10 '16 12:02

Pigfly


People also ask

How do I instantiate a view controller from storyboard?

In the Storyboard, select the view controller that you want to instantiate in code. Make sure the yellow circle is highlighted, and click on the Identity Inspector. Set the custom class as well as the field called "Storyboard ID". You can use the class name as the Storyboard ID.

How do I initialize a view controller in Swift?

Open ImageViewController. swift and add an initializer with name init(coder:image:) . The initializer accepts an NSCoder instance as its first argument and an Image object as its second argument.

What is UIViewController Swift?

The UIViewController class defines the shared behavior that's common to all view controllers. You rarely create instances of the UIViewController class directly. Instead, you subclass UIViewController and add the methods and properties needed to manage the view controller's view hierarchy.

What is nibName in Swift?

The name of the view controller's nib file, if one was specified.


2 Answers

As it was specified in one of the answers above you can not use both and custom init method and storyboard.

But you still can use a static method to instantiate ViewController from a storyboard and perform additional setup on it.

It will look like this:

class MemeDetailVC : UIViewController {          var meme : Meme!          static func makeMemeDetailVC(meme: Meme) -> MemeDetailVC {         let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "IdentifierOfYouViewController") as! MemeDetailVC                  newViewController.meme = meme                  return newViewController     } } 

Don't forget to specify IdentifierOfYouViewController as view controller identifier in your storyboard. You may also need to change the name of the storyboard in the code above.

like image 192
Alexander Grushevoy Avatar answered Oct 05 '22 21:10

Alexander Grushevoy


You can't use a custom initializer when you initialize from a Storyboard, using init?(coder aDecoder: NSCoder) is how Apple designed the storyboard to initialize a controller. However, there are ways to send data to a UIViewController.

Your view controller's name has detail in it, so I suppose that you get there from a different controller. In this case you can use the prepareForSegue method to send data to the detail (This is Swift 3):

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {     if segue.identifier == "identifier" {         if let controller = segue.destinationViewController as? MemeDetailVC {             controller.meme = "Meme"         }     } } 

I just used a property of type String instead of Meme for testing purposes. Also, make sure that you pass in the correct segue identifier ("identifier" was just a placeholder).

like image 27
Caleb Kleveter Avatar answered Oct 05 '22 22:10

Caleb Kleveter