जब dequeueReusableCellWithIdentifier बनाम dequeueReusableCellWithIdentifier का उपयोग करने के लिए: forIndexPath


167

DequeueReusableCellWithIdentifier के लिए दो ओवरलोड हैं और मैं यह निर्धारित करने की कोशिश कर रहा हूं कि मुझे एक बनाम दूसरे का उपयोग कब करना चाहिए?

ForIndexPath फ़ंक्शन के बारे में ऐप्पल डॉक्स बताता है, "यह पद्धति तालिका दृश्य में सेल की स्थिति के आधार पर अतिरिक्त कॉन्फ़िगरेशन करने के लिए इंडेक्स पथ का उपयोग करती है।"

मुझे यकीन नहीं है कि हालांकि इसकी व्याख्या कैसे करें?

जवाबों:


216

सबसे महत्वपूर्ण अंतर यह है कि forIndexPath:यदि आप पहचानकर्ता के लिए एक वर्ग या नायब पंजीकृत नहीं करते हैं तो संस्करण जोर देता है (क्रैश)। उस मामले में पुराना (गैर- forIndexPath:) संस्करण वापस आ nilजाता है।

आप registerClass:forCellReuseIdentifier:तालिका दृश्य को भेजकर एक पहचानकर्ता के लिए एक वर्ग पंजीकृत करते हैं। आप registerNib:forCellReuseIdentifier:तालिका दृश्य को भेजकर एक पहचानकर्ता के लिए एक निब रजिस्टर करते हैं।

यदि आप एक स्टोरीबोर्ड में अपना टेबल व्यू और अपने सेल प्रोटोटाइप बनाते हैं, तो स्टोरीबोर्ड लोडर सेल प्रोटोटाइप को पंजीकृत करने का ध्यान रखता है जिसे आपने स्टोरीबोर्ड में परिभाषित किया था।

सत्र २०० - WWDC 2012 से कोको टच में नया क्या है (तत्कालीन-नया) forIndexPath:संस्करण 30 एम ३० के आसपास शुरू हुआ। यह कहता है कि "आपको हमेशा एक आरंभिक सेल मिलेगा" (यह उल्लेख किए बिना कि यदि आप एक वर्ग या नायब पंजीकृत नहीं हुए तो यह दुर्घटनाग्रस्त हो जाएगा)।

वीडियो यह भी कहता है कि "यह उस सूचकांक पथ का सही आकार होगा"। संभवतः इसका मतलब यह है कि यह सेल के आकार को सेट करने से पहले इसे लौटा देगा, तालिका दृश्य की अपनी चौड़ाई को देखकर और अपने प्रतिनिधि के tableView:heightForRowAtIndexPath:तरीके (यदि परिभाषित किया गया है) को कॉल करके । यही कारण है कि इसे सूचकांक पथ की आवश्यकता है।


यह वास्तव में उपयोगी है, धन्यवाद। ऑटो साइज़िंग और लेआउट की कमी के साथ एक समय पर सेल का आकार कम होने से फायदा कम लगता है?
बेंजोना

38

dequeueReusableCellWithIdentifier:forIndexPath:जाएगा हमेशा एक सेल लौट आते हैं। यह या तो मौजूदा कोशिकाओं का उपयोग करता है या एक नया बनाता है और अगर कोई सेल नहीं है तो रिटर्न करता है।

हालांकि, पारंपरिक dequeueReusableCellWithIdentifier:एक सेल को लौटाएगा यदि यह मौजूद है यानी यदि कोई सेल है जिसका पुन: उपयोग किया जा सकता है तो वह वापस लौटता है अन्यथा यह शून्य देता है। इसलिए आपको nilमूल्य की जांच करने के लिए एक शर्त भी लिखनी होगी ।

dequeueReusableCellWithIdentifier:जब आप iOS 6 और निचले संस्करणों का समर्थन करना चाहते हैं, तब से अपने प्रश्न उपयोग का उत्तर देने के लिए dequeueReusableCellWithIdentifier:forIndexPathकेवल iOS 6+ पर उपलब्ध है

संदर्भ: https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/occ/instm/UITableView/dequeueReusableCellWithIdentifier:forIndexPath :


नहीं, यह हमेशा एक सेल नहीं लौटता है 2014-12-26 07: 56: 39.947 testProg [4024: 42920390] *** इसमें विफलता - [UITableView dequeueReusableCellWithIdentifier: forIndexPath:], /SourceCache/UIKit_Sim/UIKit-3381818 UITableView.m: 6116 2014-12-26 07: 56: 39.954 इंटरपेज़ [4024: 42920390] *** अनचाहे अपवाद 'NSInternalInconsistencyException' अपवाद के कारण ऐप समाप्त करना, कारण: पहचानकर्ता MyCustomCellIdentifier के साथ एक सेल को समाप्त करने में असमर्थ - एक nib रजिस्टर करना होगा। या पहचानकर्ता के लिए एक वर्ग या स्टोरीबोर्ड में एक प्रोटोटाइप सेल कनेक्ट करें '
15

@binarystar आप चाहिए एक निब या ध्यान में रखते हुए अपने कस्टम सेल के वर्ग रजिस्टर लोड किया था। जैसे:[self.tableView registerNib:[UINib nibWithNibName:@"cell" bundle:nil] forCellReuseIdentifier:@"cell"];
GoodSp33d

6

मुझे कभी समझ नहीं आया कि Apple ने नया तरीका क्यों बनाया, dequeueReusableCellWithIdentifier: forIndexxath:। उन पर उनका प्रलेखन पूर्ण नहीं है, और कुछ भ्रामक है। एकमात्र अंतर जो मैं दो तरीकों के बीच विचार करने में सक्षम हूं, वह यह है कि पुरानी विधि शून्य वापस आ सकती है, अगर इसमें पास किए गए पहचानकर्ता के साथ एक सेल नहीं मिलता है, जबकि नई विधि दुर्घटनाग्रस्त हो जाती है, अगर यह वापस नहीं आ सकती है एक कोशिका। यदि आप पहचानकर्ता को सही ढंग से सेट करते हैं, और सेल को स्टोरीबोर्ड में बनाते हैं, तो दोनों तरीकों से सेल वापस करने की गारंटी दी जाती है। यदि आप एक वर्ग या xib रजिस्टर करते हैं, और कोड या xib फ़ाइल में अपना सेल बनाते हैं, तो दोनों तरीकों से भी सेल वापस करने की गारंटी दी जाती है।


3
नई विधि सेल के लिए उचित आकार निर्धारित करने के लिए सूचकांक पथ का उपयोग करती है।
डकैती

1
@robmayoff लेकिन क्या इसका कोई मतलब है? नई विधि के बिना, सेल का आकार अभी भी ठीक से सेट किया जा सकता है। क्या नई विधि किसी भी सुविधा की पेशकश कर सकती है?
फुजियानजिआंग ६४ Jul१

1
विवरण के लिए मेरे उत्तर के अंतिम पैराग्राफ को पढ़ें।
लूट मय जूल 29'15

तो क्या इसका मतलब यह है कि, यदि मेरी सभी कोशिकाएं तालिका में एक ही आकार की हैं, तो इससे कोई फर्क नहीं पड़ता कि मैं किस पद्धति को कॉल करूं?
हैप्पीहापी

2
यदि मैं प्रदान करता हूं tableView.estimateHeight, तो सेल का आकार ठीक से निर्धारित किया जाएगा। मुझे अभी भी नई पद्धति का लाभ नहीं मिला है।
रयान

1

छोटे के लिए:

dequeueReusableCell(withIdentifier, for)केवल प्रोटोटाइप कोशिकाओं के साथ काम करता है। यदि आप प्रोटोटाइप सेल के अभाव में इसका उपयोग करने की कोशिश करते हैं, तो यह ऐप क्रैश कर देगा।

होलेमन्स एम। 2016, अध्याय 2 चेकलिस्ट, आईओएस अपरेंटिस (5 वां संस्करण)। पीपी: 156।


-2

यदि आप गतिशील उत्पन्न सामग्री का उपयोग कर रहे हैं तो मैं दोनों का उपयोग करने की सलाह दूंगा। अन्यथा आपका ऐप अप्रत्याशित रूप से क्रैश हो सकता है। आप एक वैकल्पिक पुन: प्रयोज्य सेल को पुनः प्राप्त करने के लिए अपने स्वयं के फ़ंक्शन को लागू कर सकते हैं। अगर यह होता हैnil तो आपको एक खाली सेल वापस करना चाहिए जो दिखाई नहीं दे रहा है:

स्विफ्ट 3

// Extensions to UITableView
extension UITableView
{
    // returns nil, if identifier does not exist. 
    // Otherwise it returns a configured cell for the given index path
    open func tryDequeueReusableCell (
        withIdentifier identifier: String, 
        for indexPath: IndexPath) -> UITableViewCell?
    {
        let cell = self.dequeueReusableCell(withIdentifier: identifier)
        if cell != nil {
            return self.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
        }  
        return nil
    }
}

और खाली सेल वापस करने के लिए एक्सटेंशन:

// Extension to UITableViewCell
extension UITableViewCell
{
    // Generates an empty table cell that is not visible
    class func empty() -> UITableViewCell
    {
        let emptyCell = UITableViewCell(frame:CGRect(x:0, y:0, width:0, height:0))
        emptyCell.backgroundColor = UIColor.clear
        return emptyCell
    }
}

इसका उपयोग कैसे करें का एक पूरा उदाहरण:

import Foundation
import UIKit

// A protocol is used to identify if we can configure
// a cell with CellData
protocol ConfigureAbleWithCellData
{
    func configure(_ data: CellData)
}

class MyCustomTableViewCell :
    UITableViewCell,
    ConfigureAbleWithCellData
{
    @IBOutlet weak var title:UILabel! = nil
    func configure(_ data: CellData)
    {
        self.title.text = data.title
    }
}

// This actually holds the data for one cell
struct CellData
{
    var title:String = ""
    var reusableId:String = ""
}

class CosmoConverterUnitTableViewController:
    UIViewController,
    UITableViewDelegate,
    UITableViewDataSource
{
    // Storage
    var data = Array<Array<CellData>>()

    func loadData()
    {
        var section1:[CellData] = []
        var section2:[CellData] = []

        section1.append(CellData(title:"Foo", reusableId:"cellType1"))
        section2.append(CellData(title:"Bar", reusableId:"cellType2"))

        data.append(section1)
        data.append(section2)
    }

    func tableView(_ tableView: UITableView,
                   numberOfRowsInSection section: Int) -> Int
    {
        return data[section].count
    }

    public func numberOfSections(in tableView: UITableView) -> Int
    {
        return data.count
    }

    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        guard
            indexPath.row < data[indexPath.section].count
            else
        {
            fatalError("this can't be")
        }

        let cellData = data[indexPath.section][indexPath.row]

        if let cell = tableView.tryDequeueReusableCell(
            withIdentifier: cellData.reusableId,
            for: indexPath)
        {
            if let configurableCell = cell as? ConfigureAbleWithCellData
            {
                configurableCell.configure(cellData)
            }
            else
            {
                // cell is not of type ConfigureAbleWithCellData
                // so we cant configure it.
            }
            return cell
        }
        // id does not exist
        return UITableViewCell.empty()
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.