UITableViewCell से UITableView कैसे प्राप्त करें?


100

मेरे पास एक UITableViewCellवस्तु से जुड़ा हुआ है और मुझे यह बताना होगा कि क्या सेल दिखाई दे रही है। मेरे द्वारा किए गए शोध से, इसका मतलब है कि मुझे किसी तरह UITableViewइसे एक्सेस करने की आवश्यकता है जिसमें यह है (वहां से, अगर यह दिखाई दे रहा है तो यह जांचने के कई तरीके हैं)। तो मैं सोच रहा था कि UITableViewCellक्या कोई पॉइंटर है UITableViewया सेल से पॉइंटर पाने का कोई और तरीका है?


2
इसका उद्देश्य क्या है?
अधिकतम_

[cell superView]शायद?
क्रिस लोनाम

6
यह समझाने के लायक है कि आपको ऐसा क्यों लगता है कि आपको इसकी आवश्यकता है - क्योंकि यह खराब डिज़ाइन का संकेत हो सकता है क्योंकि मैं किसी सेल के लिए कई वैध कारणों के बारे में नहीं सोच सकता कि यह स्क्रीन पर है या नहीं।
पॉल।

@ पॉल। हमारे पास एक सेल में एक छवि पर एक इशारा पहचानकर्ता है और जब सेल को छुआ जाता है, तो यह एक और ओवरले व्यू को खोलता है, पॉपओवर शैली को सोचता है, जिसे ठीक से प्रदर्शित करने के लिए जितनी ज़रूरत हो उतनी कोशिकाओं को ओवरले करना चाहिए। इसे काम करने के लिए इसे प्रदर्शित करने के लिए दिए गए TableView या अन्य दृश्य की आवश्यकता होती है। वास्तव में समाधान से खुश नहीं हैं, लेकिन वांछित प्रभाव पाने के लिए UITableViewCell के UITableView प्राप्त करना सबसे अच्छा है जिसे हम लेकर आए हैं।
चाडबाग

1
@ चीकबग कोई चिंता नहीं, उम्मीद है कि मैंने उसी समस्या के साथ किसी और को एक विचार दिया।
पीजे_फिनगन

जवाबों:


153

IOS संस्करण की जाँच करने से बचने के लिए, पुन: क्रमिक रूप से UITableView पाए जाने तक सेल के दृश्य से सुपरवाईज को ऊपर उठाएँ:

id view = [tableViewCellInstance superview];

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

UITableView *tableView = (UITableView *)view;

1
धन्यवाद। ऐसा प्रतीत होगा कि यह iOS 8 में एक बार फिर से बदल गया है और यह सभी संस्करणों का अच्छी तरह से ख्याल रखता है।
djskinner

2
मैं भविष्य के अपडेट में संगतता के मुद्दों से बचने के लिए सेल में तालिका के कमजोर संदर्भ को जोड़ने की सिफारिश करूंगा।
सेनी

1
बल्कि एक कमजोर तरीका है। यदि भविष्य में पदानुक्रम में परिवर्तन होता है तो यह काम नहीं करेगा।
रोमन एनवी

2
बस एक कमजोर संपत्ति बनाने के लिए बेहतर होगा जो वास्तव में टेबलव्यू के लिए एक संकेतक रखता है। उपवर्ग में @property (weak, nonatomic) UITableView *tableView;और tableView:cellForRowAtIndexPath:बस सेट में cell.tableView = tableView;
एलेजांद्रो इवान

वर्तमान अनुभव यह है कि एक सेल को हटाने के बाद, एक टेबलव्यू सेल के सुपरवाइवे के रूप में तुरंत दिखाई नहीं दे रहा है - अगर मैं सेल को देखने से बाहर स्क्रॉल करता हूं और फिर से वापस करता हूं, तो मैं एक टेबल व्यू को सुपरवाइवे (पुनरावर्ती खोज) के रूप में वर्णित करता हूं। अन्य उत्तर)। ऑटोलॉययट और संभवतः अन्य कारक संभावित कारण हैं।
जॉनी

48

IOS7 में बीटा 5 UITableViewWrapperViewएक का पर्यवेक्षण है UITableViewCellइसके अलावा UITableViewएक का पर्यवेक्षण है UITableViewWrapperView

तो iOS 7 के लिए समाधान है

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

तो iOS 6 के लिए iOS के लिए समाधान है

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


5
ओह यार, यह एक क्रूर एपीआई परिवर्तन है। यदि आप 6 और 7 दोनों का समर्थन करते हैं तो ऐप्पल का सबसे अच्छा अभ्यास क्या है?
रयान रोमनचुक

@RyanRomanchuk यहां एक अच्छा सुझाव है: devforums.apple.com/message/865550#865550 - सेल बनाते समय अपने संबंधित तालिका दृश्य में एक कमजोर सूचक बनाएं। वैकल्पिक रूप से, UITableViewCellएक नई विधि के साथ एक श्रेणी बनाएं , relatedTableViewजो एक iOS संस्करण के लिए एक जांच करता है और उपयुक्त सुपर व्यू लौटाता है।
मेमन

3
इसके लिए UIView पर एक पुनरावर्ती श्रेणी लिखें। आपको संस्करण की जाँच करने की आवश्यकता नहीं है; जब तक आपको टेबल व्यू सेल या व्यू स्टैक के शीर्ष नहीं मिल जाता है, तब तक पर्यवेक्षण करें। यह वह है जो मैंने iOS 6 में उपयोग किया था, और इसने iOS 7 में संशोधन के बिना काम किया। और इसे iOS 8 में काम करना चाहिए।
स्टीवन फिशर

क्षमा माँगता हूँ; मेरा मतलब था जब तक आपको टेबल व्यू नहीं मिल जाता। :)
स्टीवन फिशर

39

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

अंगूठे का एक नियम बल प्रयोग का प्रयोग नहीं करना है
थिबुत नूह

1
@thibautnoah अलिखित करने view != nilसे पहले एक जाँच है। हालांकि क्लीनर कोड को अपडेट किया गया
ओरखान अलीखानोव

25

IOS7 से पहले, सेल का सुपरवाइज वह था UITableViewजिसमें यह निहित था। IOS7 GM (जैसा कि संभवतः सार्वजनिक रिलीज में भी होगा) के रूप में, सेल का सुपरवाइड 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और तालिका के दृश्य को सेल की तालिका दृश्य संपत्ति में असाइन करें। फिर सेल के अंदर आप उपयोग करने वाले टेबलव्यू को संदर्भित कर सकते हैं self.tableView


मैं असहमत हूं कि समाधान 2 एक बेहतर डिजाइन है। इसमें विफलता के अधिक बिंदु हैं और अनुशासित मैनुअल हस्तक्षेप की आवश्यकता है। पहला समाधान वास्तव में काफी विश्वसनीय है, हालांकि मैं इसे लागू करूंगा क्योंकि @idris ने अपने उत्तर में थोड़ा और भविष्य के लिए सुझाव दिया था।
devios1

1
टेस्ट [self.superview.superview isKindOfClass:[UITableView class]]पहले होना चाहिए, 'कारण iOS 7 अधिक से अधिक है।
कॉपरैश

7

यदि यह दिखाई दे रहा है तो इसमें एक पर्यवेक्षण है। और ... आश्चर्य ... पर्यवेक्षी एक UITableView ऑब्जेक्ट है।

हालाँकि, सुपरवाइज होना स्क्रीन पर होने की कोई गारंटी नहीं है। लेकिन UITableView यह निर्धारित करने के लिए तरीके प्रदान करता है कि कौन से सेल दिखाई दे रहे हैं।

और नहीं, सेल से तालिका में कोई समर्पित संदर्भ नहीं है। लेकिन जब आप UITableViewCell को उपवर्गित करते हैं तो आप एक परिचय कर सकते हैं और इसे निर्माण पर सेट कर सकते हैं। (मैंने उप-स्तरीय पदानुक्रम के बारे में सोचने से पहले खुद को ऐसा किया था।)

IOS7 के लिए अपडेट: Apple ने यहां सबव्यू पदानुक्रम को बदल दिया है। हमेशा की तरह जब उन चीज़ों के साथ काम किया जाता है जिन्हें डॉक्यूमेंट नहीं किया जाता है, तो हमेशा एक जोखिम होता है कि चीजें बदल जाएं। UITableView ऑब्जेक्ट को अंतिम रूप से मिलने तक दृश्य पदानुक्रम को "क्रॉल अप" करना अधिक सुरक्षित है।


14
IOS7 में यह अब सच नहीं है, iOS7 में बीटा 5 UITableViewWrapperView एक UITableViewCell का पर्यवेक्षण है ... जिससे मुझे अभी समस्याएँ होती हैं
Gabe

टिप्पणी के लिए धन्यवाद। मुझे तब अपना कुछ कोड जांचना होगा।
हरमन क्लेकर

7

स्विफ्ट 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 को सेलफ़ोरराउट IndexPath निष्पादन के बाद ही UITableView पर जोड़ा जाता है।


आप पूरी lookForSuperviewOfType:विधि बॉडी को एक लाइन में कॉम्पैक्ट कर सकते हैं , जिससे यह और भी तेज हो जाती है:return superview as? T ?? superview?.superviewOfType(type)
kabiroberai

@kabiroberai, धन्यवाद। मैंने जवाब में आपकी सलाह को जोड़ा।
मेहदजोर २०

पुनरावर्ती कॉल द्वारा उपयोग किए जाने वाले नाम का मिलान करना होगा। तो यह पढ़ने की जरूरत है: ... ?? निरिक्षण।? नजरअंदाज करें।विशेषकर (टाइप)
रॉबर्ट

7

सुपर व्यू कहकर या रिस्पॉन्डर चेन के जरिए आप जो भी करने का प्रबंध कर सकते हैं वह बहुत नाजुक होने वाला है। ऐसा करने का सबसे अच्छा तरीका है, अगर सेल कुछ जानना चाहते हैं, तो सेल के लिए एक ऑब्जेक्ट पास करना है जो कुछ विधि का जवाब देता है, जो उस सवाल का जवाब देता है जो सेल पूछना चाहता है, और नियंत्रक को यह निर्धारित करने के तर्क को लागू करना है कि क्या जवाब देना है (आपके प्रश्न से मुझे लगता है कि सेल जानना चाहता है कि कुछ दिखाई दे रहा है या नहीं)।

सेल में एक डेलिगेट प्रोटोकॉल बनाएँ, सेल के प्रतिनिधि को टेबल व्यू कॉन्ट्रोलर सेट करें और टेबल व्यू कॉट्रोलर में सभी यूआई "कंट्रोलिंग" लॉजिक को स्थानांतरित करें।

तालिका दृश्य कक्ष डम दृश्य होना चाहिए जो केवल जानकारी प्रदर्शित करेगा।


शायद प्रतिनिधियों के माध्यम से और भी बेहतर। मैं अस्थायी रूप से तालिका में पारित संदर्भ का उपयोग कर रहा हूं क्योंकि माता-पिता ने मुझे समस्याएं दी हैं।
बजे क्रिस्टी बालूओ

1
जो मैंने वर्णित किया है वह मूल रूप से प्रतिनिधि पैटर्न का उपयोग कर रहा है :)
जेवियर सोतो

यह स्वीकृत उत्तर होना चाहिए, लोग इस प्रश्न को देखते हैं, 150+ अपवोट उत्तर देखते हैं और उन्हें लगता है कि सेल से टेबल व्यू प्राप्त करना ठीक है और इससे भी अधिक दुर्भाग्य से इसका एक मजबूत संदर्भ रखें।
एलेक्स टेरेंटे

6

मैंने इसके मूल तालिका प्राप्त करने के लिए 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

श्रेष्ठ,


3

यहाँ उपरोक्त उत्तरों के आधार पर स्विफ्ट संस्करण है। मैंने 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
    }
}

उममीद है कि इससे मदद मिलेगी :)


2

मैंने गैब के सुझाव पर इस समाधान को आधारित किया कि UITableViewWrapperViewऑब्जेक्ट UITableViewCelliOS7 बीटा 5 में ऑब्जेक्ट का पर्यवेक्षक है।

उपवर्ग 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

मैंने उधार लिया और उपरोक्त उत्तर से थोड़ा संशोधित किया और निम्नलिखित स्निपेट के साथ आया।

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

कक्षा में उत्तीर्ण करने से कुछ अन्य अवसरों में UITableView के अलावा अन्य ट्रैवर्सिंग और विचार प्राप्त करने की सुविधा मिलती है।


2

इस समस्या का मेरा समाधान कुछ हद तक अन्य समाधानों के समान है, लेकिन एक सुरुचिपूर्ण लूप का उपयोग करता है और संक्षिप्त है। यह भविष्य का प्रमाण भी होना चाहिए:

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

यह हमेशा के लिए लूप जाएगा यदि सेल अभी तक तालिका दृश्य में नहीं है, जब कहा जाता है। ठीक करने के लिए, nil के लिए एक चेक जोड़ें: for (view = self.superview; view && ![view isKindOfClass:UITableView.class]; view = view.superview);
एंटोनियो न्यून्स

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

1

पर्यवेक्षण के बजाय, ["UItableViewvariable" दृश्यमान] का उपयोग करने का प्रयास करें।

मैंने उस फोरचार्ज लूप में उन कोशिकाओं के माध्यम से लूप का उपयोग किया, जो ऐप ने देखीं और यह काम किया।

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

न्यूनतम परीक्षण किया गया लेकिन यह गैर-जेनेरिक स्विफ्ट 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
    }
}

0

यह कोड `UITableView *tblView=[cell superview];आपको यूआईटेब्यूव्यू का एक उदाहरण देगा जिसमें टैब व्यू सेल शामिल है


यह काम नहीं करेगा, क्योंकि UITableViewCell का तत्काल पर्यवेक्षक UITableView नहीं है। IOS 7 के रूप में, UITableViewCell पर्यवेक्षक एक UITableViewWrapperView है। कम नाजुक, अधिक विश्वसनीय दृष्टिकोण के लिए अन्य उत्तर यहां देखें।
जेरेडह

0

मेरा सुझाव है कि आप पदानुक्रम को देखने के लिए पदानुक्रम को इस तरह से देखें: 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 फिर से पदानुक्रम को बदलेगा तो आपका कोड टूट जाएगा ।

एक अन्य उत्तर जो पदानुक्रम का पता लगाता है वह भी पुनरावर्ती है।


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

@idris जवाब से मैंने स्विफ्ट में 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
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.