2017-12-19 5 views
0

ためnilを返す: func indexPath(for cell: UITableViewCell) -> IndexPath?UITableViewのindexPath(セルの場合:UITableViewCell) - > IndexPath?私は、このメソッドはnilを返している理由として少し混乱している可視セル

ことはここではいくつかのデバッガ出力です:

(lldb) po expandingCell 
<MyApp.BankDetailsTableViewCell: 0x7f9ec307da00; baseClass = UITableViewCell; frame = (0 495.01; 414 258); clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x60400003ffc0>> 

(lldb) po self.tableView.visibleCells 
▿ 8 elements 
    ▿ 0 : <MyApp.AddressTableViewCell: 0x7f9ec2e49600; baseClass = UITableViewCell; frame = (0 207.01; 414 70); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x60800022fc40>> 
    ▿ 1 : <MyApp.BankDetailsTableViewCell: 0x7f9ec307da00; baseClass = UITableViewCell; frame = (0 277.01; 414 258); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x60400003ffc0>> 
    ▿ 2 : <MyApp.TransactionLinkTableViewCell: 0x7f9ec585d800; baseClass = UITableViewCell; frame = (0 535.01; 414 70); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x600000025e60>> 
    - 3 : <MyApp.SeparatorTableViewCell: 0x7f9ec3003000; baseClass = UITableViewCell; frame = (0 605.01; 414 44); autoresize = W; layer = <CALayer: 0x604000225780>> 
    ▿ 4 : <MyApp.GenericFieldTableViewCell: 0x7f9ec3071a00; baseClass = UITableViewCell; frame = (0 649.01; 414 44); autoresize = W; layer = <CALayer: 0x604000226100>> 
    ▿ 5 : <MyApp.GenericFieldTableViewCell: 0x7f9ec28eb600; baseClass = UITableViewCell; frame = (0 693.01; 414 44); autoresize = W; layer = <CALayer: 0x6080004337a0>> 
    ▿ 6 : <MyApp.GenericFieldTableViewCell: 0x7f9ec590c800; baseClass = UITableViewCell; frame = (0 737.01; 414 44); autoresize = W; layer = <CALayer: 0x600000038b60>> 
    ▿ 7 : <MyApp.GenericFieldTableViewCell: 0x7f9ec5849000; baseClass = UITableViewCell; frame = (0 781.01; 414 44); autoresize = W; layer = <CALayer: 0x600000037080>> 

(lldb) 

あなたが拡大するセルがであることがわかります可視リスト(配列インデックス1)。では、なぜ私のコードがこれに対してnilを返すのですか?ここではいくつかの余分なコンテキストを与えること

if let indexPath = self.tableView.indexPath(for: expandingCell) { 

    // NEVER REACHES HERE. Returns nil    

} else { 
    log.warning("This shouldn't happen. The indexPath should be returned by tableView!") 
} 

、私はその後、細胞「isExpandedとして」にフラグを設定する必要があり、ボタンを押し、に対応しています、そして私は(self.tableView.beginUpdatesを呼び出す)と.endUpdates ()(heightForRow(at:...)の新しい値を提供しています)ので、セルの高さが拡大します。

+0

expandCellをどこに設定しますか? –

+0

通常通り。 cellForRowAtIndexPath:それは意味がありますか? – horseshoe7

+0

beginUpdatesおよびendUpdates内でreloadRowsを使用しましたか? –

答えて

0

私はこの方法をまったく好きではないので、私はそれをまったく犠牲にすることなく避けます。あなたが実際にインデックスパスが必要な場合は、データソースがセルを要求するときにそれを割り当てます。だからcellForRow私はカスタムセルをデキューし、そのデータオブジェクトとそのインデックスパスを割り当てます。

しかし、選択(ボタン押下)中にデータ(オブジェクトの配列など)が変更される可能性があるので、一般的にはもう一度悪い考え方です(他のデータソースに入れたり、あなたは再び自分が困っているかもしれません。

だから、最良の方法は、オブジェクトをセルに設定し、セルフをデリゲートとして割り当てることです。セルデリゲートは、デリゲートによってセルを消費するために使用される特定のオブジェクトのボタンがクリックされたことを通知する必要があります。

ビューコントローラがデータ

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell... 
     cell.object = dataSource[indexPath.row].object 
     cell.delegate = self 
     return cell 
    } 

private typealias DataObject = (object: MyObject, extended: Bool) // TODO: use class, not typealias so you can easily change "extended" property for it 
private var dataSource: [DataObject] = [] 
func setDataArray(array: [MyObject]) { 
    dataSource = array.map { (object: $0, extended: false) } // TODO: fetch extended from current data source if it exists, else use default 
    tableView.reloadData() 
} 

だから、行のためのセルは次のようになります。あなたのテーブルビューのとあなたのテーブルビューは、あなたがこれらのオブジェクトを挿入しますいくつかの方法を持っているタイプMyObjectのオブジェクトを示していることソースとの高さ行:今

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     dataSource[indexPath.row].extended ? 100.0 : 44.0 
    } 

細胞デリゲート:

func myCell(_ sender: MyCell, shouldToggleObjectBeingExtended object: MyObject) { 
    if let target = dataSource.first(where: { $0.object === object }) { 
     target.extended = !target.extended // To use this you must have a class instead of typealias 
     tableView.beginUpdates() 
     tableView.endUpdates() 
    } 
} 

私は、これはあなたがたが、通常は大幅で支払うようなシステムを作成しているものとは少し逆さまであるかもしれないと想像することができます。物事をより単純で安定したものにするために、ソースを変更するときは、テーブルビューから完全に切り離されています。あなたの状況を解決するのに役立つことを願っています。

私の経験では、その方法の「バグ」に関しては、これらは常にちょっと面白かったです。通常はいくつかの解決策がありますが、めったにきれいな解決策はありません。

+0

ありがとうございます。しかし、私は細胞を広げる方法を知る必要はありません。私はvisibleCellsの配列内のALSOであるセルが、IndexPathを返さない原因となっているのだろうかと思います。 – horseshoe7

+0

@ horseshoe7私は知っています。しかし、私はあなたに回避策を与えました。セルが表示されているか、インデックスパスが同じセルではない可能性があります。可視のセルが変更されたり、キューに移動したり、デキューされたりする場合があります。その場合は、おそらくインデックスパスがありません。これが機能しても、安定性とパフォーマンスの両方の理由から、この種のメソッドを使用しないようにする必要があります。 –

+0

私はvar indexPathを割り当てました:IndexPath? UITableViewCellサブクラスで、cellForRowAt ...に設定し、prepareForReuseでnilに設定します。 – horseshoe7

0

私は自分の質問にちょうど答えます。私にとってこれはUIKitのバグのように思えるが、とにかく、私はちょうどUITableViewCellのサブクラスに var indexPath: IndexPath? = nilを追加し、私はその後、私は、セルに直接何indexPath彼に尋ねることができ-tableView:cellForRowAt:でそれを設定し、prepareForReuse

にゼロに設定しますを表す。

理想的ではありませんが、機能します。

関連する問題