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
iOS - Could Not Open Obj File When Convert Mdlasset to Mdlmesh
How to Get an Array of Days Between Two Dates in Swift
Swift 3 Cocoa: Use Quicklook to Preview File in Os X
Prefix(_ Maxlength:) Is Type-Erased When Used with a Struct That Conforms to Lazysequenceprotocol
Redirect Process Stdout to Apple System Log Facility in Swift
How to Import Zbar Framework in Swift Project
Swift's Decimal Precision Issue
Difference Between Orientation and Rotation in Scnnode
Changing Associated Value of Enum Swift
Arkit: How to Tell If User's Face Is Parallel to Camera
Prepareforsegue from a UIbutton in a Custom Prototype Cell
How to Programmatically Scroll iOS Wkwebview, Swift 4
Allow Siri Remote Menu Button When Play/Pause Button Is Overridden
Swift Protocol That Is Using an Enum with Generic Associated Type
Uipickerviewdelegate Xcode 8 Swift 3