completionHandler / userCompletionHandler 问题 - Swift iOS
completionHandler / userCompletionHandler problem - Swift iOS
我有以下两个功能:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath)
let message = self.messages[indexPath.row]
// Set table cell values
getUserFriendlyName(sid: message.sid!, arg: true, completion: { (success) -> Void in
cell.detailTextLabel?.text = self.friendly_name
cell.textLabel?.text = message.body
cell.selectionStyle = .none
//self.tableView.reloadData()
})
return cell
}
和
func getUserFriendlyName(sid: String, arg: Bool, completion: @escaping (Bool) -> ()) {
let ACCOUNT_IDENTITY: String = "AC***redacted"
let AUTH_TOKEN: String = "**redacted"
let SERVICE_ID: String = "IS***redacted"
let loginString = "\(ACCOUNT_IDENTITY):\(AUTH_TOKEN)"
let loginData = loginString.data(using: String.Encoding.utf8)
let base64LoginString = loginData!.base64EncodedString()
let url = URL(string: "https://chat.twilio.com/v2/Services/IS***redacted/Users/US***redacted")
var request = URLRequest(url: url!)
var session = URLSession.shared
request.httpMethod = "GET"
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//request.addValue(AUTH_TOKEN, forHTTPHeaderField: "Authorization")
var fn: String!
let task = session.dataTask(with: request, completionHandler: { data, response, error in
var strData = String(data: data!, encoding: String.Encoding.utf8)
print("Body: \(strData)")
guard error == nil else {
print(error!)
return
}
guard let data = data else {
print("Data is empty")
return
}
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
//getting the json response
print(json)
fn = json["friendly_name"] as! String?
self.friendly_name = fn
completion(arg)
//return fn
//print(fn)
})
task.resume()
}
这是我 运行 遇到的问题...当检测到新的聊天消息时,将调用 tableView 函数。使用文本和子文本创建一个新单元格。因为本机 Twilio 代码不允许我显示谁写聊天的友好名称,我必须去进行 HTTP 调用,所以我调用 getUserFriendlyName()。因为 resumeTask() 是异步的,所以程序的流程是这样的:
- tableView功能进入
- 我调用了 getUserFriendlyNameFunction(),它被输入了
- 当我们到达 HTTP 请求时,resumeTask() 被调用,然后流程 returns 返回到 tableView 函数,特别是对友好用户名函数的调用结束并执行return单元格行,表示单元格已创建,但包含原型数据,即"Title"为文本,"Subtitle"为描述文本。
- 流程然后返回到 HTTP 请求并被执行
- 流程 return 直接在调用 tableView 函数内的 getUserFriendlyName() 之后的代码行。该代码将文本和详细文本值设置为由 HTTP 调用编辑的数据 return。但是此时,该单元格已经存在于我的 tableView 中。所以我只剩下一个包含 "Text" 和 "Subtext".
的单元格
我尝试过的:
在 tableView 函数中的最后几行代码执行后添加 tableView.reloadData()。这不会使用来自 HTTP 调用的数据更新 tableView。事实上,它不断地一遍又一遍地刷新tableView。
将最后三行代码移动到与 "return Cell" 行相同的位置。这也没有用。
我开始相信我唯一的希望is/are completionHandler / userCompletionHandler。我和他们玩了很长时间,但无法获得预期的结果,即用来自 HTTP 请求的数据填充第一条传入的聊天消息。
有人能帮忙吗?
当你收到一条消息时,不要直接将它添加到消息数组中,而是先调用
// this goes inside some function not cellForRowAt
let message = // received
getUserFriendlyName(sid: message.sid!, arg: true, completion: { (success) -> Void in
message....// set all needed properties
self.messages.append(message)
self.tableview.reloadRows(at:[IndexPath(row:messages.count - 1,section:0)],with:.none)
}
不要在内部做任何异步工作 cellForRowAt
因为它会在每次滚动时完成,此外它不会同时显示完整数据
session.dataTask(with: request
的完成是在后台线程中进行的,因此请考虑
DispatchQueue.main.async {
completion(arg)
}
你让self.friendly_name
self.friendly_name = fn
A vc 属性 而它应该是每个消息对象的 属性 以便不要与其他消息发送者混合
我有以下两个功能:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath)
let message = self.messages[indexPath.row]
// Set table cell values
getUserFriendlyName(sid: message.sid!, arg: true, completion: { (success) -> Void in
cell.detailTextLabel?.text = self.friendly_name
cell.textLabel?.text = message.body
cell.selectionStyle = .none
//self.tableView.reloadData()
})
return cell
}
和
func getUserFriendlyName(sid: String, arg: Bool, completion: @escaping (Bool) -> ()) {
let ACCOUNT_IDENTITY: String = "AC***redacted"
let AUTH_TOKEN: String = "**redacted"
let SERVICE_ID: String = "IS***redacted"
let loginString = "\(ACCOUNT_IDENTITY):\(AUTH_TOKEN)"
let loginData = loginString.data(using: String.Encoding.utf8)
let base64LoginString = loginData!.base64EncodedString()
let url = URL(string: "https://chat.twilio.com/v2/Services/IS***redacted/Users/US***redacted")
var request = URLRequest(url: url!)
var session = URLSession.shared
request.httpMethod = "GET"
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//request.addValue(AUTH_TOKEN, forHTTPHeaderField: "Authorization")
var fn: String!
let task = session.dataTask(with: request, completionHandler: { data, response, error in
var strData = String(data: data!, encoding: String.Encoding.utf8)
print("Body: \(strData)")
guard error == nil else {
print(error!)
return
}
guard let data = data else {
print("Data is empty")
return
}
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
//getting the json response
print(json)
fn = json["friendly_name"] as! String?
self.friendly_name = fn
completion(arg)
//return fn
//print(fn)
})
task.resume()
}
这是我 运行 遇到的问题...当检测到新的聊天消息时,将调用 tableView 函数。使用文本和子文本创建一个新单元格。因为本机 Twilio 代码不允许我显示谁写聊天的友好名称,我必须去进行 HTTP 调用,所以我调用 getUserFriendlyName()。因为 resumeTask() 是异步的,所以程序的流程是这样的:
- tableView功能进入
- 我调用了 getUserFriendlyNameFunction(),它被输入了
- 当我们到达 HTTP 请求时,resumeTask() 被调用,然后流程 returns 返回到 tableView 函数,特别是对友好用户名函数的调用结束并执行return单元格行,表示单元格已创建,但包含原型数据,即"Title"为文本,"Subtitle"为描述文本。
- 流程然后返回到 HTTP 请求并被执行
- 流程 return 直接在调用 tableView 函数内的 getUserFriendlyName() 之后的代码行。该代码将文本和详细文本值设置为由 HTTP 调用编辑的数据 return。但是此时,该单元格已经存在于我的 tableView 中。所以我只剩下一个包含 "Text" 和 "Subtext". 的单元格
我尝试过的:
在 tableView 函数中的最后几行代码执行后添加 tableView.reloadData()。这不会使用来自 HTTP 调用的数据更新 tableView。事实上,它不断地一遍又一遍地刷新tableView。
将最后三行代码移动到与 "return Cell" 行相同的位置。这也没有用。
我开始相信我唯一的希望is/are completionHandler / userCompletionHandler。我和他们玩了很长时间,但无法获得预期的结果,即用来自 HTTP 请求的数据填充第一条传入的聊天消息。
有人能帮忙吗?
当你收到一条消息时,不要直接将它添加到消息数组中,而是先调用
// this goes inside some function not cellForRowAt
let message = // received
getUserFriendlyName(sid: message.sid!, arg: true, completion: { (success) -> Void in
message....// set all needed properties
self.messages.append(message)
self.tableview.reloadRows(at:[IndexPath(row:messages.count - 1,section:0)],with:.none)
}
不要在内部做任何异步工作 cellForRowAt
因为它会在每次滚动时完成,此外它不会同时显示完整数据
session.dataTask(with: request
的完成是在后台线程中进行的,因此请考虑
DispatchQueue.main.async {
completion(arg)
}
你让self.friendly_name
self.friendly_name = fn
A vc 属性 而它应该是每个消息对象的 属性 以便不要与其他消息发送者混合