Store a Closure as a Variable in Swift

Store a closure as a variable in Swift

The compiler complains on

var completionHandler: (Float)->Void = {}

because the right-hand side is not a closure of the appropriate signature, i.e. a closure taking
a float argument. The following would assign a "do nothing" closure to the
completion handler:

var completionHandler: (Float)->Void = {
(arg: Float) -> Void in
}

and this can be shortened to

var completionHandler: (Float)->Void = { arg in }

due to the automatic type inference.

But what you probably want is that the completion handler is initialized to nil
in the same way that an Objective-C instance variable is inititialized to nil. In Swift
this can be realized with an optional:

var completionHandler: ((Float)->Void)?

Now the property is automatically initialized to nil ("no value").
In Swift you would use optional binding to check of a the
completion handler has a value

if let handler = completionHandler {
handler(result)
}

or optional chaining:

completionHandler?(result)

swift closure stored and access as a variable

Here is your working example. You have a number of mistakes which the attached illustrates. Note
I had the download() method return Bool so that the result can be see in this screen shot.

Sample Image

But, your use of an implicitly unwrapped optional (aka '!') is incorrect. Such an optional is used when the value may be nil but will be assigned at a known time and not changed (see Apple documentation for a description). Your downloadCompleted is a true optional (at least in your example use). Thus, better code, which turns out to be slightly simpler is:

Sample Image

Swift closure giving function to variable

Adding () to someFunc means that you are calling the function and this will evaluate to the return value of someFunc, which is Void.

You need to refer to the function directly, without calling it. Just remove the ():

a.callback = someFunc

Add value to variable inside closure in swift

The problem is that geocodeAddressString runs asynchronously (i.e. it takes so long they have written it to return immediately and call its closure later, when the request is done), so viewDidLoad is printing latLong well before this property was eventually set in the geocodeAddressString completion handler closure.

The solution is to adopt asynchronous programming pattern in your own code. For example, employ your own completion handler pattern:

override func viewDidLoad() {
super.viewDidLoad()

findCordiante(adress: "Cupertino, California, U.S.") { string in
// use `string` here ...

if let string = string {
self.latLong = string
print(string)
} else {
print("not found")
}
}

// ... but not here, because the above runs asynchronously and it has not yet been set
}

func findCordiante(adress:String, completionHandler: @escaping (String?) -> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(adress) { placemarks, error in
if let location = placemarks?.first?.location, location.horizontalAccuracy >= 0 {
completionHandler("\(location.coordinate.latitude), \(location.coordinate.longitude)")
} else {
completionHandler(nil)
}
}
}

Setting a closure as a variable in Swift and trying to call from Objective C class

Seems you just need to explicitly annotate some properties and types with @objc:

@objc public enum IAPHelperAlertType: Int {
case disabled
case restored
case purchased
func message() -> String{
switch self {
case .disabled:
return "Purchases are disabled in your device!"
case .restored:
return "You've successfully restored your purchase!"
case .purchased:
return "You've successfully bought this purchase!"

}
}
}

(Added :Int as suggested by Xcode.)

class IAPHelper: NSObject {
@objc static let shared = IAPHelper()
@objc var purchaseStatusBlock: (@convention(block) (IAPHelperAlertType) -> Void)?
}

(Added two @objc and @convention(block). @convention(block) makes the closure type compatible with Objective-C blocks.)

With these changes above, you can write something like this in your Objective-C code:

    IAPHelper.shared.purchaseStatusBlock(IAPHelperAlertTypeDisabled)

Assign Value from Closure to Variable Swift

change var userId: Int to var userId: Int!

The reason is that the closure is expecting a value to be in the variable when you "capture it". By using a forcefully unwrapped variable, the closure will be able to capture it as it holds a value of nil, which you can then assign a value to when the closure is called.

How to save variable in closure to external variable?

In the completion block of makeApiCall simply reload your pickerView's component on main thread and you all set to go.

SomeClass.makeApiCall(completionHandler: { customds in
self.customDS = customds
DispatchQueue.main.async {
self.reloadComponent(0)
}
})


Related Topics



Leave a reply



Submit