What causes 'Constant captured by a closure before being initialized' error
The reason for the error message is that the nil-coalescing operator
is defined as
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
and does a "auto closure" on the second argument (in order to get
a short-circuiting behaviour). So
self.value = dict["bar"] as? String ?? _defaultValue
is transformed by the compiler to
self.value = dict["bar"] as? String ?? { self._defaultValue }()
and here the compiler complains because self
is captured before
being fully initialised. (The error messages are slightly different
between Swift 2 and Swift 3).
Possible workarounds. You can assign the property to a local variable first:
init(dict: NSDictionary){
let defValue = _defaultValue
self.value = dict["bar"] as? String! ?? defValue
}
Or you can make it a static property of the class:
class Foo {
static let _defaultValue = "N/A"
let value: String
init(dict: NSDictionary) {
self.value = dict["bar"] as? String ?? Foo._defaultValue
}
}
Or replace ??
by an if-statement:
class Foo {
let _defaultValue = "N/A"
let value: String
init (dict: NSDictionary) {
if let value = dict["bar"] as? String {
self.value = value
} else {
self.value = _defaultValue
}
}
}
Addendum: Related resources:
- Autoclosure of self in initializers in the Swift forum.
- SR-944 Cannot use 'self' in RHS of && before all properties are initialized bug report.
Quote from the bug report:
Jordan Rose: This is true since && is implemented using @autoclosure, but it's certainly suboptimal.
how to deal with 'Self captured by closure before being initialized'
The problem with your code is that you have declared the variable as a constant, and swift should always have constants initialized within the init method. But, here you have dependent kind of requirement, readyHandler property is a constant which has to be initialized in order to create object but then, you are using self inside it which is not initialized, you can see a cyclic requirement.
You can directly get rid of this, if you use optional or implicitly unwrapped optional in which case, swift need not have initial value at the phase of instantiation.
class A {
class ReadyHandler { // fires off the callback when needed
let callback: ()->Void
init(callback: @escaping ()->Void) {
self.callback = callback
}
}
var readyHandler: ReadyHandler!
var ready = false
init() {
readyHandler = ReadyHandler(callback: {self.ready = true})
}
}
You can create a also use lazy property for your readyHandler which gets initialized first time it is used.
class A {
class ReadyHandler {
let callback: ()->Void
init(callback: @escaping ()->Void) {
self.callback = callback
}
}
var ready = false
lazy var readyHandler: ReadyHandler = {
return ReadyHandler(callback: { [unowned self] in
self.ready = true
})
}()
}
Variable (results) captured by a closure before being initialized
Error is because you are not initializing the results array,
simple solution can be this
declare your results array like this
var results = [Any]()
I think you should do this:
you should declare results as instance variable like this outside viewDidLoad
method
var results = [Any]()
Then use this variable inside closure as follows because I think you need this result in other parts of your code
self.results.append(result)
Strange 'self' captured by a closure before all members were initialized error
The problem is in bExpectedValue
. That's an instance property on B
. That interacts with the definition of &&
on Bool:
static func && (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool
The @autoclosure
makes the b == bExpectedValue
into a closure, capturing it as self.bExpectedValue
. That's not allowed before initialization is complete. (The closure here is to allow short-circuiting. The rhs closure is not evaluated if lhs is false.)
This is pretty awkward (see SR-944 that MartinR references for a little discussion about it).
If bExpectedValue
were static
, or if it were moved outside the class definition, then this wouldn't be an issue. The following approach will also fix it:
override init(a: String, b: String) {
let goodA = a == aExpectedValue
let goodB = b == bExpectedValue
c = goodA && goodB
super.init(a: a, b: b)
}
Variable 'newBalance' captured by a closure before being initialized - Firestore data fetch function - SwiftUI
You need a completion
func getBalance(uid: String,completion:@escaping(Double) -> ()) {
FirebaseManager.shared.firestore.collection("users").document(uid).getDocument{ snapshot, error in
guard let data = snapshot?.data() else {self.errorMessage = "No data found"
return}
let balance = data["balance"] as? Double ?? 0
print("Function balance \(balance)")
completion(balance)
}
}
Call
getBalance(uid:<#value#>) { balance in
print(balance)
}
OR with SwiftUI use @published
@published var newBalance: Double?
func getBalance(uid: String) {
FirebaseManager.shared.firestore.collection("users").document(uid).getDocument{ snapshot, error in
guard let data = snapshot?.data() else {self.errorMessage = "No data found"
return}
let balance = data["balance"] as? Double ?? 0
print("Function balance \(balance)")
self.newBalance = balance
}
}
self' captured by a closure before all members were initialized
I'd hazard to guess that your are running into a concurrency problem. You are probably trying to access your object's properties before the asynchronous call to the DarkSkyClient returns (my apologies in advance if I got this wrong). i.e., the order of events is...
- Weather object is initialized, setting temp to 0
- Call to DarkSkyClient begins, runs in the background
- Read temp variable - hey, it's 0!
- Call to DarkSkyClient completes, sets the temp to the value you really wanted. Bad
So what you really need to do is switch to an inversion of control pattern:
class Weather {
var temp: Float
var condition: String
var wind: Float
var precip: Float
init(forecast: Forecast) {
temp = (forecast.currently?.temperature)!
condition = (forecast.currently?.summary)!
wind = (forecast.currently?.windSpeed)!
precip = (forecast.currently?.precipitationProbability)!
}
static func getWeather() {
DarkSkyClient(apiKey: "<api key>").getForecast(latitude: Utils().getLat(), longitude: Utils().getLong()) { result in
switch result {
case .success(let currentForecast, _):
let weather = Weather(forecast: currentForecast)
// Display the weather somewhere
doSomethingWith(weather: weather)
case .failure(let error):
print(error)
}
}
}
}
If you're not familiar with developing with asynchronous APIs it's worth your while to read up on the subject; it can be very tricky (sadly, I don't have any recommendations for a good primer).
Hope this helps!
Guard condition provokes compiler error that talks about closure
The problem, as explained by Martin in this Q&A, is that the ||
operator is implemented with an @autoclosure
second parameter, in order to allow for short-circuit evaluation (the right hand expression need only be evaluated if the left hand expression evaluates to false
).
Therefore in the expression
b == nil || self.a > 0
self.a > 0
is implicitly wrapped in a () -> Bool
closure. This is problematic, because it requires the capture of self
, so that a
can be accessed upon applying the closure.
However, in an initialiser, Swift tightly restricts what you can do with self
before it has been fully initialised. One of these restrictions is the inability to be captured by a closure – which is why you get a compiler error.
Although really, there's nothing wrong with the closure { self.a > 0 }
capturing self
before it's fully initialised, because all the closure is doing is accessing a
on it, which has already been initialised. Therefore, this is really just an edge case (for which there's an open bug report), which I hope will be smoothed out in a future version of the language.
Until then, one solution as shown by Martin in this Q&A, is to use a temporary local variable to create a copy of the value of self.a
, avoiding the capturing of self
in the closure:
class Foo {
var a: Int
var b: Int
init(a: Int, b: String?) throws {
// some computation meaning that a != self.a
self.a = a * 42
// temporary local variable to be captured by the @autoclosure.
let _a = self.a
guard b == nil || _a > 0 else {
throw "Too little a!"
}
self.b = self.a
}
}
extension String: Error {}
Obviously, this assumes that self.a != a
, otherwise you can just refer to a
instead of self.a
in the guard
condition.
Self captured by a closure before all members were initialized
The problem is that you have some variables in your class that are only declared, but not initialized by the time your capture is called, where you are referring to self
.
Declaring a variable: var a: Int
and initializing it: var a:Int = 0
or var a:Int? = nil
are not the same.
All variables of your class need to be initialized (given an initial value) before you could refer to self
.
Related Topics
Obervableobject Being Init Multiple Time, and Not Refreshing My View
How to Do If Pattern Matching with Multiple Cases
Perform Assignment Only If Right Side Is Not Nil
How to Obtain the Selected Text from the Frontmost Application in MACos
Change Color Searchbar Result Icon Swift
How to Get Indexpath When Image Inside Cell Tapped
How to Use Array.Filter to Filter a Class Object Based on a Property
Function Does Not Wait Until the Data Is Downloaded
Is Swift Dictionary of Indexed for Performance? Even for Exotic Types (Uuid)
How to Get the File Creation Date Using Url Resourcevalues Method in Swift 3
Swiftui: Can't Get the Transition of a Detailview to a Zstack in the Mainview to Work
Apply a Shadow on a Uiview That Have Same Corner Radius Than View
Why Isn't Guard Let Foo = Foo Valid
Xcode 9 and Xcode 10 Giving Different Results, Even with Same Swift Version
Swift Setter Causing Exc_Bad_Access
Swift: Can Someone Explain This Syntax 'Numbers.Sort { $0 > $1 }' for Me