2017-04-19 5 views
0

サーバーに画像をアップロードするための進捗インジケータを作成しようとしています!私の目標は、UIProgressViewUILabelを含むUIViewをアップロードして写真の現在の状態を表示することです。Swift 3:DispatchQueue URLSessionのタイミング

私のコードは私のサーバーに画像をオフに送信し、それが(progressImagesを参照)、次の画像へのループUILabelを更新中(lblImagesRemainingを参照)とUIProgressViewべきたびに。

は私が取得することができた UIView表示され、多少の進捗状況を更新する(参照を viewUploadBox与えられた)が、私はそれに 完全仕事を得るように見えることはできません。 viewUploadBoxが表示されますが、 lblImagesRemainingprogressImagesも、アップロードプロセスが〜70%完了するまで更新されません。しかし、一度それが〜70%の完成をヒットしても、イメージが送信されるたびにアップデートされます。 Upload Testボタンがトリガーされる前に

はここに私のUIViewControllerです: enter image description here

Upload Testボタンが最初にトリガーされるとここに私のUIViewControllerです: enter image description here

をここでアップロードプロセスが〜70%が完了したら、私のUIViewControllerです。 enter 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

ここには混乱するコードがたくさんあります。あなたはあなたの 'uploadTest'メソッドに' imageCount'を渡します。しかし、あなたはwhileループを7回反復するようにハードコードしています。どうして?次に、 'imageDictionary'のキーと値を繰り返すループがあります。それぞれのキー/値のペアに対して新しい 'URLSession'を開始します。どうして? – rmaddy

+0

カスタムテストクラスである7つの 'Test'オブジェクトがあります。 'uploadTest'コードの先頭にある' collectImages'メソッドは、7つの異なる辞書を作成し、アップロードする必要がある画像の数を 'imageCount'に伝えます。 'getImageDictionairy(i)'メソッドは、7つの辞書を循環させるために使用されます。これには常に7つの辞書がありますので、whileループでハードコードされています。新しい 'URLSession'については、それはコーディングの無知にまで下がるかもしれません。複数のURLSessionを使わずに異なるキーと値のペアを持つ76の画像をアップロードするより適切な方法が分かりません –

答えて

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 

2番目と3番目の '列'の値の違いを参照してください。 2番目はプログレスバーのように見え、3番目はあなたが望むものです。

フムを、私たちは、シリアルキューが同時からディスパッチ使用して...のはそれ

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 

あり仕上がっ同時タスクを注文する保証するものではありませんが、私たちの進行状況が正しく表示されます。

関連する問題