オブジェクトにリンクされているUITableViewCell
があり、セルが表示されるかどうかを確認する必要があります。私が行った調査から、これは何らかの形でそれを含むUITableView
にアクセスする必要があることを意味します(そこから、それが見えるかどうかを確認するいくつかの方法があります)。だから、UITableViewCell
がUITableView
へのポインターを持っているのか、それともセルからポインターを取得する他の方法があったのだろうかと思っています。
IOSのバージョンチェックを回避するには
id view = [tableViewCellInstance superview];
while (view && [view isKindOfClass:[UITableView class]] == NO) {
view = [view superview];
}
UITableView *tableView = (UITableView *)view;
IOS7ベータ5では、UITableViewWrapperView
はUITableViewCell
のスーパービューです。 UITableView
はUITableViewWrapperView
のスーパービューでもあります
IOS 7のソリューションは
UITableView *tableView = (UITableView *)cell.superview.superview;
そのため、iOS 6までのiOS向けのソリューションは
UITableView *tableView = (UITableView *)cell.superview;
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
}
}
IOS7以前は、セルのスーパービューはそれを含むUITableView
でした。 iOS7の時点でGM(したがって、おそらく一般公開にもなります)セルのスーパービューはUITableViewWrapperView
であり、そのスーパービューはUITableView
です。この問題には2つの解決策があります。
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]
に置き換え、ビュー階層が変更された場合にアサートをスローします。または、将来的に元に戻すと、テストですぐに表示されます。
UITableView
参照をUITableViewCell
に追加する@interface SOUITableViewCell
@property (weak, nonatomic) UITableView *tableView;
@end
これははるかに優れた設計ですが、既存のプロジェクトで使用するには、もう少しコードのリファクタリングが必要になります。 tableView:cellForRowAtIndexPath
で、SOUITableViewCellをセルクラスとして使用するか、カスタムセルクラスが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
CellForRowAtIndexPathの実行後にのみUITableViewCellがUITableViewに追加されることに注意してください。
表示されている場合、スーパービューがあります。そして...驚き...スーパービューはUITableViewオブジェクトです。
ただし、スーパービューを持つことは、画面に表示されることを保証するものではありません。ただし、UITableViewには、どのセルが表示されるかを決定するメソッドが用意されています。
いいえ、セルからテーブルへの専用の参照はありません。ただし、UITableViewCellをサブクラス化する場合は、UITableViewCellを導入し、作成時に設定できます。 (サブビューの階層構造を考える前に、私はそれをかなりしました。)
iOS7の更新: Appleは、ここでサブビュー階層を変更しました。文書化されていない詳細なものを扱う場合、いつものように、常に物事が変わるリスクがあります。 UITableViewオブジェクトが最終的に見つかるまで、ビュー階層を「クロールアップ」することははるかに効率的です。
スーパービューを呼び出したり、レスポンダーチェーンを介して何とかしてやろうとすると、非常に壊れやすくなります。セルが何かを知りたい場合、これを行う最善の方法は、セルが尋ねたい質問に答える何らかのメソッドに応答するオブジェクトをセルに渡し、コントローラーに答えを決定するロジックを実装させることです(あなたの質問から、セルは何かが見えるかどうかを知りたいと思います)。
セルにデリゲートプロトコルを作成し、セルのデリゲートをtableViewControllerに設定し、tableViewCotroller内のすべてのUI「制御」ロジックを移動します。
テーブルビューのセルは、情報のみを表示するダムビューである必要があります。
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
ベスト、
上記の回答に基づいた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
}
}
このヘルプを願っています:)
UITableView *tv = (UITableView *) self.superview.superview;
BuyListController *vc = (BuyListController *) tv.dataSource;
上記の回答から少し借りて修正し、次のスニペットを作成しました。
- (id)recursivelyFindSuperViewWithClass:(Class)clazz fromView:(id)containedView {
id containingView = [containedView superview];
while (containingView && ![containingView isKindOfClass:[clazz class]]) {
containingView = [containingView superview];
}
return containingView;
}
クラスを渡すと、他の場合にUITableView以外のビューを走査および取得するための柔軟性が提供されます。
このソリューションは、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];
}
この問題に対する私のソリューションは、他のソリューションと多少似ていますが、エレガントな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
}
}
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
}
}
1行のコードで取得できます。
UITableView *tableView = (UITableView *)[[cell superview] superview];
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
親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。
別の答え 階層を横断することは再帰的です。
このコード`UITableView *tblView=[cell superview];
は、tabeビューセルを含むUItableviewのインスタンスを提供します
@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
}