Swift 3 - DispatchQueue 内部函数
Swift 3 - Function Inside DispatchQueue
我在 DispatchQueue.main.async
中调用了一个函数。这是我的代码:
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
for i in 0 ... (Global.selectedIcons.count - 1) {
if self.albumorphoto == 1 {
if i == 0 {
self.detector = 1
self.uploadPhoto() //here
}
else {
self.detector = 2
self.uploadPhoto() //here
}
}
else {
self.uploadPhoto() //here
}
}
group.leave()
}
group.notify(queue: .main) {
print("done")
}
}
func uploadPhoto(){
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let params = param
request.httpBody = params.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error!)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response!)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString!)")
if self.detector == 1 {
self.album = self.parseJsonData(data: data)
}
}
task.resume()
}
func parseJsonData(data: Data) -> [AnyObject] {
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
let jsonalbum = jsonResult!["data"] as? [AnyObject]
for jsonAlbum in jsonalbum! {
self.folderID = jsonAlbum["id"] as! String
}
} catch {
print(error)
}
return album
}
我想让它等到 DispathcQueue
中的所有任务完成。它可以工作,但问题是我的函数 uploadPhoto()
。它不能等到 uploadPhoto()
完成它的任务。有解决这个问题的想法吗?谢谢!
在这里使用 DispatchGroup
是正确的选择,但是对于每个异步任务你必须 enter
和 leave
:
let group = DispatchGroup()
photos.forEach { photo in
group.enter()
// create the request for the photo
URLSession.shared.dataTask(with: request) { data, response, error in
group.leave()
// handle the response
}.resume()
}
group.notify(queue: .main) {
print("All photos uploaded.")
}
您不需要 DispatchQueue.async()
调用,因为 URLSession.shared.dataTask
已经是异步的。
在我的代码中,我假设您想将对象建模为 Photo
并将 Global.selectedIcons.count
替换为 photos
数组:
class Photo {
let isAlbum: Bool
let isDefector: Bool
let imageData: Data
}
我建议您查看 Alamofire and SwiftyJSON 以进一步改进您的代码。这些是流行的库,可以更轻松地处理网络请求。使用它们,您几乎可以将整个 uploadPhoto()
/parseJsonData()
函数简化为如下所示:
Alamofire.upload(photo.imageData, to: url).responseSwiftyJSON { json in
json["data"].array?.compactMap{ [=12=]["id"].string }.forEach {
self.folderID = [=12=]
}
}
这使您的代码更加稳定,因为它删除了所有强制解包。 Alamofire 还为您提供上传进度和恢复和取消请求等功能。
我在 DispatchQueue.main.async
中调用了一个函数。这是我的代码:
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
for i in 0 ... (Global.selectedIcons.count - 1) {
if self.albumorphoto == 1 {
if i == 0 {
self.detector = 1
self.uploadPhoto() //here
}
else {
self.detector = 2
self.uploadPhoto() //here
}
}
else {
self.uploadPhoto() //here
}
}
group.leave()
}
group.notify(queue: .main) {
print("done")
}
}
func uploadPhoto(){
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let params = param
request.httpBody = params.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error!)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response!)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString!)")
if self.detector == 1 {
self.album = self.parseJsonData(data: data)
}
}
task.resume()
}
func parseJsonData(data: Data) -> [AnyObject] {
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
let jsonalbum = jsonResult!["data"] as? [AnyObject]
for jsonAlbum in jsonalbum! {
self.folderID = jsonAlbum["id"] as! String
}
} catch {
print(error)
}
return album
}
我想让它等到 DispathcQueue
中的所有任务完成。它可以工作,但问题是我的函数 uploadPhoto()
。它不能等到 uploadPhoto()
完成它的任务。有解决这个问题的想法吗?谢谢!
在这里使用 DispatchGroup
是正确的选择,但是对于每个异步任务你必须 enter
和 leave
:
let group = DispatchGroup()
photos.forEach { photo in
group.enter()
// create the request for the photo
URLSession.shared.dataTask(with: request) { data, response, error in
group.leave()
// handle the response
}.resume()
}
group.notify(queue: .main) {
print("All photos uploaded.")
}
您不需要 DispatchQueue.async()
调用,因为 URLSession.shared.dataTask
已经是异步的。
在我的代码中,我假设您想将对象建模为 Photo
并将 Global.selectedIcons.count
替换为 photos
数组:
class Photo {
let isAlbum: Bool
let isDefector: Bool
let imageData: Data
}
我建议您查看 Alamofire and SwiftyJSON 以进一步改进您的代码。这些是流行的库,可以更轻松地处理网络请求。使用它们,您几乎可以将整个 uploadPhoto()
/parseJsonData()
函数简化为如下所示:
Alamofire.upload(photo.imageData, to: url).responseSwiftyJSON { json in
json["data"].array?.compactMap{ [=12=]["id"].string }.forEach {
self.folderID = [=12=]
}
}
这使您的代码更加稳定,因为它删除了所有强制解包。 Alamofire 还为您提供上传进度和恢复和取消请求等功能。