I am trying to implement a native module in React native using Swift for IOS.
I have a function getRandomFoodWithCompletionHandler() Where I am trying to fetch something from the API and then sending it back to JS through the bridge using promises. I use resolve:RCTPromiseResolveBlock function, but when I use it I have an error Escaping closure captures non-escaping parameter 'resolve'
struct Food: Identifiable, Decodable {
var id: Int
var uid: String
var dish: String
var description: String
var ingredient: String
var measurement: String
}
@objc
func getRandomFoodWithCompletionHandler(_ resolve:RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
guard let url = URL(string: "https://random-data-api.com/api/food/random_food") else { fatalError("Missing URL") }
let urlRequest = URLRequest(url: url)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let error = error {
print("Request error: ", error)
return
}
guard (response as? HTTPURLResponse)?.statusCode == 200 else { return }
guard let data = data else { return }
do {
let decodedFood = try JSONDecoder().decode(Food.self, from: data)
print("Completion handler decodedFood", decodedFood)
resolve(decodedFood)
} catch {
print("Error decoding", error)
}
}
dataTask.resume()
}
CodePudding user response:
Make your resolve: RCTPromiseResolveBlock
parameter an escaping block:
func getRandomFoodWithCompletionHandler(
_ resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock
) {
An "escaping" block is essentially a block that can be called even when the original function has already finished executing, e.g. when it's an asynchronous completion handler. In Swift it's necessary to distinguish such a situation because of memory allocations/deallocations.