0

UITableViewアプリの初期読み込み中に複数の API リクエストを送信します。API リクエストが返されるたびに、新しい行を に追加しますUITableView。したがって、最初の読み込みでは、行がランダムな順序でランダムな時間に追加されます (ほとんどの場合、すべてが 1 秒以内に発生します)。

セルのセットアップ中に、Async メソッドを呼び出してMKMapKit MKMapSnapshotter画像を生成します。

以前は問題なく非同期の画像読み込みを使用していましたが、画像が間違ったセルに表示されることはめったになく、その理由がわかりません。

に切り替えてみましたDiffableDataSourceが、問題は残ります。

DiffableDataSourceの場合、画像の非同期が返されたときに呼び出されるセルにクロージャーを渡し、変更された場合に現在のセルをフェッチします。

let dataSource = DiffableDataSource(tableView: tableView) {
            (tableView, indexPath, journey) -> UITableViewCell? in
            
            let cell = tableView.dequeueReusableCell(withIdentifier: "busCell", for: indexPath) as! JourneyTableViewCell
            cell.setupCell(for: journey) { [weak self] () -> (cell: JourneyTableViewCell?, journey: Journey?) in
                
                if let self = self
                {
                    let cell = tableView.cellForRow(at: indexPath) as? JourneyTableViewCell
                    let journey = self.sortedJourneys()[safe: indexPath.section]
                    return (cell, journey)
                }
                return(nil, nil)
            }
            
            return cell
        }

これが私のセルセットアップコードです:

override func prepareForReuse() {
    super.prepareForReuse()
    
    setMapImage(nil)
    journey = nil
    asyncCellBlock = nil
}

func setupCell(for journey:Journey, asyncUpdateOriginalCell:@escaping JourneyOriginalCellBlock) {
    
    self.journey = journey
    
    // Store the async block for later
    asyncCellBlock = asyncUpdateOriginalCell
    
    // Map
    if let location = journey.location,
       (CLLocationCoordinate2DIsValid(location.coordinate2D))
    {
        // Use the temp cached image for now while we get a new image
        if let cachedImage = journey.cachedMap.image
        {
            setMapImage(cachedImage)
        }
        
        // Request an updated map image
        journey.createMapImage {
            [weak self] (image) in
            
            DispatchQueue.main.async {
                
                if let asyncCellBlock = self?.asyncCellBlock
                {
                    let asyncResult = asyncCellBlock()
                    if let cell = asyncResult.cell,
                       let journey = asyncResult.journey
                    {
                        if (cell == self && journey.id == self?.journey?.id)
                        {
                            self?.setMapImage(image)
                            
                            // Force the cell to redraw itself.
                            self?.setNeedsLayout()
                        }
                    }
                }
            }
        }
    }
    else
    {
        setMapImage(nil)
    }
}

UITableViewこれが短期間に数回更新されるだけの競合状態であるかどうかはわかりません。

4

2 に答える 2

0

これは、画像が利用可能な場合、そのインデックスが存在しないためだと思います。テーブル ビュー セルは再利用可能であるため、現在の画像がまだ読み込まれていないため、前の画像が読み込まれます。

if let cachedImage = journey.cachedMap.image
    {
        setMapImage(cachedImage)
    }
else {
        // make imageView.image = nil
}
于 2021-01-27T10:39:05.067 に答える