UITableViewCell
オブジェクトにリンクされている があり、セルが表示されているかどうかを確認する必要があります。私が行った調査から、これは何らかのUITableView
方法でそれを含む にアクセスする必要があることを意味します (そこから、表示されているかどうかを確認する方法がいくつかあります)。UITableViewCell
へのポインターがあるUITableView
かどうか、またはセルからポインターを取得する他の方法があったかどうか疑問に思っていますか?
21 に答える
iOS のバージョンをチェックしないようにするには、UITableView が見つかるまで、セルのビューからスーパービューを繰り返します。
Objective-C
id view = [cellInstance superview];
while (view && [view isKindOfClass:[UITableView class]] == NO) {
view = [view superview];
}
UITableView *tableView = (UITableView *)view;
迅速
var view = cellInstance.superview
while (view != nil && (view as? UITableView) == nil) {
view = view?.superview
}
if let tableView = view as? UITableView {
tableView.beginUpdates()
tableView.endUpdates()
}
iOS7 beta 5UITableViewWrapperView
では、UITableViewCell
. のスーパービューもあります。UITableView
UITableViewWrapperView
したがって、iOS 7の場合の解決策は
UITableView *tableView = (UITableView *)cell.superview.superview;
したがって、iOS 6 までの iOS の場合、解決策は次のとおりです。
UITableView *tableView = (UITableView *)cell.superview;
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
これははるかに優れた設計ですが、既存のプロジェクトで使用するにはもう少しコードのリファクタリングが必要になります。SOUITableViewCelltableView:cellForRowAtIndexPath
をセル クラスとして使用するか、カスタム セル クラスがサブクラス化されていることを確認しSOUITableViewCell
、tableView をセルの tableView プロパティに割り当てます。セル内では、 を使用して含まれているテーブルビューを参照できますself.tableView
。
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
UITableViewCell は cellForRowAtIndexPath の実行後にのみ UITableView に追加されることに注意してください。
表示されている場合は、スーパービューがあります。そして...驚き...スーパービューはUITableViewオブジェクトです。
ただし、スーパービューがあるからといって、画面に表示される保証はありません。ただし、UITableView には、どのセルが表示されているかを判断するメソッドが用意されています。
いいえ、セルからテーブルへの専用の参照はありません。しかし、UITableViewCell をサブクラス化すると、作成時にそれを導入して設定することができます。(サブビュー階層について考える前に、私は自分でそれをたくさんしました。)
iOS7 の更新: Apple はここでサブビュー階層を変更しました。詳細に文書化されていないものを扱うときはいつものように、物事が変わるリスクが常にあります。UITableView オブジェクトが最終的に見つかるまで、ビュー階層を「クロール」する方がはるかに節約になります。
スーパー ビューを呼び出したり、レスポンダー チェーンを介して実行したりすることは、非常に脆弱です。セルが何かを知りたがっている場合、これを行う最善の方法は、セルが尋ねたい質問に答える何らかのメソッドに応答するオブジェクトをセルに渡し、何を答えるべきかを決定するロジックをコントローラーに実装させることです。 (あなたの質問から、セルは何かが見えるかどうかを知りたがっていると思います)。
セルにデリゲート プロトコルを作成し、セルのデリゲートを tableViewController に設定し、すべての UI の「制御」ロジックを tableViewCotroller に移動します。
テーブル ビューのセルは、情報のみを表示するダム ビューにする必要があります。
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
一番、
上記の回答から少し借りて変更し、次のスニペットを考え出しました。
- (id)recursivelyFindSuperViewWithClass:(Class)clazz fromView:(id)containedView {
id containingView = [containedView superview];
while (containingView && ![containingView isKindOfClass:[clazz class]]) {
containingView = [containingView superview];
}
return containingView;
}
クラスで渡すと、他の場合に UITableView 以外のビューをトラバースして取得するための柔軟性が提供されます。
この問題に対する私の解決策は、他の解決策と多少似ていますが、洗練された for ループを使用しており、短いものです。また、将来的にも保証されている必要があります。
- (UITableView *)tableView
{
UIView *view;
for (view = self.superview; ![view isKindOfClass:UITableView.class]; view = view.superview);
return (UITableView *)view;
}
スーパービューの代わりに、["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
}
}
}
魅力のように機能します。
最小限のテストですが、この非汎用の 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
}
}
このコード`UITableView *tblView=[cell superview];
は、タブ ビュー セルを含む UItableview のインスタンスを提供します。
この方法でビュー階層をトラバースして、親 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 がビュー階層を再度変更したときにコードが壊れます。
階層を横断する別の答えは再帰的です。
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
}
}