Reputation: 641
This is probably the silliest question to date - but I am having problems with initializing a subclassed view controller with a customized required coder initializer (specifically using the QRCoder pod; and to not expose code I don't own, I'll be using example classes in my case).
Here are the essentials.
class A: UIViewController {
public var name = String()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
name = "This is a test"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Then we have...
class B: A {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
name = "What what"
}
}
If I attempt to generate a new view controller of B in say, a button tap on C...
class C: UIViewController {
let button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
button(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)}
}
@objc func buttonTapped(_ sender: Any) {
let viewOfB = B()
present(viewOfB, animated: true)
}
}
It doesn't compile = because my call of let viewOfB = B()
is missing the coder
parameter.
The problem is, if I add a coder
parameter, what in the world do I put in there? I've tried filling it with just an empty(?) NSCoder, like so
let emptyCoder = NSCoder()
let viewOfB = B(coder: emptyCoder)
But then upon a run and button tap, I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -decodeObjectForKey: cannot be sent to an abstract object of class NSCoder: Create a concrete instance!'
I've tried adding a convenience initializer to A (where I have to run a self.init
instead of super.init
for some reason), but doing that gives me an EXC_BAD_ACCESS_ERROR
.
What exactly do I need to provide to an init:(coder)
instance to be able to... get things going?
Upvotes: 0
Views: 566
Reputation: 535304
What exactly do I need to provide to an
init:(coder)
instance to be able to... get things going?
Nothing. Stop thinking about init(coder:)
.
Here's the actual problem. When you say B()
, you are calling init()
. But there is no init()
, because where would it come from? You didn't implement any such method in A. And it is not inherited from the superclass (UIViewController), because you effectively destroyed all inherited initializers when you implemented init(coder:)
.
So if you want to say B()
, you must implement init()
explicitly in A, yourself, like this:
class A: UIViewController {
public var name = String()
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
name = "This is a test"
}
}
Upvotes: 1