2017-05-02 3 views
0

私はSwiftを学習しています。私には一つの問題がある。SwiftのDispatchQueue.main.async/Block/Closureを使用してデータモデルを更新する方法

問題 - 私は画像URLを持つDataModelを持っていますので、初めてURLから画像をダウンロードし、もちろん2回目はダウンロードしません。だから私は私のブロック内の画像を取得しているときに私は画像で私のデータモデルを更新したい。しかし、それは動作しません。私は戻って

ViewController.swift

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell 

    var model = offersArray[indexPath.row] as! OffersModel 
    cell.updateOfferCellWith(model: model, completionHandler: { image in 
     model.image = image 
    })///// I am getting image here, but model is not getting update 
    return cell 
} 

Cell.Swift

func updateOfferCellWith(model: OffersModel, completionHandler:@escaping (UIImage) -> Void) { 

    if (model.image != nil) { //Second time this block should be execute, but model image is always nil 
     DispatchQueue.main.async { [weak self] in 
      self?.offerImageView.image = model.image 
     } 
    } 
    else{ 
     //First time- Download image from URL 
     ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in 
      DispatchQueue.main.async {[model] in 
       var model = model 
       self?.offerImageView.image = image 
       //model.image = image*//This is also not working* 
       completionHandler(image)*//Call back* 
      } 
     } 
    } 
} 
を呼び出すcompletionHanderまたinoutの機能を
  • を試してみました

  • +0

    'OffersModel'は' struct'ですか? – Sulthan

    +0

    これは危険な方法です。なぜなら、ユーザーがスクロールしてセルが画面から消えると、予期しない動作が起こるからです。 [LazyTableImages](https://developer.apple.com/library/content/samplecode/LazyTableImages/Introduction/Intro.html)をご覧ください。 – vadian

    +0

    はい@スルタン、それは構造化されています。今私はクラスとその作業について変更しました。今のところ、completionHandler呼び出しを取り消し、完了したときに直接更新しました。私たちがcompletionHandlerを使用するとBTWはnoescapingする必要があります。これはSwift 3のデフォルトです...正しいのですか? – user7167475

    答えて

    0

    コメントmodelstructあります。

    struct(または任意の値型)をメソッドに渡すか、変数に代入すると、structがコピーされます。

    したがって、は実際にmodelという新品にimageを割り当てていますが、元のmodelには割り当てません。

    リファレンスタイプ(class)を使用すると修正されます。

    0

    以下はコードに基づく潜在的な解決策ですが、これはコメント内でvadainが述べたように、イメージの読み込みが非同期でセルがなくなった時点でイメージを返す可能性があるため危険です。

    あなたがしたいのは、永続的な方法でモデルを設定し、画像をダウンロードするための非同期要求を送信するのが理想です。次に、画像が戻ってくるとモデルを更新し、モデルはその画像が更新されたというメッセージをブロードキャストします。セルは、存在するモデルの更新をリスンして応答することができます。

    FUNC用のtableView(_のtableView:のUITableView、cellForRowAt indexPath:IndexPath) - >のUITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "OffersTableCell", for: indexPath) as! OffersTableCell 
    
        var model = offersArray[indexPath.row] as! OffersModel 
    
        if image = model.image { 
         // setting directly here... you could call an image on the cell if you want more data encapuslation 
         cell.offerImageView.image = model.image 
        } else { 
         ImageDownloader.downloadImage(imageUrl: model.offerImageURL) { [weak self] image in 
          DispatchQueue.main.async { 
           model.image = image 
           cell.offerImageView.image = image 
          } 
         } 
        } 
    
        return cell 
    } 
    
    関連する問題