I have written this code:
In the first step, I read an Excel file that contains the addresses of the buildings as a string.
LABE | HAUS | Gemeindename |
---|---|---|
Hasenwinkel | 14 | Braunschweig |
The Excel file is similar to the table above.
I want to read the addresses inside a loop and get the coordinates of the addresses (Lat, Long) using CLGeocoder. Using the snapshotImage function, I give the coordinates as input to the function, and if there is picture, I want to save that picture of the target address with its address name.
But I get the following errors:
1.Cannot pass function of type ‘([CLPlacemark]?, (any Error)?) async throws -> Void’ to parameter expecting synchronous function type
2. Invalid conversion from throwing function of type ‘([CLPlacemark]?, (any Error)?) async throws -> Void’ to non-throwing function type ‘([CLPlacemark]?, (any Error)?) -> Void’
let columnTypes: [String: CSVType] = ["LABE": .string,
"HAUS": .string,
"Gemeindename": .string]
let path = Bundle.main.url(forResource: "Adresse", withExtension: "csv")!
let options = CSVReadingOptions(
hasHeaderRow: true,
ignoresEmptyLines: true,
delimiter: ";"
)
let result = try DataFrame(contentsOfCSVFile: path,rows: 0..<50, types: columnTypes,options: options)
enum LookaroundError: Error {
case unableToCreateScene
}
func snapshotImage(for coordinate: CLLocationCoordinate2D) async throws -> UIImage {
guard let scene = try await MKLookAroundSceneRequest(coordinate: coordinate).scene else {
throw LookaroundError.unableToCreateScene
}
let options = MKLookAroundSnapshotter.Options()
options.size = CGSize(width: 1000, height: 500)
return try await MKLookAroundSnapshotter(scene: scene, options: options).snapshot.image
}
var address: String = ""
for row in result.rows {
if row["HAUS"] == nil {
address = "(row["LABE"] ?? <#default value#>) (row["Gemeindename"] ?? <#default value#>)"
} else {
address = "(row["LABE"] ?? <#default value#>) (row["HAUS"] ?? <#default value#>) (row["Gemeindename"] ?? <#default value#>)"
}
print(address)
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address){ (placemarks, error) in
guard
let placemarks = placemarks,
let location: CLLocationCoordinate2D = placemarks.first?.location?.coordinate
else{
return
}
var image = try await snapshotImage(for: location)
var url = try FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appending(component: "(address).png")
try image.pngData()?.write(to: url)
}
}
Ideally, I want to read the addresses in this loop and save a picture of them using their coordinates.I don’t have much experience in Swift programming. Does anyone have an idea how to solve the code problem?
2
Answers
The error tells you exactly what’s wrong, but it may not be obvious why it is wrong.
This line
makes the closure you pass to
geocoder.geocodeAddressString
asynchronous. That function will not acceptasync
closures. It’s not declared to. It’s the same as if you passed a throwing closure to a non throwing parameter.Since you don’t provide the definition for
geocoder.geocodeAddressString
it is difficult to suggest a fix. Perhaps just build an array of locations in the loop and then get the snapshot images afterwards.change
to
or, more correct, mark your function signature with
throws
and