Swift 3:通过URLSession进行DispatchQueue计时

时间:2017-04-19 22:34:14

标签: ios swift grand-central-dispatch nsurlsession

我正在尝试创建一个进度指示器,用于将图像上传到我的服务器!我的目标是让UIView包含UIProgressViewUILabel,以显示正在上传的照片的当前状态。

每当我的代码将图像发送到我的服务器时,它应该在更新UILabel(引用lblImagesRemaining)和UIProgressView(引用{{progressImages时循环到下一张图片。 1}})。

我能够显示UIView(给定引用viewUploadBox)并稍微更新进度,但我似乎无法将其完全 工作。系统会显示viewUploadBox,但lblImagesRemainingprogressImages都不会更新,直到上传过程完成约70%。虽然,一旦达到约70%的完成率,每次发送图像时都会有更新。

UIViewController按钮被触发之前,这是我的Upload Testenter image description here

首次触发UIViewController按钮后,这是我的Upload Testenter image description here

上传过程完成约70%后,这是我的UIViewControllerenter image description here

这是我的代码:

@IBAction func uploadTest(_ sender: Any) {
        let imageCount = collectImages() // Collect images also prepares the tests with dictionaries for images to upload.
        DispatchQueue.main.async {
            self.viewUploadBox.isHidden = false
            self.lblImagesRemaining.text = "Images Remaining: " + String(imageCount)
            self.view.alpha = 0.5
            self.viewUploadBox.alpha = 1.5
        }
        let time = DispatchTime.now() + 0.01
        DispatchQueue.main.asyncAfter(deadline: time) { // The asyncAfter was used to ensure that the viewUploadBox appeared.
            self.uploadTest(imageCount: imageCount)
        }
    }


func uploadTest(imageCount: Int) {
        let progressFactor = 1.0 / Double(imageCount)
        var i = 1
        var imagesRemaining = imageCount
        while i < 8 {
            let imageDictionary = projectHandler.testHandler.getImageDictionary(i)
            let test = imageDictionary["test"] as! String
            for (key, value) in imageDictionary {
                if key == "test" || key == "count" {
                    continue
                }
                let url = NSURL(string: "http://IMAGEUPLOADLOCATION.PHP")
                let request = NSMutableURLRequest(url: url! as URL)
                request.httpMethod = "POST"
                let boundary = generateBoundaryString()
                //define the multipart request type
                request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
                let image_data = UIImageJPEGRepresentation((value as! UIImage), 0.2)
                let body = NSMutableData()
                let constructedName = userdata.valueForKey("name_full") + "(ID-" + userdata.valueForKey("id_ACCOUNT") + ")"
                let parameters = [
                    "name" : constructedName,
                    "project" : projectHandler.projectName,
                    "picturefile" : key + ".jpeg",
                    "testname" : test,
                    "projectid" : projectHandler.idPROJECT,
                    "accountid" : userdata.valueForKey("id_ACCOUNT"),
                    "brazerid" : projectHandler.idBrazer]
                //define the data post parameter
                for (key, value) in parameters {
                    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
                    body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
                    body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
                    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
                }
                let fname = "image"
                let mimetype = "image/jpeg"
                body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
                body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fname); \"\r\n".data(using: String.Encoding.utf8)!)
                body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
                body.append(image_data!)
                body.append("\r\n".data(using: String.Encoding.utf8)!)
                body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
                request.httpBody = body as Data
                let session = URLSession.shared
                session.dataTask(with: request as URLRequest, completionHandler: {
                    (data, response, error) in
                    if(error != nil){
                        print("error")
                    } else {
                            do {
                            let dataString = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
                            print("Response: \(response!)")
                            print("Data: \(data!)")
                            print(dataString)
                        } catch {
                            print(error)
                        }
                    }
                    DispatchQueue.main.async {
                        self.progressImages.progress += Float(progressFactor)
                        imagesRemaining -= 1
                        self.lblImagesRemaining.text = "Images Remaining: " + String(imagesRemaining)
                        if imagesRemaining == 0 {
                            self.viewUploadBox.isHidden = true
                            self.btnEmail.isEnabled = true
                            self.view.alpha = 1.0
                        }
                    }
                }).resume()
            }
            i += 1
        }
    }

1 个答案:

答案 0 :(得分:1)

这似乎是一种竞争条件。尝试下一个片段。

import PlaygroundSupport
import Dispatch
PlaygroundPage.current.needsIndefiniteExecution = true

let q = DispatchQueue(label: "test") // serial queue

var j = 0

DispatchQueue.concurrentPerform(iterations: 10) {  i in
    q.async {
        j += 1
        DispatchQueue.main.async {
            print(i, j)
        }
    }
}

print("total",j)

检查代码,尝试想象代码将打印出来并将结果与​​您的期望进行比较: - )

打印

total 6
0 10
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10

这是你期望的吗?

让我们尝试一些更高级的东西: - )

import PlaygroundSupport
import Dispatch
PlaygroundPage.current.needsIndefiniteExecution = true

let q = DispatchQueue(label: "test") // serial queue

class S {
    let q = DispatchQueue(label: "sync", attributes: .concurrent)
    private var v: Int = 0
    func add(i: Int) {
        q.async(flags: .barrier) {
            self.v += i
        }
    }
    var i: Int {
        get {
            return q.sync {
                return v
            }
        }
    }
}

let s = S()

DispatchQueue.concurrentPerform(iterations: 10) {  i in
    q.async {
        s.add(i: 1)
        let k = s.i
        DispatchQueue.main.async {
            print(i, s.i, k)
        }
    }
}

看起来好多了,但再次检查结果。

0 4 1
1 4 2
2 4 3
3 4 4
4 6 5
5 6 6
6 8 7
7 8 8
8 10 9
9 10 10

查看第二个和第三个“列”中值之间的差异。第二个看起来像你的进度条,第三个是你想要的。

嗯,但是我们使用从并发调度的串行队列...让我们将其删除

import Dispatch
PlaygroundPage.current.needsIndefiniteExecution = true


class S {
    let q = DispatchQueue(label: "sync", attributes: .concurrent)
    private var v: Int = 0
    func add(i: Int) {
        q.async(flags: .barrier) {
            self.v += i
        }
    }
    var i: Int {
        get {
            return q.sync {
                return v
            }
        }
    }
}

let s = S()

DispatchQueue.concurrentPerform(iterations: 10) {  i in
        s.add(i: 1)
        let k = s.i
        DispatchQueue.main.async {
            print(i, s.i, k)
        }
}

我们又开始......

1 10 4
0 10 4
3 10 4
2 10 5
5 10 7
4 10 7
6 10 7
7 10 10
8 10 10
9 10 10

<强>解决方案

import PlaygroundSupport
import Dispatch
PlaygroundPage.current.needsIndefiniteExecution = true

class S {
    let q = DispatchQueue(label: "sync", attributes: .concurrent)
    private var v: Int = 0
    func add(i: Int) {
        q.async(flags: .barrier) {
            self.v += i
            let k = self.v
            DispatchQueue.main.async {
                print("update progress", k)
            }
        }
    }
    var i: Int {
        get {
            return q.sync {
                return v
            }
        }
    }
}

let s = S()

DispatchQueue.concurrentPerform(iterations: 10) {  i in
    s.add(i: 1)
    print(i, s.i)
}

打印

0 3
1 5
2 5
3 5
4 7
5 9
8 9
7 9
6 9
9 10
update progress 1
update progress 2
update progress 3
update progress 4
update progress 5
update progress 6
update progress 7
update progress 8
update progress 9
update progress 10

无法保证并发任务的完成顺序,但我们的进度已正确显示。