157

I decided to continue my remaining project with Swift. When I add the custom class (subclass of UIViewcontroller) to my storyboard view controller and load the project, the app crashes suddenly with the following error:

fatal error: use of unimplemented initializer 'init(coder:)' for class

This is a code:

import UIKit

class TestViewController: UIViewController {

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    override func viewDidLoad() {
        super.viewDidLoad()
              // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
}

Please suggest something

Lukas Würzburger
  • 6,207
  • 7
  • 35
  • 68
Pratik Bhiyani
  • 2,489
  • 3
  • 15
  • 26

6 Answers6

210

Issue

This is caused by the absence of the initializer init?(coder aDecoder: NSCoder) on the target UIViewController. That method is required because instantiating a UIViewController from a UIStoryboard calls it.

To see how we initialize a UIViewController from a UIStoryboard, please take a look here

Why is this not a problem with Objective-C?

Because Objective-C automatically inherits all the required UIViewController initializers.

Why doesn't Swift automatically inherit the initializers?

Swift by default does not inherit the initializers due to safety. But it will inherit all the initializers from the superclass if all the properties have a value (or optional) and the subclass has not defined any designated initializers.


Solution

1. First method

Manually implementing init?(coder aDecoder: NSCoder) on the target UIViewController

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

2. Second method

Removing init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) on your target UIViewController will inherit all of the required initializers from the superclass as Dave Wood pointed on his answer below


Community
  • 1
  • 1
E-Riddie
  • 14,052
  • 7
  • 47
  • 70
  • 4
    Thanks for this. Quick follow up... When you create the TableViewController file, Xcode already includes `init(style: UITableViewStyle) { super.init(style: style) // Custom initialization }` Why can we have *two* init functions? And any idea why Apple doesn't include the 2nd init by default? – Trevor McKendrick Jun 06 '14 at 07:55
  • This has nothing to do with iOS 7 or iOS 8. This is connected with the way Swift inherits intitializers! – Sulthan Jun 23 '14 at 08:57
  • public init(view: UIViewController, frame: CGRect) { self.viewController = view self.imageName = "" self.actionName = "" super.init(frame: frame) } – scrainie Sep 13 '15 at 10:10
  • The first method worked ! My dynamic table finally filled with dynamic cells!!! All because the line `fatalError( "init(coder:) has not been implemented")` halted my app. – Jose Manuel Abarca Rodríguez Jan 15 '16 at 22:22
26

Another option besides @3r1d's is to instead remove the following init method from your class:

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // Custom initialization
}

Including that init method, prevents the sub class from inheriting the init(coder aDecoder: NSCoder!) from its super class. By not including it, your class will inherit both.

Note: See WWDC 2014 Session 403 "Intermediate Swift" at about the 33:50 mark for more details.

Dave Wood
  • 12,322
  • 1
  • 51
  • 63
  • Thanks for pointing out the explanation on Session 403. But if the child class only has convenience initializers then it will inherite the super class initializers right? – jamiltz Jun 09 '14 at 18:20
  • 1
    Yes. You only prevent the super class init methods from being inherited if you provide your own designated init methods (those that call super inits). Then you have to specify which of the super inits to support by adding them to your class and just calling the super version (as in @3r1d's answer) – Dave Wood Jun 09 '14 at 18:55
  • Having only convenience init() without (designated) init() in your child class will cause compile error. That's because convenience init() function must call self.init() inside function definition. – Ohmy Oct 15 '16 at 21:38
  • @narumolPug That's incorrect. You do not need to include designated `init` methods. Your child class will inherit them from the super class. You can still call `self.init()` which will execute the super version. – Dave Wood Oct 15 '16 at 22:47
  • The exact moment of the video can be found here https://youtu.be/W1s9ZjDkSN0?t=2030 – Honey Jan 16 '17 at 19:44
10

For people having the same issue with swift UICollectionViewCells, add the code that @3r1d suggested to your custom UICollectionViewCell class and not to the View Controller:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}
E-Riddie
  • 14,052
  • 7
  • 47
  • 70
Nick Yap
  • 857
  • 1
  • 10
  • 13
  • which UICollectionViewCell are you referring to? Init with coder is the way to init the viewController – E-Riddie Jun 06 '14 at 19:08
  • Not in this example but in case anyone has a problem with it (I did)... if you try to use a UICollectionViewController, in your custom cell .swift file you need to put init with coder. – Nick Yap Jun 06 '14 at 21:58
  • 2
    You need to add this code everytime you use this way of instantiation http://stackoverflow.com/questions/24035984/instantiate-a-viewcontroller-in-swift/24036227#24036227 – E-Riddie Jun 06 '14 at 22:01
3

For those needing the code in Swift:

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

[Edit] This was for an older version of Swift. Possibly doesn't work anymore.

Mauricio
  • 2,140
  • 5
  • 24
  • 52
3

I had this problem in a programmatic collectionView cell and even though the op is asking about a vc I still landed on this question when searching for an answer. For me the issue was I did have

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

implemented so the top answer didn't work. What I didn't have in the cell was the initializer:

// my programmatic cell was missing this
override init(frame: CGRect) {
    super.init(frame: frame)
}

Once I added it the error went away

Lukas Würzburger
  • 6,207
  • 7
  • 35
  • 68
Lance Samaria
  • 11,429
  • 8
  • 67
  • 159
1

Rather than adding some methods for making internal mechanism work fine, i would go with defining my attributes as @lazy and initialise them right in the class scope.

hasancan85
  • 11
  • 2