2016-05-24 5 views
0

私は理由は「再利用可能な細胞」のセルを更新して苦労してきたダウンロードマネージャを作っています....なぜこのようにUITableViewのセルを更新するのは間違っていますか?

私はスクロールした後、細胞を更新して問題を抱えていたが、私はdoesnの回避策を見つけましたこの方法では、セルが表示されなくなった後にクラッシュするようにアプリケーションを誘導しています。どうしてあなたが説明できることを願っているのか分からず、修正方法を知っていれば教えてください。

NSURLSessionDownloadTask

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { 

    for (index, downloadModel) in downloadingArray.enumerate() { 
     if downloadTask.isEqual(downloadModel.downloadTask) { 
      dispatch_async(dispatch_get_main_queue(), { 

       let indexPath = NSIndexPath(forRow: index, inSection: 0) 
       /* xCode stops here when the app crashes */ let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! RCHDownloadAddictTableViewCell 
       let countOfBytesWritten: Double! 
       if totalBytesExpectedToWrite < 0 { 

        countOfBytesWritten = 0 

       } else { 

        countOfBytesWritten = Double(totalBytesWritten)/Double(totalBytesExpectedToWrite) 

       } 

       downloadModel.fileName = downloadTask.response?.suggestedFilename 
       downloadModel.downloadIndex = downloadingArray.indexOf(downloadModel) 
       downloadModel.downloadSize = Double(totalBytesExpectedToWrite) 
       downloadModel.downloadProgress = Float(countOfBytesWritten) 
       downloadModel.downloadTaskIdentifier = downloadTask.taskIdentifier 
       downloadModel.didFinishDownload = false 

       self.updateCell(cell, forRowAt: indexPath) 

      }) 
     } 
    } 


} 

を呼び出し、これは、セルが更新さやり方で取得し、このメソッドのダウンロードを開始したとき、私はダウンロードタスクをこのよう

func addDownloadTask(URL: NSURL) { 

    let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration() 
    let mainQueue = NSOperationQueue.mainQueue() 
    let session = NSURLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: mainQueue).downloadTaskWithURL(URL) 

    let newDownload = RCHDownloadAddictModelClass(fileURL: URL) 

    newDownload.downloadTask = session 

    downloadingArray.append(newDownload) 

    newDownload.downloadIndex = downloadingArray.indexOf(downloadingArray.last!) 

    self.tableView.reloadData() 

    session.resume() 

} 

を追加します。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCellWithIdentifier("downloadCell", forIndexPath: indexPath) as! RCHDownloadAddictTableViewCell 

    updateCell(cell, forRowAt: indexPath) 

    return cell 
} 



func updateCell(cell: RCHDownloadAddictTableViewCell, forRowAt indexPath: NSIndexPath) { 

    let arrayInfo = downloadingArray[indexPath.row] 

    cell.cellProgressView.setProgress((arrayInfo.downloadProgress)!, animated: true) 
    cell.cellFileName.text = arrayInfo.fileName 
    cell.cellDownloadSpeed.text = String(format: "%.1fMB", (arrayInfo.downloadSize/1000000)) 
    cell.cellBlock = { 

     switch arrayInfo.downloadTask.state { 
     case .Running: 
      arrayInfo.downloadTask.suspend() 
      cell.cellButton.setImage(UIImage(named: "resume.png"), forState: UIControlState.Normal) 
     case .Suspended: 
      arrayInfo.downloadTask.resume() 
      cell.cellButton.setImage(UIImage(named: "pause.png"), forState: UIControlState.Normal) 
     default: 
      arrayInfo.downloadTask.suspend() 
      cell.cellButton.setImage(UIImage(named: "resume.png"), forState: UIControlState.Normal) 
     } 

    } 

    if (arrayInfo.didFinishDownload == true) { 
     cell.cellButton.hidden = true 
     cell.cellFinishIndicator.text = "Finished." 
     cell.cellProgressView.hidden = true 
     cell.cellFinishIndicator.hidden = false 
    } else { 
     cell.cellButton.hidden = false 
     cell.cellProgressView.hidden = false 
     cell.cellFinishIndicator.hidden = true 
    } 

} 

答えて

0

あなたはAppleの文書でそれを見ることができます:

public func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? 
// returns nil if cell is not visible or index path is out of range 

//cell will be nil when this row is not visible 
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! RCHDownloadAddictTableViewCell 

その後、あなたはそれがあなたが1つの例外を除いて、あなたのコードで正しい道にいる

+0

それでは、毎回 'self.tableView.reloadData()'を呼び出さずにどうすれば更新できますか? – Raffi

+0

tableview.visibleCellsでセルをチェックする –

+0

セルがnilであるかどうかをチェックするだけで十分である:-) –

0

をクラッシュしますself.updateCell(cell, forRowAt: indexPath)呼び出します。

ダウンロードが完了すると、あなたがコードを実行する必要があり、正しい場所に配列に正しいデータを格納した後...

tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic) 

これは、その後で、細胞を再ロードする表をトリガーします正しいインデックスパス。そのセルが画面に表示されている場合は、再読み込みされます。そのセルが画面に表示されていない場合は、リロードされません。しかし、次にセルが表示されたら、正しい情報が表示されます。

本質的に。セルを直接更新しないでください。あなたはその特定の行のデータを変更したことをtableviewに伝えてください。

+0

私はこれを追加します!、私は直接私が更新している理由ですダウンロードメイトのライブフィードバックが欲しいです。ありがとう:) – Raffi

+0

@ Raffiこれは間違いなく、セルの進捗状況を更新するために使用することができます。しかし、それはtableviewを介して行います。 WilsonXJが指摘したように。行がまだ画面上にあるかどうかわからない場合は、参照している 'セル'が異なる行のデータを表示する画面に表示されます。そのセルが「Sarah」の行にあるときに、ラベルを「David」と更新することがあります。 (例えば)。 – Fogmeister

+0

私は今あなたの例を理解していますが、私はtableview経由でセルを更新する方法を理解できませんより明確にすることができますか? – Raffi

関連する問題