Self' Used Before All Stored Properties Are Initialized

self' used before all stored properties are initialized

In this case I would suggest you to make the property a variable but hiding it (make it seem like a constant) through a computed property:

class Country {
let name: String

private var _capitalCity: City!
var capitalCity: City {
return _capitalCity
}

init(name: String, capitalName: String) {
self.name = name
self._capitalCity = City(name: capitalName, country: self)
}
}

self' used before all stored properties are initialized in struct

Instead defining your getRandom as an instance method, define it as a static one, then reference it by a type name (CurrentData) or Self

struct CurrentData {
var size: (x: Int, y: Int)
var location: (x: Int, y: Int)

init(size: (x: Int, y: Int)) {
self.size = size
location = (Self.getRandom(size.x), Self.getRandom(size.y))
}

private static func getRandom (_ value:Int) -> Int {
Int.random(in: 0...value-1)
}
}

Other solution is to define your locationproperty as a lazy one, then the self is accessible and the location will be executed only once and after being called in the code.

struct CurrentData {
var size: (x: Int, y: Int)
lazy var location: (x: Int, y: Int) = {
(getRandom(size.x), getRandom(size.y))
}()

init(size: (x: Int, y: Int)) {
self.size = size
}

private func getRandom (_ value:Int) -> Int {
Int.random(in: 0...value-1)
}
}

Struct initialization in SwiftUI: 'self' used before all stored properties are initialized

You shouldn't create @ObservedObject values in your initializer. Doing so leads to bugs, because you'll create new instances every time the view is recreated. Either jobsViewModel and categoriesViewModel should be passed as arguments to init, or you should be using @StateObject for those properties.

But anyway, you actually asked: why can't we use $jobFilter before initializing jobsViewModel?

Let's start by simplifying the example:

struct JobsTab: View {
@State var jobFilter: String
var jobFilterBinding: Binding<String>

init() {
jobFilter = ""
jobFilterBinding = $jobFilter
// ^ 'self' used before all stored properties are initialized
}

var body: some View { Text("hello") }
}

So, what's going on here? It'll help if we “de-sugar” the use of @State. The compiler transforms the declaration of jobFilter into three properties:

struct JobsTab: View {
private var _jobFilter: State<String>

var jobFilter: String {
get { _jobFilter.wrappedValue }
nonmutating set { _jobFilter.wrappedValue = newValue }
}

var $jobFilter: Binding<String> {
get { _jobFilter.projectedValue }
}

var jobFilterBinding: Binding<String>

init() {
_jobFilter = State<String>(wrappedValue: "")
jobFilterBinding = $jobFilter
// ^ 'self' used before all stored properties are initialized
}

var body: some View { Text("hello") }
}

Notice now that $jobFilter is not a stored property. It is a computed property. So accessing $jobFilter means calling its “getter”, which is a method on self. But we cannot call a method on self until self is fully initialized. That's why we get an error if we try to use $jobFilter before initializing all stored properties.

The fix is to avoid using $jobFilter. Instead, we can use _jobFilter.projectedValue directly:

struct JobsTab: View {
@State var jobFilter: String
var jobFilterBinding: Binding<String>

init() {
jobFilter = ""
jobFilterBinding = _jobFilter.projectedValue
}

var body: some View { Text("hello") }
}

SwiftUI: 'self' used before all stored properties are initialized

If I understand the question correctly it sounds like you want the view to track some vpnState class from your view and you're attempting to pass references from the view to the controller object, but that's backwards of how SwiftUI is designed.

Fundamentally you should view Views as read-only objects that are updated behind the scenes by the framework. You lock them onto a property or object to observe and when that thing changes the view is automatically updated with the new value.

@State variables are intended for use strictly within your views, like for use with an animation or some other intermediate state completely within the View. In this instance the Swifty thing to do would be to use a @ObservedObject or @EnvironmentObject to watch the state of the object for you.

As to why self is a "different" object when you use it that is because a struct is a value type not a reference type. It is destroyed and recreated by Swift each time it is change. It is not "updated" in the sense that values are changed on the object.

self' used before all stored properties are initialized error - @State - extension - second file

Here the solution with @binding:


// ListCell.swift

import SwiftUI

struct ListCell: View {
@Binding var name: String
var count: Int

var body: some View {
HStack {
Text(name)
Text(": \(count)")
}
}
}

// ListCell+Ext.swift

import SwiftUI

extension ListCell {
init(name: Binding<String>) {
self.init(name: name, count: 0)
}
}

Initializing 2 variables in init(): 'self' used before all stored properties are initialized

Binding as a property (hidden) has _ (underscore), so you have to initialize it as

init(showSurvey: Binding<Bool>) {
self.customerVM = BuildCustomerViewModel()
self._showSurvey = showSurvey // << this !!
}

Use of 'self' in method call 'f' before all stored properties are initialized

It doesn't mean that if you haven't written self with function call f then it will not reference to self as of f is still instance method, so with init it must be called after all the instance properties are initialized means after the the instance of class is initialized. So simply call f() after you initialized the instance property a.

class A {
var a: String
init(a: String) {
self.a = a
f()
}

func f() {
print("HeHe")
}
}


Related Topics



Leave a reply



Submit