Swift 1.2: override init gives error [duplicate] - ios

So I've just upgraded to Xcode 6.3 Beta 3 and a lot of error(s) are appearing relating to the following:
Initializer does not override a designated initializer from its superclass.
override init() {
super.init()
}
For example this is a UIButton class:
class CustomButton: UIButton {
var target: AnyObject!
var selector: Selector!
var action: (() -> Void)!
override init() { // Initializer does not override a designated initializer from its superclass
super.init() // Must call a designated initializer of the superclass 'UIButton'
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
This is one of my UIViewController classes:
class CustomAlertView: UIViewController {
required init(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
required override init() { // Initializer does not override a designated initializer from its superclass
super.init() // Must call a designated initializer of the superclass 'UIViewController'
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}

My solution is a quick fix, but I think is easier than what Apple purposes on the the Release Notes. For more information search for 19775924 http://adcdownload.apple.com//Developer_Tools/Xcode_6.3_beta_3/Xcode_6.3_beta_3_Release_Notes.pdf here. What Apple says is that you create an Objective-C file and extend it (having to add it to the header files and all) and it's on "Known Issues in Xcode 6.3 beta 3", so I think is easy to do what I did:
This is how I fixed it for UIButton:
class CustomButton : UIButton {
init() {
super.init(frame: CGRectZero)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And this is one of my ViewControllers (remove public if not needed):
public class GenericViewController: UIViewController {
public init() {
super.init(nibName: nil, bundle: nil)
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I don't use IB so I also have UIView, because I do separate the view from the viewController (remove public if not needed):
public class GenericMenuView: UIView {
public init() {
super.init(frame: CGRectZero)
}
public required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I need this specially in views because I have a setupViews method that I override in all subclasses that is called on the init. And using AutoLayout I don't need any frames (so I don't override the init with the frame parameter).
So it seems you have to drop override. Oh! and be sure to not call self.init() or the class is never initialized (and it crashes after some internal timeout).

As per Apple documentation here, what you are overriding is a convenience initializer. So for your initializer to work, you will have to change the method to
override convenience init() {
super.init()
}
You can either do that, or remove the initializer if you are not really using it except for calling the superclass initializer.

I recently figured this out and I'd like to explain what the problem was. Originally answered on the Apple Developer forums.
It seems Swift has changed the strategy for initializer dependency checking or for imporing initializers.
Now if your initializers' are as shown, one way to deal with both Xcode 6.3 Beta 2 and Beta 3 is to remove all initializer definitions:
class CustomButton: UIButton {
var target: AnyObject!
var selector: Selector!
var action: (() -> Void)!
}
class CustomAlertView: UIViewController {
}
Without defining any designated initializers, classes inherit all initializers of their superclasses.
A pretty easy fix, but a big gotcha that had me stumped for a while.

I think this is way easier than it seems.
For an SKSpriteNode, I was doing this:
override init() {
let texture = SKTexture(imageNamed: "bgTile")
super.init(texture: texture, color: nil, size: texture.size())
}
The problem is init() is not the designated initializer for SKSpriteNode. So I just changed it to:
override init(texture: SKTexture!, color: UIColor!, size: CGSize) {
let texture = SKTexture(imageNamed: "bgTile")
super.init(texture: texture, color: nil, size: texture.size())
}
Now it works fine.

Solution for Error : Override init(coder aDecoder: NSCoder!) not working like expected - Swift
This works for me , Try this, Note: u must awake nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialisation code
}

Related

Subclassing view controller in Swift

I want to subclass UIViewController and override init methods. I ended up with:
class BaseViewController : UIViewController, BaseViewCreating, ModelBinding {
var viewModel : Any!
convenience init(viewModel: Any){
self.init()
self.createUserInterface()
self.createConstraints()
self.viewModel = viewModel
self.bindWithModel(model: self.viewModel)
}
convenience init() {
self.init()
self.createUserInterface()
self.createConstraints()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createUserInterface() {
}
func createConstraints() {
}
func bindWithModel(model: Any) {
}
func update(){
self.bindWithModel(model: self.viewModel)
}
}
However, when app launch, it throw an error - EXC_BAD_ACCESS on line self.init() in method convenience init().
How to fix that?
Thats because you are calling init recursively with self.init inside
convenience init() {
self.init()
}
Every single Convenience init should call designated initializer of the class. UIViewController has
public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
public init?(coder aDecoder: NSCoder)
as designated initializer. So you should call any one of them in your init() or override them in your ViewController and later call self.init(nibName or self.init(coder
As it cant find designated initializer by name init() it is calling recursively your init hence crashing
EDIT:
Just in case anybody has a doubt that self.init will not result in loop because thats one of the way how a Convenience initializer can call designated initializer. I have explained in detail why it results in infinite loop in this specific case in comment below :) attaching a proof here
This is the stack trace when I ran OP code. Clearly shows infinite recursive call
If anyone face same problem i paste answer here:
You should add this to your subclas:
init() {
super.init(nibName:nil, bundle:nil)
self.createUserInterface()
self.createConstraints()
}

Force user to use custom init method for the initialization

I am creating a UIView subclass with the intention to force users to my required init method than the default one.
So for that, I have created a convenience method for this.
#available(*, unavailable, message: "init is unavailable.")
public override init(frame: CGRect) {
super.init(frame: frame)
}
required
convenience public init(withSomeParameters myParam:Type) {
self.init(frame: CGRect.zero)
//Doing something nice!
}
This works! However, when I try to init it's showing me two ways to initialize it. How to force the user to make use of custom init method?
You can make it private , so user must need to init Test class with withSomeParameters
class Test:UIView {
private override init(frame: CGRect) {
super.init(frame: frame)
}
convenience public init(withSomeParameters myParam:Type) {
self.init(frame: CGRect.zero)
//Doing something nice!
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Maybe you need to mark the coder initialiser as unavailable as well:
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Plus: remove the convenience from your initialiser, and call supers init(frame:)
public init(withSomeParameters myParam:Type) {
super.init(frame: .zero)
//Doing something nice!
}
As another example, here is some base UIView subclass I use in a lot of my projects that don't utilise storyboards:
class MXView: UIView {
init() {
super.init(frame: .zero)
}
// Storyboards are incompatible with truth and beauty.
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Subclass:
class CustomView: MXView {
init(someParameters params: Type) {
// Phase 1: store ivars.
super.init()
// Phase 2: Do something nice.
}
If you do it like that, users of CustomView will be forced to use init(someParamters:). init(frame:) is shadowed because init(someParameters:) is a non-convenience init.

Initializer does not override a designated initializer from its superclass, Swift 2.0

Working thru this appcoder tutorial building a text to speech app tutorial and run into a swift 1.2-> swift 2.0 feature.
The demo project has a class in it... which the Xcode 7.1.1 under IOS 10.11.1 doesn't like, giving me the error. "initialiser doesn't override the designated initialiser from its super class" on the override init() statement, followed by the error "Must call the designated initialiser of the superclass UISlider".
Ok, Rather new to Swift; and quite where I start to fix this is a little lost on me.
class CustomSlider: UISlider {
var sliderIdentifier: Int!
override init() { <--- error here
super.init() <--- error here
sliderIdentifier = 0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sliderIdentifier = 0
}
}
What should this code snippet say?
Since UISlider doesn't define or inherit init() as a designated initializer, you can't call it from your subclass init.
class CustomSlider: UISlider {
var sliderIdentifier: Int!
required init() {
super.init(frame: CGRect.zero)
sliderIdentifier = 0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sliderIdentifier = 0
}
}
In this case, you could factor out the initialization of sliderIdentifier and just inherit all of UISliders initializers:
class CustomSlider: UISlider {
var sliderIdentifier: Int! = 0
}
For more information, read the section titled “Designated Initializers and Convenience Initializers” in The Swift Programming Language.

Initializer does not override a designated initializer from its superclass

So I've just upgraded to Xcode 6.3 Beta 3 and a lot of error(s) are appearing relating to the following:
Initializer does not override a designated initializer from its superclass.
override init() {
super.init()
}
For example this is a UIButton class:
class CustomButton: UIButton {
var target: AnyObject!
var selector: Selector!
var action: (() -> Void)!
override init() { // Initializer does not override a designated initializer from its superclass
super.init() // Must call a designated initializer of the superclass 'UIButton'
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
This is one of my UIViewController classes:
class CustomAlertView: UIViewController {
required init(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
required override init() { // Initializer does not override a designated initializer from its superclass
super.init() // Must call a designated initializer of the superclass 'UIViewController'
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
My solution is a quick fix, but I think is easier than what Apple purposes on the the Release Notes. For more information search for 19775924 http://adcdownload.apple.com//Developer_Tools/Xcode_6.3_beta_3/Xcode_6.3_beta_3_Release_Notes.pdf here. What Apple says is that you create an Objective-C file and extend it (having to add it to the header files and all) and it's on "Known Issues in Xcode 6.3 beta 3", so I think is easy to do what I did:
This is how I fixed it for UIButton:
class CustomButton : UIButton {
init() {
super.init(frame: CGRectZero)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And this is one of my ViewControllers (remove public if not needed):
public class GenericViewController: UIViewController {
public init() {
super.init(nibName: nil, bundle: nil)
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I don't use IB so I also have UIView, because I do separate the view from the viewController (remove public if not needed):
public class GenericMenuView: UIView {
public init() {
super.init(frame: CGRectZero)
}
public required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I need this specially in views because I have a setupViews method that I override in all subclasses that is called on the init. And using AutoLayout I don't need any frames (so I don't override the init with the frame parameter).
So it seems you have to drop override. Oh! and be sure to not call self.init() or the class is never initialized (and it crashes after some internal timeout).
As per Apple documentation here, what you are overriding is a convenience initializer. So for your initializer to work, you will have to change the method to
override convenience init() {
super.init()
}
You can either do that, or remove the initializer if you are not really using it except for calling the superclass initializer.
I recently figured this out and I'd like to explain what the problem was. Originally answered on the Apple Developer forums.
It seems Swift has changed the strategy for initializer dependency checking or for imporing initializers.
Now if your initializers' are as shown, one way to deal with both Xcode 6.3 Beta 2 and Beta 3 is to remove all initializer definitions:
class CustomButton: UIButton {
var target: AnyObject!
var selector: Selector!
var action: (() -> Void)!
}
class CustomAlertView: UIViewController {
}
Without defining any designated initializers, classes inherit all initializers of their superclasses.
A pretty easy fix, but a big gotcha that had me stumped for a while.
I think this is way easier than it seems.
For an SKSpriteNode, I was doing this:
override init() {
let texture = SKTexture(imageNamed: "bgTile")
super.init(texture: texture, color: nil, size: texture.size())
}
The problem is init() is not the designated initializer for SKSpriteNode. So I just changed it to:
override init(texture: SKTexture!, color: UIColor!, size: CGSize) {
let texture = SKTexture(imageNamed: "bgTile")
super.init(texture: texture, color: nil, size: texture.size())
}
Now it works fine.
Solution for Error : Override init(coder aDecoder: NSCoder!) not working like expected - Swift
This works for me , Try this, Note: u must awake nib
override func awakeFromNib() {
super.awakeFromNib()
// Initialisation code
}

ios Swift fatal error: use of unimplemented initializer 'init()'

I've been trying very hard, have looked up every similar question pertaining to this issue on StackOverflow and trying them to no avail.
class TimeLineTableViewController:
UITableViewController,
UIImagePickerControllerDelegate,
UINavigationControllerDelegate {
var timelineData = [PFObject]()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
self.loadData()
}
#IBAction func loadData(){
timelineData.removeAll(keepCapacity: false)
var findTimelineData:PFQuery = PFQuery(className:"timelineMessages")
findTimelineData.findObjectsInBackgroundWithBlock { (objects:[AnyObject]! , error:NSError!) -> Void in
if error == nil {
self.timelineData = objects.reverse() as [PFObject]
//let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
// self.timelineData = array as NSMutableArray
self.tableView.reloadData()
}
}
}
override func viewDidAppear(animated: Bool) {
var footerView:UIView = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
self.tableView.tableFooterView = footerView
var logoutButton:UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
logoutButton.frame = CGRectMake(20, 10, 50, 20)
logoutButton.setTitle("Logout", forState: UIControlState.Normal)
logoutButton.addTarget(self, action:"logout:", forControlEvents: UIControlEvents.TouchUpInside)
footerView.addSubview(logoutButton)
}
To clarify, timelineTableViewController has one class that inherits, MessageTableCell. It's also part of a project that I've integrated into Objective-C code, so it's a combination of both Swift and ObjC. I've run both projects (the swift one and the ObjC one) independently and they work fine; it's only when I try to run it together do they mess up. Any suggestions? I'm at an utter loss for this.
“Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default.”
Automatic Initializer Inheritance
Rule 1:
If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.
Rule 2:
If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/tw/jEUH0.l
Since you have override the init(coder aDecoder: NSCoder), TimeLineTableViewController won't have the init() initiailzer.
You can provide an implementation of all of its superclass designated initialisers like this
override init() {
super.init()
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
, or just delete the implementation of init(coder aDecoder: NSCoder).

Resources