Swift Error in inheritance init class - ios

I have an error when un want init my B object.
My error is : Use of 'self' in property access 'name' before super.init initializes self
class A {
let name = "myName";
}
class B:A {
let point: ObjectWithName;
init() {
self.point = ObjectWithName(name); // error here
super.init();
}
}
Thanks for your help !

The problem is that you are accessing name which is declared in the superclass. But the superclass has not been initialized yet (it will after super.init()).
So it's a logic problem.
Solution #1
You can declare point as lazy, this way it will be executed after the whole init process has been completed, unless you call it before.
struct ObjectWithName {
let name: String
}
class A {
let name = "myName";
}
class B: A {
lazy var point: ObjectWithName = { ObjectWithName(name:self.name) }()
}
Solution #2
Inside A you can define name as static
class A {
static let name = "myName";
}
class B:A {
let point: ObjectWithName;
override init() {
self.point = ObjectWithName(name: B.name)
super.init();
}
}

Related

(MVVM) Cannot use instance member 'model' within property initializer; property initializers run before 'self' is available

I want access to SampleMoel's 'head' at ViewModel
How to fix this error?
this is MVVM(not Use combine, RxSwift ... only use Uikit)
SampleViewModel.swift
class SampleViewModel {
var model: SampleModel?
let changeData = Observer(model?.head) //Line error
init() {
self.model = SampleModel()
}
func changeLabel(_ tf: String) {
self.changeData.value = tf
}
}
SampleModel.swift
struct SampleModel {
var head = "initValue"
}
Modify your implementation as follows:
class SampleViewModel {
private let model: SampleModel
let changeData: Observer<String>
init(model: SampleModel) {
self.model = model
changeData = Observer(model.head)
}
func changeLabel(_ tf: String) {
self.changeData.value = tf
}
}

Is there any way to create an instance for current class type dynamically?

Assume that I have more than 10 classes, for example: class1, class2, class3, .. etc and each class has own functions.
My question is, since I have to create an instance for each class to use its functions, can I create an instance variable dynamically and assign class type rather than to specific the type manually?
I mean something like this:
class class1 {
static var instance = self
// or
static var instance :type(of:self) {
get {
return type(of:self)
}
}
}
/* instance type will be "class1", through "instance" I can access to class public functions */
Of course I tried these ideas but none of them worked.
Is there any way to do it?
UPDATE :
class Country {
static var instance = Country()
func do_something1 () { // do soething
}
func do_something2 () { // do soething
}
func do_something3 () { // do soething
}
func do_something4 () { // do soething
}
func do_somethingN () { // do soething
}
}
I want make instance got it type dynamically based on class that exist in rather then specific type manually
You can get the class by providing class name and then you can init.
func classFromString(className: String) -> AnyClass! {
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
let class1: AnyClass = NSClassFromString("\(namespace).\(className)")!;
return class1;
}

DidSet not working in init function swift 3

I have already seen
Is it possible to allow didSet to be called during initialization in Swift?
for me it is not working..
I am working in project where I have created class below
protocol FileManagerHelper {
var fileName:String {get}
var fileCategory:FileCategory {get set}
var isFileExitsAtPath:Bool {get}
var filePath:String {get}
var fileType:FileTypes {get set}
}
class FileManager:FileManagerHelper {
// Other property
//STORED PROPERY INIT WHEN OBJECT WILL CREATED WITH FileCategory OBJECT
var fileCategory:FileCategory {
didSet {
switch fileCategory {
case .XYZ:
print("Test")
... other cases
}
}
required init(fileCategory:FileCategory,fileType:FileTypes = .Image) {
self.fileCategory = fileCategory
self.path = self.folderPath + self.fileName
}
}
did set method is not calling of fileCategory
NOTE: I don't want to give default value , I want to pass it runtime from init method
Tries
1) defer
use of self in method called $defer before all stored property are initialised
2) Create custom method that will assign that value and call it from init
private func setCategory(with category:FileCategory) {
self.fileCategory = category
}
Use of method call setCategory before stored property ...
I know that all stored property should be initialised before instance created. Till that instance will not been created so i won't call methods (using self) may be that why above solution not working
Please help me if any one have idea
For me, using the defer is better readable.
import Foundation
class A {
var b: String {
didSet {
print("didSet called with value: \(b)")
}
}
init(x: String) {
self.b = x
defer { self.b = x }
}
}
let a = A(x: "It's Working!") // didSet called with value: It's Working!
print(a.b) // It's Working
One way to solve this is to extract the didSet logic into a separate method and call this method from both didSet and init:
class FileManager: FileManagerHelper {
var fileCategory:FileCategory {
didSet {
didSetFileCategory()
}
}
required init(fileCategory:FileCategory,fileType:FileTypes = .Image) {
self.fileCategory = fileCategory
self.path = self.folderPath + self.fileName
didSetFileCategory()
}
private func didSetFileCategory() {
switch fileCategory {
case .XYZ:
print("Test")
//... other cases
}
}
}

Referencing the class in it self in Class method

I would like to access the class methods inside the class it self. I know you could use self keyword in a class instance like so:
class InstanceClass {
var testProperty = "testing"
func testMathod() {
print(self.testProperty)
}
}
// initiate like so
let newInstance = InstanceClass()
newInstance.testMathod() // result testing
What's the keyword for accessing class in static property in below example:
class BaseClass {
static let testProperty = "test"
class func printProperty () {
// here I want to access testProperty
}
}
I aware that I could do BaseClass.testProperty in above example but I want to keep it abstract.
I have Swift 2.11 running.
My bad.. self keyword works with Class Methods also.
Example:
class BaseClass {
class var testProperty: String {
return "Original Word"
}
static func printTestPropery() {
print(self.testProperty)
}
}
class ChildClass: BaseClass {
override class var testProperty: String {
return "Modified Word"
}
}
ChildClass.printTestPropery() // prints "Modified Word"
I find Swift to be a little inconsistent for this but here is how you access static class properties from various scopes:
class BaseClass
{
static let testProperty = "test2"
// access class property from class function
class func printProperty()
{
print( testProperty )
}
// access class property from instance function
func printClassProperty()
{
print(BaseClass.testProperty)
print(self.dynamicType.testProperty)
}
}
protocol PrintMe:class
{
static var testProperty:String { get }
}
extension BaseClass:PrintMe {}
extension PrintMe
{
// access from a class protocol can use Self for the class
func printFromProtocol()
{
print(Self.testProperty)
}
}

Swift - dynamicType in initializer of Subclass returns BaseClass instead

I'm trying to create a Abstract class that can fetch records from CloudKit and return the appropriate instances based on the subclass that called the fetch method.
The problem is the class method of the Base class doesn't return an instance of the Subclass.
Run the following code in playgrounds:
class Base {
class var value: String { return "Base" }
class func doSomething() -> Self { // In Obj-C this would return instanceType
println("doSomething() = \(self.value)")
let object = self.init()
return object
}
init() {
println("init() = \(self.dynamicType.value)")
}
}
class Sub: Base {
override class var value: String { return "Sub" }
override init() {
super.init()
println("Value = \(self.dynamicType.value)")
}
}
println("Base")
let base = Base.doSomething() // type = Base
println()
println("Sub")
let sub = Sub.doSomething() // type = Base !!
For some reason when calling doSomething() on the Subclass, the initializer prints the value of the Base class property ("Base" instead of "Sub):
Base doSomething() = Base
init() = Base
Sub doSomething() = Sub
init() = Base
You should get the correct string value when you do a:
NSStringFromClass(self.dynamicType)

Resources