Instantiate class with NSCODER - swift

I face a problem when trying to instantiate a class(SettingsView) that uses NSCoder, in another class(Swipe). The SettingsView class is already an instance of an objective -C class(FXBlurView)
I get the following error "Missing argument for parameter 'coder' in call". I realized that I have to call some parameters, but I do not know which.
SettingsView :
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.tintColor = UIColor.clearColor()
}
Swipe :
var settings = SettingsView()//error occurs here
i already tried to use
init () {
super.init (tint: ...)
}
But it seems to be not functionnal.

Ok , i succeed to do it just by adding :
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
var settings = SettingsView(coder: aDecoder)
}
into my "Swipe" view controller.

Related

Swift Call an override method by subclass from superclass

I have two classes in swift. I have an action method that I want to override in many subclasses that will do a different action. I wanted this to sort of function like an abstract class in Java, where I could pass a bunch of different subclasses of a certain class, but they would be referred to from the superclass so that one method could be called for all of them even though they are different subclasses with different overridden versions of that one method. Here is what I mean.
class1: SKSpriteNode{
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func action(){ print("this should never be called") }
}
class2: class1 {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func action() {
self.physicsBody?.affectedByGravity = true
}
}
I would want to do something like this. A node with name someName would be defined as a class2 in the SKScene editor.
class GameScene...
let node = self.childNode(withName: "someName") as? class1
noe.action()
However, I never get the output I want. I always get the call of class1 even when I want it to be overridden as a class2 and turn on gravity for that node. I would want to call the action method for many subclasses of class1 no matter the subclass, so just changing the class1 method to do what I want will not work.
Thank you
EDIT: Here are my actual classes:
So I have some classes that are nodes that will be triggered when the user passes the trigger node. It has a stored value for the name of the target node that is then retrieved from the main SKScene, its parent. Then I want to have a specific TargetNode, DropNode that will make it fall from the sky, but I want to be able to trigger any subclass of TargetNode by calling the TriggerAction method, but it never seems to perform the code of the subclass, the DropNode, but instead always does nothing/ whatever code I put in the action method of the TargetNode class. It never overrides the method.
//SUPERCLASS:
import Foundation
class SKTargetNode: SKGlowNode {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func action(){
print("i don't want this to be called")
}
}
//SUBCLASS:
import Foundation
class SKDropNode: SKTargetNode {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func action() {
self.physicsBody?.affectedByGravity = true
}
}
//Just a class that triggers any TargetNode
import Foundation
import SpriteKit
class SKTriggerNode: SKSpriteNode {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func triggerAction(_ scene: GameScene){
let nodeName = self.userData?.value(forKey: "TargetNode") as? String ?? ""
let node = scene.childNode(withName: "//\(nodeName)") as? SKTargetNode
node?.action()
}
}

UIHostingController throws

I want to load from a UIViewController a SwiftUI based view that reads a json local to the bundle. The code and binding in a swiftUI only project works fine, when I leverage the UIHostingController I get an error for which I am seeking help to fix.
class ProgramsListVCHost : UIHostingController<ProgramsList>, Storyboarded {
weak var coordinator: MainCoordinator?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder, rootView: ProgramsList())
}
}
The code above crashes because I didn't pass what I should have to cause the init of the model.
super.init(coder: aDecoder, rootView: ProgramsList().environmentObject(ProgramUserData()))
However, if I do that the compiler demands that I cast the whole thing to the underlying class ProgramList (Cannot convert value of type 'some View' to expected argument type 'ProgramsList')
If I do apply the recommended fix, the code crashes with the error:
Could not cast value of type
'SwiftUI.ModifiedContent>>'
(0x7fff89d0ec68) to 'bikeit.ProgramsList' (0x110477328). 2019-11-15
14:36:26.049041-0500 bikeit[13658:8386085] Could not cast value of
type 'SwiftUI.ModifiedContent>>'
(0x7fff89d0ec68) to 'bikeit.ProgramsList' (0x110477328). (lldb)
I don't understand how to initialize the object that I must pass in order to make it work.
Of course, it is because your declared content UIHostingController<ProgramsList> is ProgramsList, so it is expected in initialiser, but you pass to it output of .environmentObject, which is SwiftUI.ModifiedContent, so types checking fails and you get compiler error.
It is not clear your needs, but possible solution could be as follows:
class ProgramsListVCHost : UIHostingController<AnyView>, Storyboarded {
weak var coordinator: MainCoordinator?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder, rootView: AnyView(ProgramsList().environmentObject(ProgramUserData())))
}
}
Update: found alternate
class ProgramsListVCHost : UIHostingController<ProgramsListVCHost.MyView>, Storyboarded {
// Internal view
struct MyView: View {
var body: some View {
ProgramsList().environmentObject(ProgramUserData())
}
}
weak var coordinator: MainCoordinator?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder, rootView: MyView())
}
}

problem with initializer: Property 'self.options' not initialized at super.init call

i'm using SwiftPageMenu from cocoapods. it used to work perfectly. but after i reinstall it by pod i keep getting this error
Thread 1: Fatal error: init(coder:) has not been implemented
i looked for some solution and mostly advised to change :
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
to :
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
but i get
Property 'self.options' not initialized at super.init call
options is initialized in other init functions:
public init(options: PageMenuOptions? = nil) {
self.options = options ?? DefaultPageMenuOption()
super.init(nibName: nil, bundle: nil)
}
public init?(coder: NSCoder, options: PageMenuOptions? = nil) {
self.options = options ?? DefaultPageMenuOption()
super.init(coder: coder)
}
i didn't really understand the problem can someone help me please.
here's the controller

Swift UIView subclass init failing

I created a UIView subclass:
class RA_Circle: UIView {
let elipseWidth:CGFloat
let elipseHeight:CGFloat
init(elipseWidth: CGFloat, elipseHeight:CGFloat) {
self.elipseWidth = elipseWidth
self.elipseHeight = elipseHeight
super.init(frame: CGRect.zero)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
But the compiler is giving me this error on the required init:
Property 'self.elipseWidth' not initialized at super.init call
I was following this SO Q&A:
How to properly init passed property in subclass of UIView?
In your class definition you're declaring your variable without any default values, and the required initializer is not providing any values before calling super init.
There are a number of ways to deal with this, here's a few...
One way is to provide default values in the property declarations:
var elipseWidth: CGFloat = 0.0
var elipseHeight: CGFloat = 0.0
The second is to make your properties optional:
var elipseWidth: CGFloat?
var elipseHeight: CGFloat?
A third is to provide default values in the required initializer:
required init?(coder aDecoder: NSCoder) {
elipseWidth = 14.0
elipseHeight = 14.0
super.init(coder: aDecoder)
}
You have to change the let variable declarations to var and optional. In this case, you would initialize them in awakeFromNib() or at some later time.

Correctly init NSCoder in sub class when init NSCoder is convenience method in base class in Swift

Here's my code:
import Foundation
class Person: NSObject, NSCoding {
var name: String
init(name: String) {
self.name = name
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(name, forKey: "name")
}
required convenience init?(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObjectForKey("name") as! String
self.init(name: name)
}
}
class Martin: Person {
init() {
self.init(name: "Martin")
}
required convenience init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
let p = Martin()
print(p.name)
For some reason I always end-up in a catch-22 situation, the only way i see making this work is to explicitly initialize all properties in required convenience init?(coder aDecoder: NSCoder) to able to remove the convenience and do super.init(coder: aDecoder) in Martin
I read about the init rules in Swift, still don't understand why Martin can't inherit the convenience init from Person in this case.
Because the rules state that
A designated initializer must call a designated initializer from its immediate superclass.
A convenience initializer must call another initializer from the same class.
A convenience initializer must ultimately call a designated initializer.