2016-10-22 7 views
2

iOS 10.0では、UICollectionViewはデフォルトでセルをプリフェッチします。これは、画面に表示されるように準備されているが、非表示になっているセルにつながります。このquestionは本当にうまく説明しています。セルのプリフェッチが有効な場合、UICollectionViewのdeselectItem

次のコードは、セルが表示されているか、まったく存在しない場合でも、インデックスパスの選択を解除します。セルが存在し、非表示になっている場合、インデックスパスは選択解除されますが、セルは再利用されるまで選択状態に留まります。

collectionView!.deselectItem(at: indexPath, animated: false) 

この問題は、プリフェッチがiOSの10.0にisPrefetchingEnabled = falseで無効になっているiOSの9かでない終了を行います。

これはUICollectionViewのバグですか、またはdeselectItemが動作するはずのことを誤解していますか?ここ


次のステップでこの動作を示しUICollectionViewControllerサブクラスの完全なコードである:細胞上

  • タップ、それはわずかに(赤)
  • スクロールセルを選択した状態になるように
  • 画面オフ、それはまだ見てどのように守ってバックスクリーン
  • 上のスクロールに
  • セルを「セルの選択を解除」ボタンをタップします別のセルに
  • タップを選択されたS
  • 両方のセルが
  • スクロールに最初のセル遠くオフスクリーンを選択見て、再び
  • は、最初のセルが最終的に選択を見ていないか確認してどのように守って


import UIKit 

private let reuseIdentifier = "Cell" 

class CollectionViewController: UICollectionViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) 

     let button = UIButton(frame: CGRect(x: 10, y: 30, width: 360, height: 44)) 
     button.backgroundColor = #colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 1) 
     button.setTitleColor(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1), for: .normal) 
     button.setTitleColor(#colorLiteral(red: 0.05882352963, green: 0.180392161, blue: 0.2470588237, alpha: 1), for: .highlighted) 
     button.setTitle("Deselect Cell", for: .normal) 
     button.addTarget(self, action: #selector(CollectionViewController.buttonPress), for: .touchUpInside) 
     view.addSubview(button) 
    } 

    func buttonPress() { 
     for indexPath in collectionView!.indexPathsForSelectedItems ?? [IndexPath]() { 

      let cell = collectionView!.cellForItem(at: indexPath) 
      NSLog("Deselecting indexPath: %@, cell: %@", indexPath.description, cell?.frame.debugDescription ?? "not visible") 

      collectionView!.deselectItem(at: indexPath, animated: false) 
     } 
    } 

    override func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return 300 
    } 

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) 
     cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) 
     cell.selectedBackgroundView = UIView(frame: cell.bounds) 
     cell.selectedBackgroundView!.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1) 
     return cell 
    } 
} 

答えて

1

は、私の知る限り、これを言うことができるようにUICollectionViewのバグである、と私は」自分でレーダーを開けました。より多くの圧力をかけるためにもそうしたいと思うかもしれません。

プリフェッチ前であっても、コレクションビューは表示されなかったセルの選択を解除しませんでした。 cellForItemAtIndexPath:でも、表示されていないセルに対してはnilが返されると記載されています。

しかし、プリフェッチする前に、セルがコンテンツビューを出ると直ちに再利用プールに追加され、スクロールバックすると再選択されたセルが選択状態にリセットされます。

これで、そのセルはロードされたままになり、プリフェッチ領域を超えてさらにスクロールして再利用されるまでリセットされません。あなたはNOprefetchingEnabledを設定するか、これを修正し、セルが表示されたときにその利点、または更新選択状態を失う

-

- (void)collectionView:(UICollectionView *)collectionView 
     willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 
    if (!cell.isSelected) { 
    return; 
    } 

    if ([[collectionView indexPathsForSelectedItems] containsObject:indexPath]) { 
    return; 
    } 

    cell.selected = NO; 
} 

これは、パフォーマンスを低下させていないようです。

+0

このコードでは、選択されていないセルが選択されて表示される問題を解決しますが、セルが選択されると選択解除されて表示される可能性があることに注意してください。 – user3246268

+0

@ user3246268これはこの特定のケースでは問題ではありません。問題はプリフェッチ領域内のセルですが、選択されたセルは選択されたままです。なぜなら、システムはそれらのセルに対して 'prepareForReuse'を呼び出さないからです。すべての目的のために、目に見えない間にプログラムで選択を解除すると、セルが選択解除されないという事実を除いて、まだ見えているセルです。システムが誤ってそれを行うべきポイントがないと仮定した場合、とにかく準備が整った後に表示されます。 –

関連する問題