当应用启动时,我向api发送请求,应用程序开始接收数据。我使用委托方法,控制流,当它占用空字节时,它停止任务和会话。之后,我必须调用一些方法(UpdateInfoManager.createHouse()),其中包含方法链,它调用api并将数据解析为对象。但我执行时遇到了一些问题。例如,我启动我的应用程序10次,只有1或2次立即执行,其他8次我有无限加载:
extension ViewController: URLSessionTaskDelegate, URLSessionDelegate, URLSessionDataDelegate {
func getLogBinData() {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main)
if let url = URL(string: TaskManager.httpString + "log.bin") {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.dataTask(with: request)
task.resume()
}
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if data.first != 255 {
fullData.append(data)
} else {
dataTask.cancel()
session.invalidateAndCancel()
UpdateInfoManager.createHouse(logData: self.fullData) { (complete) in
DispatchQueue.main.async {
self.house = HouseManager.house
if let house = self.house {
self.nameLabel.text = house.houseName
self.menuController.house = house
self.menuController.roomsTableView.reloadData()
self.menuController.houseNameLabel.text = house.houseName
self.spinner.stopAnimating()
self.hideView.isHidden = true
self.view.isUserInteractionEnabled = true
}
}
}
}
}
}
但是我试图使用DispatchQueue.global()。asyncAfter(截止日期:.now()+ 0.1),并且它的工作原理,应用程序总是快速启动。但我认为这不是一个好的解决方案。为什么会这样?
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if data.first != 255 {
fullData.append(data)
} else {
dataTask.cancel()
session.invalidateAndCancel()
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
UpdateInfoManager.createHouse(logData: self.fullData) { (complete) in
DispatchQueue.main.async {
self.house = HouseManager.house
if let house = self.house {
self.nameLabel.text = house.houseName
self.menuController.house = house
self.menuController.roomsTableView.reloadData()
self.menuController.houseNameLabel.text = house.houseName
self.spinner.stopAnimating()
self.hideView.isHidden = true
self.view.isUserInteractionEnabled = true
}
}
}
}
}
}
我还尝试在委托方法体中调用UpdateInfoManager.createHouse(),它也很有效。但我需要在这里打电话
更新
createHouse()方法代码:
class UpdateInfoManager: NSObject {
static func createHouse(logData: Data, completion: @escaping ((Bool) -> ())) {
TaskManager.getUserBinFileFromApi { (userData) in
TaskManager.getDeviceBinFileFromApi(userData: userData, completion: { (userData, deviceData) in
HouseManager.createDataObject(userData: userData, deviceData: deviceData, completion: { (house, data) in
HouseManager.createRooms(house: house, data: data, completion: { (house, data) in
DeviceManager.addDevicecToRooms(logData: logData, house: house, data: data, completion: { (data) in
DispatchQueue.main.async {
HouseManager.house = house
completion(true)
}
})
})
})
})
}
}
}
答案 0 :(得分:0)
@Sergey我的猜测是UpdateInfoManager.createHouse阻塞主线程因为你已经指定调用Delegate方法调用主线程检查下面的代码
URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main
替换为
URLSession(configuration: .default, delegate: self, delegateQueue:OperationQueue()
然后保持原样,
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if data.first != 255 {
fullData.append(data)
} else {
dataTask.cancel()
session.invalidateAndCancel()
UpdateInfoManager.createHouse(logData: self.fullData) {[weak self] (complete) in
DispatchQueue.main.async {
self?.house = HouseManager.house
if let house = self?.house {
self?.nameLabel.text = house.houseName
self?.menuController.house = house
self?.menuController.roomsTableView.reloadData()
self?.menuController.houseNameLabel.text = house.houseName
self?.spinner.stopAnimating()
self?.hideView.isHidden = true
self?.view.isUserInteractionEnabled = true
}
}
}
}
}