web-dev-qa-db-ja.com

UITableViewCellからUITableViewを取得する方法は?

オブジェクトにリンクされているUITableViewCellがあり、セルが表示されるかどうかを確認する必要があります。私が行った調査から、これは何らかの形でそれを含むUITableViewにアクセスする必要があることを意味します(そこから、それが見えるかどうかを確認するいくつかの方法があります)。だから、UITableViewCellUITableViewへのポインターを持っているのか、それともセルからポインターを取得する他の方法があったのだろうかと思っています。

97
sinθ

IOSのバージョンチェックを回避するには

id view = [tableViewCellInstance superview];

while (view && [view isKindOfClass:[UITableView class]] == NO) {
    view = [view superview]; 
}

    UITableView *tableView = (UITableView *)view;
151
Muhammad Idris

IOS7ベータ5では、UITableViewWrapperViewUITableViewCellのスーパービューです。 UITableViewUITableViewWrapperViewのスーパービューでもあります

IOS 7のソリューションは

UITableView *tableView = (UITableView *)cell.superview.superview;

そのため、iOS 6までのiOS向けのソリューションは

UITableView *tableView = (UITableView *)cell.superview;

48
KGS-12

Swift 5拡張

再帰的に

extension UIView {
    func parentView<T: UIView>(of type: T.Type) -> T? {
        guard let view = superview else {
            return nil
        } 
        return (view as? T) ?? view.parentView(of: T.self)
    }
}

extension UITableViewCell {
    var tableView: UITableView? {
        return parentView(of: UITableView.self)
    }
}

ループを使用する

extension UITableViewCell {
    var tableView: UITableView? {
        var view = superview
        while let v = view, v.isKind(of: UITableView.self) == false {
            view = v.superview
        }
        return view as? UITableView
    }
}
33

IOS7以前は、セルのスーパービューはそれを含むUITableViewでした。 iOS7の時点でGM(したがって、おそらく一般公開にもなります)セルのスーパービューはUITableViewWrapperViewであり、そのスーパービューはUITableViewです。この問題には2つの解決策があります。

解決策1:UITableViewCellカテゴリーを作成する

@implementation UITableViewCell (RelatedTable)

- (UITableView *)relatedTable
{
    if ([self.superview isKindOfClass:[UITableView class]])
        return (UITableView *)self.superview;
    else if ([self.superview.superview isKindOfClass:[UITableView class]])
        return (UITableView *)self.superview.superview;
    else
    {
        NSAssert(NO, @"UITableView shall always be found.");
        return nil;
    }

}
@end

これはcell.superviewを使用するための優れたドロップイン置換であり、既存のコードのリファクタリングを簡単にします。検索して[cell relatedTable]に置き換え、ビュー階層が変更された場合にアサートをスローします。または、将来的に元に戻すと、テストですぐに表示されます。

解決策2:弱いUITableView参照をUITableViewCellに追加する

@interface SOUITableViewCell

   @property (weak, nonatomic) UITableView *tableView;

@end

これははるかに優れた設計ですが、既存のプロジェクトで使用するには、もう少しコードのリファクタリングが必要になります。 tableView:cellForRowAtIndexPathで、SOUITableViewCellをセルクラスとして使用するか、カスタムセルクラスがSOUITableViewCellからサブクラス化されていることを確認し、セルのtableViewプロパティにtableViewを割り当てます。セル内では、self.tableViewを使用して、含まれているテーブルビューを参照できます。

24
memmons

Swift 2.2ソリューション。

特定のタイプのビューを再帰的に検索するUIViewの拡張機能。

import UIKit

extension UIView {
    func lookForSuperviewOfType<T: UIView>(type: T.Type) -> T? {
        guard let view = self.superview as? T else {
            return self.superview?.lookForSuperviewOfType(type)
        }
        return view
    }
}

またはよりコンパクト(カビロベライのおかげ):

import UIKit

extension UIView {
    func lookForSuperviewOfType<T: UIView>(type: T.Type) -> T? {
        return superview as? T ?? superview?.superviewOfType(type)
    }
}

あなたのセルであなたはそれを呼ぶだけです:

let tableView = self.lookForSuperviewOfType(UITableView)
// Here we go

CellForRowAtIndexPathの実行後にのみUITableViewCellがUITableViewに追加されることに注意してください。

7
Mehdzor

表示されている場合、スーパービューがあります。そして...驚き...スーパービューはUITableViewオブジェクトです。

ただし、スーパービューを持つことは、画面に表示されることを保証するものではありません。ただし、UITableViewには、どのセルが表示されるかを決定するメソッドが用意されています。

いいえ、セルからテーブルへの専用の参照はありません。ただし、UITableViewCellをサブクラス化する場合は、UITableViewCellを導入し、作成時に設定できます。 (サブビューの階層構造を考える前に、私はそれをかなりしました。)

iOS7の更新: Appleは、ここでサブビュー階層を変更しました。文書化されていない詳細なものを扱う場合、いつものように、常に物事が変わるリスクがあります。 UITableViewオブジェクトが最終的に見つかるまで、ビュー階層を「クロールアップ」することははるかに効率的です。

7
Hermann Klecker

スーパービューを呼び出したり、レスポンダーチェーンを介して何とかしてやろうとすると、非常に壊れやすくなります。セルが何かを知りたい場合、これを行う最善の方法は、セルが尋ねたい質問に答える何らかのメソッドに応答するオブジェクトをセルに渡し、コントローラーに答えを決定するロジックを実装させることです(あなたの質問から、セルは何かが見えるかどうかを知りたいと思います)。

セルにデリゲートプロトコルを作成し、セルのデリゲートをtableViewControllerに設定し、tableViewCotroller内のすべてのUI「制御」ロジックを移動します。

テーブルビューのセルは、情報のみを表示するダムビューである必要があります。

6
Javier Soto

UITableViewCellにカテゴリを作成して、その親tableViewを取得します。

@implementation UITableViewCell (ParentTableView)


- (UITableView *)parentTableView {
    UITableView *tableView = nil;
    UIView *view = self;
    while(view != nil) {
        if([view isKindOfClass:[UITableView class]]) {
            tableView = (UITableView *)view;
            break;
        }
        view = [view superview];
    }
    return tableView;
}


@end

ベスト、

6
boliva

上記の回答に基づいたSwiftバージョンです。後で使用するためにExtendedCellに一般化しました。

import Foundation
import UIKit

class ExtendedCell: UITableViewCell {

    weak var _tableView: UITableView!

    func rowIndex() -> Int {
        if _tableView == nil {
            _tableView = tableView()
        }

        return _tableView.indexPathForSelectedRow!.row
    }

    func tableView() -> UITableView! {
        if _tableView != nil {
            return _tableView
        }

        var view = self.superview
        while view != nil && !(view?.isKindOfClass(UITableView))! {
            view = view?.superview
        }

        self._tableView = view as! UITableView
        return _tableView
    }
}

このヘルプを願っています:)

3
hqt
UITableView *tv = (UITableView *) self.superview.superview;
BuyListController *vc = (BuyListController *) tv.dataSource;
2
Gank

上記の回答から少し借りて修正し、次のスニペットを作成しました。

- (id)recursivelyFindSuperViewWithClass:(Class)clazz fromView:(id)containedView {
    id containingView = [containedView superview];
    while (containingView && ![containingView isKindOfClass:[clazz class]]) {
        containingView = [containingView superview];
    }
    return containingView;
}

クラスを渡すと、他の場合にUITableView以外のビューを走査および取得するための柔軟性が提供されます。

2
Azu

このソリューションは、UITableViewWrapperViewオブジェクトがiOS7 beta5のUITableViewCellオブジェクトのスーパービューであるというGabeの提案に基づいています。

サブクラスUITableviewCell

- (UITableView *)superTableView
{
    return (UITableView *)[self findTableView:self];
}

- (UIView *)findTableView:(UIView *)view
{
    if (view.superview && [view.superview isKindOfClass:[UITableView class]]) {
        return view.superview;
    }
    return [self findTableView:view.superview];
}
2
Carina

この問題に対する私のソリューションは、他のソリューションと多少似ていますが、エレガントなforループを使用しており、短いです。また、将来に対応する必要があります。

- (UITableView *)tableView
{
    UIView *view;
    for (view = self.superview; ![view isKindOfClass:UITableView.class]; view = view.superview);
    return (UITableView *)view;
}
2
Bensge

スーパービューの代わりに、["UItableViewvariable" visibleCells]を使用してみてください。

これをforeachループで使用して、アプリが表示して動作したセルをループしました。

for (UITableView *v in [orderItemTableView visibleCells])//visibleCell is the fix.
{
  @try{
    [orderItemTableView reloadData];
    if ([v isKindOfClass:[UIView class]]) {
        ReviewOrderTableViewCell *cell = (ReviewOrderTableViewCell *)v;
        if (([[cell deleteRecord] intValue] == 1) || ([[[cell editQuantityText] text] intValue] == 0))
            //code here 
    }
  }
}

魅力のように機能します。

1
user2497493

最小限のテストですが、この一般的ではないSwift 3の例は動作するようです:

extension UITableViewCell {
    func tableView() -> UITableView? {
        var currentView: UIView = self
        while let superView = currentView.superview {
            if superView is UITableView {
                return (superView as! UITableView)
            }
            currentView = superView
        }
        return nil
    }
}
1
Murray Sagal
extension UIView {
    func parentTableView() -> UITableView? {
        var viewOrNil: UIView? = self
        while let view = viewOrNil {
            if let tableView = view as? UITableView {
                return tableView
            }
            viewOrNil = view.superview
        }
        return nil
    }
}
0
neoneye

1行のコードで取得できます。

UITableView *tableView = (UITableView *)[[cell superview] superview];
0
UITableViewCell Internal View Hierarchy Change in iOS 7

Using iOS 6.1 SDK

    <UITableViewCell>
       | <UITableViewCellContentView>
       |    | <UILabel>

Using iOS 7 SDK

    <UITableViewCell>
       | <UITableViewCellScrollView>
       |    | <UIButton>
       |    |    | <UIImageView>
       |    | <UITableViewCellContentView>
       |    |    | <UILabel>


The new private UITableViewCellScrollView class is a subclass of UIScrollView and is what allows this interaction:


![enter image description here][1]


  [1]: http://i.stack.imgur.com/C2uJa.gif

http://www.curiousfind.com/blog/646 ありがとう

0
jbchitaliya

親UITableViewを見つけるには、この方法でビュー階層を走査することをお勧めします。

- (UITableView *) findParentTableView:(UITableViewCell *) cell
{
    UIView *view = cell;
    while ( view && ![view isKindOfClass:[UITableView class]] )
    {
#ifdef DEBUG
        NSLog( @"%@", [[view  class ] description] );
#endif
        view = [view superview];
    }

    return ( (UITableView *) view );
}

そうしないと、Appleがビュー階層を変更したときにコードが壊れますagain

別の答え 階層を横断することは再帰的です。

0
Bob Wakefield

このコード`UITableView *tblView=[cell superview];は、tabeビューセルを含むUItableviewのインスタンスを提供します

0
Singh

@idrisの回答から、私はSwiftのUITableViewCellの拡張を書きました

extension UITableViewCell {
func relatedTableView() -> UITableView? {
    var view = self.superview
    while view != nil && !(view is UITableView) {
        view = view?.superview
    }

    guard let tableView = view as? UITableView else { return nil }
    return tableView
}