Must Call a Designated Initializer of The Superclass 'Day' Error

Must call a designated initializer of the superclass 'Day' error

The problem is caused by calling self.init in init?(coder of Day. That call makes the initializer convenient and the subclass is not able to fulfill the requirements to call a designated initializer.

The solution is to initialize the properties directly

required init?(coder aDecoder: NSCoder) {
self.dayName = aDecoder.decodeObject(forKey: PropertyKey.dayName) as! String
self.subjects = aDecoder.decodeObject(forKey: PropertyKey.subjects) as? [Subject]
}

By the way: You are encoding always dayName as a non-optional string so it never can be nil when being decoded. The guard is useless.

In the subclass you might need to add code to en-/decode the properties of the subclass and call super to consider also the properties of the superclass.

class Subject: Day {
var subjectName: String
var startsAt: String?

init(dayName: String, subjectName: String) {
self.subjectName = subjectName
super.init(dayName: dayName)
}

override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(subjectName, forKey: "subjectName")
aCoder.encode(startsAt, forKey: "startsAt")
}

required init?(coder aDecoder: NSCoder) {
subjectName = aDecoder.decodeObject(forKey: "subjectName") as! String
startsAt = aDecoder.decodeObject(forKey: "startsAt") as? String
super.init(coder: aDecoder)
}
}

The question for the sense of using a subclass as property in its superclass is another story /p>

Build error: Must call a designated initializer of the superclass 'UIControl'

Your init(action: @escaping () -> Void) is a designated initializer, and designated initializers are not allowed to call convenience initializers from the base class, they must call another designater initializer.

This is enforced here:

Rule 1

    A designated initializer must call a designated initializer from its immediate superclass.

This the base initializer in discussion:

/// Initializes the control and adds primaryAction for the UIControlEventPrimaryActionTriggered control event. Subclasses of UIControl may alter or add behaviors around the usage of primaryAction, see subclass documentation of this initializer for additional information.
@available(iOS 14.0, *)
public convenience init(frame: CGRect, primaryAction: UIAction?)

So, you need to convert your initializer to a convenience one, and have to call with self instead of super the other intializers (again, due to the initializer rules):

class Control: UIControl {

var action: (() -> Void)?

convenience init(action: @escaping () -> Void) {
if #available(iOS 14.0, *) {
let primaryAction = UIAction(handler: { _ in action() })
self.init(frame: .zero, primaryAction: primaryAction)
} else {
self.init(frame: .zero)
}
self.action = action
}

override init(frame: CGRect) {
super.init(frame: frame)
}

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

Alternatively, as adding a new subclass of UIControl will force all your custom classes to derive from that one, you could extend the UIControl with a new convenience initializer:

extension UIControl {
// associated object dance to allow "stored" properties
// in extensions and protocols over NSObject subclasses
private static var primaryActionKey: UInt8 = 0
private var primaryAction: (() -> Void)? {
get {
objc_getAssociatedObject(self, &Self.primaryActionKey) as? () -> Void
}
set {
objc_setAssociatedObject(self, &Self.primaryActionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

convenience init(action: @escaping () -> Void) {
if #available(iOS 14.0, *) {
let primaryAction = UIAction(handler: { _ in action() })
self.init(frame: .zero, primaryAction: primaryAction)
} else {
self.init(frame: .zero)
self.primaryAction = action
addTarget(self, action: #selector(onPrimaryAction), for: .primaryActionTriggered)
}
}

@objc private func onPrimaryAction() {
primaryAction?()
}
}

Swift: Must call a designated initializer of the superclass error even though code is doing so

The problem there is that you are also trying to access your PreviewNode properties before calling self.init()

Try like this:

Xcode 8 GM • Swift 3

class PreviewNode: SCNNode {
let previewNodeColor: UIColor = .red
let size: CGFloat = 1
let chamferRadius: CGFloat = 0
convenience override init() {
self.init()
let previewBox = SCNBox(width: size, height: size, length: size, chamferRadius: chamferRadius)
previewBox.firstMaterial?.diffuse.contents = previewNodeColor
previewBox.firstMaterial?.transparency = 0.2
previewBox.firstMaterial?.specular.contents = UIColor.white
self.geometry = previewBox
}
}

Must call a designated initializer of the superclass 'UITableViewController'

You are calling super.init() which is unsupported on the UITableViewController superclass, change that to initWithStyle

Must call a designated initializer of the superclass 'UITextView'

As per document for UITextView

 // Create a new text view with the specified text container (can be nil) - this is the new designated initializer for this class
@available(iOS 7.0, *)
public init(frame: CGRect, textContainer: NSTextContainer?)

What is the designated initializer for a MKPolygon in Swift4?

The real answer to this specific issue is that you can subclass them, but your subclass must not require using its own initializer. Instead you must continue to use the convenience initializers in the super classes. Those initializers must be called otherwise MapKit won't render the data.

For example with MKPolyline:

let mine = MyPolyline(coordinates: c, count c.count)
mine.other = ...
mine.foobar = ...

class MyPolyline: MKPolyline {
var foobar: [Int] = []
var other: [Double] = []
}

You might think you could add your own initializer and simply override methods like points and pointCount (similar to what you would for NSString for example), but MapKit still won't render the data unless its own "convenience"-marked initializers were called.

Must call a designated initializer of the superclass 'UICollectionView'

You need to call designated initializer init(frame:collectionViewLayout:) of UICollectionView.

init(collectionView: UICollectionView, frame: CGRect) {        
self.collectionView = collectionView
//Setup collectionView layout here and pass with init
let layout = UICollectionViewLayout()
super.init(frame: frame, collectionViewLayout: layout)
}


Related Topics



Leave a reply



Submit