Programing

UITableViewCell에서 UITableView를 얻는 방법?

lottogame 2020. 8. 22. 11:30
반응형

UITableViewCell에서 UITableView를 얻는 방법?


나는이 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 UITableViewWrapperViewUITableViewCell. 또한 UITableView의 수퍼입니다 UITableViewWrapperView.

따라서 iOS 7의 경우 솔루션은

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

따라서 iOS 6까지의 iOS의 경우 솔루션은

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


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
    }
}

iOS7 이전에는 셀의 수퍼 뷰가 UITableView포함되었습니다. GM iOS7에 현재의 수퍼 셀이있다 (그래서 아마도 아니라 공개용 될 예정) UITableViewWrapperView의 수퍼은 인으로 UITableView. 문제에 대한 두 가지 해결책이 있습니다.

솔루션 # 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를 할당합니다. 그런 다음 셀 내부에서를 사용하여 포함하는 tableview를 참조 할 수 있습니다 self.tableView.


보이는 경우 수퍼 뷰가있는 것입니다. 그리고 ... 놀랍게도 ... superview는 UITableView 객체입니다.

그러나 수퍼 뷰가 있다고해서 화면에 있다는 보장은 없습니다. 그러나 UITableView는 표시되는 셀을 결정하는 방법을 제공합니다.

그리고 아니요, 셀에서 테이블로의 전용 참조가 없습니다. 그러나 UITableViewCell을 하위 클래스로 만들 때 하나를 도입하고 생성시 설정할 수 있습니다. (저는 하위 뷰 계층 구조를 생각하기 전에 많이했습니다.)

iOS7 업데이트 : Apple은 여기에서 하위보기 계층 구조를 변경했습니다. 상세하게 문서화되지 않은 작업을 할 때 평소처럼 상황이 변경 될 위험이 항상 있습니다. UITableView 개체가 결국 발견 될 때까지 뷰 계층 구조를 "크롤링"하는 것이 훨씬 절약됩니다.


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
    }
}

또는 더 콤팩트 (kabiroberai 덕분에) :

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에 추가됩니다.


부모 tableView를 얻기 위해 UITableViewCell에 범주를 만들었습니다.

@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

베스트,


수퍼 뷰를 호출하거나 응답자 체인을 통해 관리 할 수있는 모든 작업은 매우 취약 할 것입니다. 이를 수행하는 가장 좋은 방법은 셀이 무언가를 알고 자하는 경우, 셀이 묻고 자하는 질문에 답하는 방법에 응답하는 객체를 셀에 전달하고 컨트롤러가 응답 할 내용을 결정하는 논리를 구현하도록하는 것입니다. (귀하의 질문에서 나는 세포가 무언가가 보이는지 아닌지 알고 싶어한다고 생각합니다).

셀에 델리게이트 프로토콜을 생성하고, 셀의 델리게이트를 tableViewController로 설정하고 tableViewCotroller에서 모든 UI "제어"로직을 이동합니다.

테이블 뷰 셀은 정보 만 표시하는 덤 뷰 여야합니다.


위의 답변을 기반으로 한 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
    }
}

이 도움을 바랍니다 :)


I based this solution on Gabe's suggestion that UITableViewWrapperView object is the superview of UITableViewCell object in iOS7 beta5 .

Subclass 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];
}

I Borrowed and modified a little bit from the above answer and come up with the following snippet.

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

Passing in class offers the flexibility for traversing and getting views other than UITableView in some other occasions.


My solution to this problem is somewhat similar to other solutions, but uses an elegant for-loop and is short. It should also be future-proof:

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

UITableView *tv = (UITableView *) self.superview.superview;
BuyListController *vc = (BuyListController *) tv.dataSource;

Instead of superview, try using ["UItableViewvariable" visibleCells].

I used that in a foreach loops to loop through the cells that the app saw and it worked.

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 
    }
  }
}

Works like a charm.


Minimally tested but this non-generic Swift 3 example seems to work:

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
    }
}

this code `UITableView *tblView=[cell superview]; will give you an instance of the UItableview which contains the tabe view cell


I suggest you traverse the view hierarchy this way to find the parent 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 );
}

Otherwise your code will break when Apple changes the view hierarchy again.

Another answer that also traverses the hierarchy is recursive.


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 Thank You


You can get it with one line of code.

UITableView *tableView = (UITableView *)[[cell superview] superview];

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
    }
}

from @idris answer I wrote an expansion for UITableViewCell in Swift

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
}

참고URL : https://stackoverflow.com/questions/15711645/how-to-get-uitableview-from-uitableviewcell

반응형