i am learning to build collectionView the modern way for a few weeks now, and i am constantly facing issue to overcome and solve, but i am making no progress with this one here at all..
var layoutConfig = UICollectionLayoutListConfiguration(appearance: .plain)
layoutConfig.trailingSwipeActionsConfigurationProvider = { indexPath in
let commentIDString = self.dataSource.itemIdentifier(for: indexPath)?.commentID
let commentID = Int32(commentIDString ?? 0)
let action = UIContextualAction(style: .destructive, title: "", handler: {(action, view, completion) in
print("swipe action triggered!?")
Task {
do{
let parameter = ["commentID": commentID, "action": "removeComment"] // remove Comment
let returnDictionary = await APIs.shared.contactAPI(urlString: "APIURL.comments.php", parameter: parameter)
}
}
completion(true)
})
action.image = UIImage(systemName: "delete.left")
action.backgroundColor = .systemRed
return UISwipeActionsConfiguration(actions: [action])
}
contactAPI:
func contactAPI(urlString: String, parameter: Dictionary<String,String>) async -> Dictionary<String, Any> {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
var jsonData = Data()
do { jsonData = try encoder.encode(parameter) }
catch let error { print("something went wrong here -.-: \(error)") }
print(String(data: jsonData, encoding: .utf8)!) // for debugging
let url = URL(string: urlString)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let (data, _) = try! await URLSession.shared.upload(for: request, from: jsonData)
//// for debugging
// let dataString = String(data: data, encoding: .utf8)
// print(dataString)
let dictionary: [String: String] = try! JSONDecoder().decode([String: String].self, from: data)
// print(dictionary) // for debugging
// var returnDic = Dictionary<String, Any>()
return dictionary
}
as you can see i have to call a network method inside that actionHandler, and xcode is complaining that the "trailingSwipeActionsConfigurationProvider": "Type of expression is ambiguous without more context"
if i remove that Task {} Block, everythings works as expected, so as i understood it there is a problem with that API call which of course is async, and can't find any documentation about that anywhere ..please help me out guys
CodePudding user response:
The compiler is complaining as it does not know how to interpret your code. The do
block has to be followed by a catch
block in swift.
documentation on error handling
The function you are trying to call is not throwing so no need for that do
block at all. Just use:
Task {
let parameter = ["commentID": commentID, "action": "removeComment"] // remove Comment
let returnDictionary = await APIs.shared.contactAPI(urlString: "APIURL.comments.php", parameter: parameter)
}
I have to admit I didn´t test this answer thoroughly. Sorry for that. It just seemed to be the most obvious error.
After disecting your code I found the issue:
Take a look at your functions signature
func contactAPI(urlString: String, parameter: Dictionary<String,String>) async -> Dictionary<String, Any> {
and the way you construct your argument
let commentID = Int32(commentIDString ?? 0)
let parameter = ["commentID": commentID, "action": "removeComment"] // remove Comment
let returnDictionary = await APIs.shared.contactAPI(urlString: "APIURL.comments.php", parameter: parameter)
parameter is a [String:Any]
here because commentID
is of type Int
and the next value is of type String
. Anyway your function expects [String:String]
.
You need to fix this. It seems the best approach would be to create a custom struct for your parameters and encode that instead of this clumpsy dictionary approach.
Without knowing more about your code structure and needs for parameter I would recommend this struct:
struct Parameter: Codable{
var commentID: Int
var action: String
}
let commentIDString = self.dataSource.itemIdentifier(for: indexPath)?.commentID
let commentID = Int(commentIDString ?? "0") ?? 0
let action = UIContextualAction(style: .destructive, title: "", handler: {(action, view, completion) in
print("swipe action triggered!?")
Task {
let parameter = Parameter(commentID: commentID, action: "removeComment") // remove Comment
let responseDict = await APIs.shared.contactAPI(urlString: "APIURL.comments.php", parameter: parameter)
}
completion(true)
})
The signature of your function would become:
func contactAPI(urlString: String, parameter: Parameter) async -> Dictionary<String, String> {
This should work this way. By the way, your String?
to Int
conversion was also flawed and would have thrown another error.