स्विफ्ट में निब से कस्टम UITableViewCell


139

मैं एक निब से एक कस्टम टेबल व्यू सेल बनाने की कोशिश कर रहा हूँ। मैं यहाँ इस लेख की बात कर रहा हूँ । मैं दो मुद्दों का सामना कर रहा हूं।

मैं एक UITableViewCell वस्तु के साथ एक .xib फ़ाइल बनाया है। मैंने एक उप-वर्ग बनाया UITableViewCellऔर इसे पुन: प्रयोज्य पहचानकर्ता के रूप में सेल के वर्ग और सेल के रूप में सेट किया ।

import UIKit

class CustomOneCell: UITableViewCell {

    @IBOutlet weak var middleLabel: UILabel!
    @IBOutlet weak var leftLabel: UILabel!
    @IBOutlet weak var rightLabel: UILabel!

    required init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

UITableViewController में मेरे पास यह कोड है,

import UIKit

class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {

    var items = ["Item 1", "Item2", "Item3", "Item4"]

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK: - UITableViewDataSource
    override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let identifier = "Cell"
        var cell: CustomOneCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
        if cell == nil {
            tableView.registerNib(UINib(nibName: "CustomCellOne", bundle: nil), forCellReuseIdentifier: identifier)
            cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomOneCell
        }

        return cell
    }
}

यह कोड बिना किसी त्रुटि के अनुपालन करता है, लेकिन जब मैं इसे सिम्युलेटर में चलाता हूं, तो यह ऐसा दिखता है।

यहां छवि विवरण दर्ज करें

स्टोरीबोर्ड में UITableViewController में मैंने सेल को कुछ भी नहीं किया है। खाली पहचानकर्ता और कोई उपवर्ग नहीं। मैंने प्रोटोटाइप सेल में सेल पहचानकर्ता को जोड़ने की कोशिश की और इसे फिर से चलाया लेकिन मुझे वही परिणाम मिला।

मेरे द्वारा सामना की गई एक और त्रुटि है, जब मैंने UITableViewController में निम्न विधि को लागू करने का प्रयास किया।

override func tableView(tableView: UITableView!, willDisplayCell cell: CustomOneCell!, forRowAtIndexPath indexPath: NSIndexPath!) {

    cell.middleLabel.text = items[indexPath.row]
    cell.leftLabel.text = items[indexPath.row]
    cell.rightLabel.text = items[indexPath.row]
}

जैसा कि लेख मैंने कहा में दिखाया गया है मैं बदल cellपैरामीटर के प्रकार के फार्म UITableViewCellकरने के लिए CustomOneCellजो UITableViewCell की मेरी उपवर्ग है। लेकिन मुझे निम्नलिखित त्रुटि मिलती है,

चयनकर्ता की तालिका के साथ ओवरराइडिंग विधि: willDisplayCell: forRowAtIndexPath: 'में असंगत प्रकार' (UITableView !, CustomOneCell !, NSIndexPath!) -> () '' है।

किसी को भी इन त्रुटियों को हल करने का कोई विचार है? ये ऑब्जेक्टिव-सी में ठीक काम कर रहे थे।

धन्यवाद।

संपादित करें: मैंने अभी देखा अगर मैं सिम्युलेटर के परिदृश्य के प्रति उन्मुखीकरण को बदल देता हूं और इसे वापस चित्र में बदल देता हूं, तो कोशिकाएं दिखाई देती हैं! मैं अभी भी समझ नहीं पाया कि क्या चल रहा है। यदि आप एक त्वरित नज़र के लिए समय है, तो मैंने समस्या का प्रदर्शन करते हुए एक Xcode प्रोजेक्ट यहाँ अपलोड किया ।

जवाबों:


213

स्विफ्ट 5 और आईओएस 12.2 के साथ, आपको अपनी समस्या को हल करने के लिए निम्नलिखित कोड की कोशिश करनी चाहिए:

CustomCell.swift

import UIKit

class CustomCell: UITableViewCell {

    // Link those IBOutlets with the UILabels in your .XIB file
    @IBOutlet weak var middleLabel: UILabel!
    @IBOutlet weak var leftLabel: UILabel!
    @IBOutlet weak var rightLabel: UILabel!

}

TableViewController.swift

import UIKit

class TableViewController: UITableViewController {

    let items = ["Item 1", "Item2", "Item3", "Item4"]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
    }

    // MARK: - UITableViewDataSource

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell

        cell.middleLabel.text = items[indexPath.row]
        cell.leftLabel.text = items[indexPath.row]
        cell.rightLabel.text = items[indexPath.row]

        return cell
    }

}

नीचे दी गई छवि उन बाधाओं का एक समूह दिखाती है, जो बिना किसी बाधा के प्रदान किए गए कोड के साथ काम करते हैं, Xcode से अस्पष्टता संदेश:

यहां छवि विवरण दर्ज करें


1
जवाब देने के लिए धन्यवाद। लेकिन वह भी काम नहीं किया। क्या मुझे टेबल व्यू कंट्रोलर में कुछ भी बदलने की आवश्यकता है? क्योंकि यह अभी भी प्रोटोटाइप कोशिकाओं के लिए निर्धारित है।
इस्सरू

1
प्रोटोटाइप कोशिकाओं का उपयोग करते रहें। लेकिन सुनिश्चित करें कि आपने अच्छे ऑटो लेआउट की कमी (यदि आप ऑटो लेआउट का उपयोग करते हैं) सेट किया है।
इमानौ पेटिट

1
मैंने यहाँ एक परीक्षण परियोजना अपलोड की है जिसमें इस मुद्दे का प्रदर्शन है। यदि आपके पास समय है तो क्या आप इसे देख सकते हैं?
इसुरु

1
आपकी परीक्षण परियोजना इसकी पुष्टि करती है: मैं आपके .xib फ़ाइल में आपके सेल में कुछ ऑटो लेआउट बाधाओं को सेट करने के बाद आपके ऐप को ठीक काम करने में सक्षम था। पर एक नजर डालें इस वीडियो को अगर आप ऑटो लेआउट के बारे में अधिक जानना चाहते हैं।
इमानौ पेटिट

2
@KirillKudaev स्विफ्ट 4 में इसका नाम नहीं था, लेकिन स्विफ्ट 3 में: मैंने आपका संपादन तय कर दिया है।
कूर

30

यहाँ स्विफ्ट 2 और Xcode 7.3 का उपयोग करके मेरा दृष्टिकोण है। यह उदाहरण दो .xib फ़ाइलों को लोड करने के लिए एक एकल ViewController का उपयोग करेगा - एक UITableView के लिए और एक UITableCellView के लिए।

यहां छवि विवरण दर्ज करें

इस उदाहरण के लिए आप UITableView को खाली TableNib .xib फ़ाइल में छोड़ सकते हैं । अंदर, फ़ाइल के मालिक को अपने ViewController क्लास में सेट करें और tableView को संदर्भित करने के लिए एक आउटलेट का उपयोग करें।

यहां छवि विवरण दर्ज करें

तथा

यहां छवि विवरण दर्ज करें

अब, आपके व्यू कंट्रोलर में, आप टेबल व्यू को सामान्य रूप से जैसे चाहे वैसे कर सकते हैं

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // Table view delegate
        self.tableView.delegate = self
        self.tableView.dataSource = self

        ...

अपनी कस्टम सेल बनाने के लिए, एक टेबल व्यू सेल ऑब्जेक्ट को एक खाली TableCellNib .xib फ़ाइल में छोड़ें । इस बार, सेल .xib फ़ाइल में आपको "स्वामी" निर्दिष्ट करने की आवश्यकता नहीं है, लेकिन आपको "TableCellId" जैसी एक कस्टम क्लास और एक पहचानकर्ता निर्दिष्ट करने की आवश्यकता है

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

जो भी आउटलेट आपको पसंद हो, उसके साथ अपना उपवर्ग बनाएं

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

अंत में ... अपने व्यू कंट्रोलर में वापस, आप पूरी चीज़ को लोड कर सकते हैं और प्रदर्शित कर सकते हैं

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    // First load table nib
    let bundle = NSBundle(forClass: self.dynamicType)
    let tableNib = UINib(nibName: "TableNib", bundle: bundle)
    let tableNibView = tableNib.instantiateWithOwner(self, options: nil)[0] as! UIView

    // Then delegate the TableView
    self.tableView.delegate = self
    self.tableView.dataSource = self

    // Set resizable table bounds
    self.tableView.frame = self.view.bounds
    self.tableView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

    // Register table cell class from nib
    let cellNib = UINib(nibName: "TableCellNib", bundle: bundle)
    self.tableView.registerNib(cellNib, forCellReuseIdentifier: self.tableCellId)

    // Display table with custom cells
    self.view.addSubview(tableNibView)

}

कोड दिखाता है कि आप बस एक निब फ़ाइल (तालिका) को कैसे लोड और प्रदर्शित कर सकते हैं, और दूसरा सेल उपयोग के लिए निब कैसे दर्ज करें।

उम्मीद है की यह मदद करेगा!!!


2
क्या आप बता सकते हैं कि इस पंक्ति में "tableCellId" क्या है .... self.tableView.registerNib (cellNib, forCellReuseIdentifier: self.tableCellId) .... क्योंकि आपने वह परिभाषित नहीं किया है। और आप xib में पहचानकर्ता को मैन्युअल रूप से परिभाषित नहीं कर सकते .. इसे परिभाषित करने के लिए कोई विकल्प नहीं है
PRADIP KUMAR

1
इंटरफ़ेस बिल्डर में, जब आप तालिका बनाते हैं, तो "गुण निरीक्षक" में आप एक पहचानकर्ता को परिभाषित करते हैं। समान पहचानकर्ता वह है जो आप अपने नियंत्रक में वस्तु को संदर्भित करने के लिए उपयोग करते हैं। let tableCellId = "myAwesomeCell"। मैंने आपकी मदद करने के लिए एक और छवि जोड़ी।
इंटरनेट-निको

16

स्विफ्ट 4

निब पंजी

override func viewDidLoad() {
    super.viewDidLoad()
    tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell")
}

TableView DataSource में

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          guard let cell = tableView.dequeueReusableCell(withIdentifier: "MissionCell", for: indexPath) as? MissionCell else { return UITableViewCell() }
          return cell
    }

9

स्क्रीनशॉट के साथ विस्तृत समाधान

  1. एक खाली उपयोगकर्ता इंटरफ़ेस फ़ाइल बनाएं और उसे नाम दें MyCustomCell.xib

यहां छवि विवरण दर्ज करें

  1. UITableViewCellअपने xib फ़ाइल और किसी भी अन्य दृश्य घटकों के मूल के रूप में जोड़ें जो आप चाहते हैं।

यहां छवि विवरण दर्ज करें

  1. वर्ग MyCustomCellउप नाम के साथ एक कोको टच क्लास फ़ाइल बनाएँ UITableViewCell

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

  1. कस्टम वर्ग सेट करें और अपने कस्टम टेबल व्यू सेल के लिए पहचानकर्ता का पुन: उपयोग करें।

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

  1. सहायक संपादक खोलें और ctrl+dragअपने दृश्य घटकों के लिए आउटलेट बनाएं।

यहां छवि विवरण दर्ज करें

  1. UIViewControllerअपने कस्टम सेल का उपयोग करने के लिए कॉन्फ़िगर करें।
class MyViewController: UIViewController {

    @IBOutlet weak var myTable: UITableView!

    override func viewDidLoad {
        super.viewDidLoad()

        let nib = UINib(nibName: "MyCustomCell", bundle: nil)
        myTable.register(nib, forCellReuseIdentifier: "MyCustomCell")
        myTable.dataSource = self
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell") as? MyCustomCell {
            cell.myLabel.text = "Hello world."
            return cell
        }
        ...
    }
}

आपने मेरा दिन बचाया। मेरे पास .. MyHeaderView.swiftकस्टम सेल के लिए कॉपी किया गया था । .swiftहेडर के लिए दृश्य नहीं है identifierमें Table View Cellमें Attribute Inspector। इसलिए ... रन टाइम एरर हुआ।
mazend 14

वैसे .. हम में .swiftऔर में पहचानकर्ता के लिए एक ही नाम क्यों घोषित किया है tableView?.register(blahblah, forCellReuseIdentifier: "myCell")? मैंने सोचा कि उनमें से एक आवश्यक नहीं है लेकिन .. मैंने पाया कि दोनों आवश्यक हैं।
माज़ेंड

उम .. यह शायद इसलिए क्योंकि .. के .xibलिए कस्टम सेल में कई शामिल हो सकते हैं UITableViewCell.. .xibपर्याप्त नहीं है .. सही सेल खोजें।
माज़ेंड

5

आपने अपने निब को नीचे के रूप में पंजीकृत नहीं किया है:

tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")

4

एक और तरीका जो आपके लिए काम कर सकता है (यह है कि मैं इसे कैसे करता हूं) एक वर्ग का पंजीकरण कर रहा है।

मान लें कि आप निम्न की तरह एक कस्टम तालिका बनाते हैं:

class UICustomTableViewCell: UITableViewCell {...}

आप इस सेल को तब पंजीकृत कर सकते हैं जो कुछ भी UITableViewController में आप इसे "registerClass" के साथ प्रदर्शित करेंगे:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier")
}

और आप इसे पंक्ति विधि के लिए सेल में अपेक्षा के अनुसार कह सकते हैं:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell
    return cell
}

3

"ओवरराइडिंग विधि ... को ठीक करने के लिए ... असंगत प्रकार है ..." त्रुटि के लिए मैंने फ़ंक्शन घोषणा को बदल दिया है

override func tableView(tableView: (UITableView!), 
                        cellForRowAtIndexPath indexPath: (NSIndexPath!)) 
    -> UITableViewCell {...}

(था -> UITableViewCell!- अंत में विस्मयादिबोधक चिह्न के साथ)


2

तेजी से 4.1.2

xib।

ImageCell2.swift बनाएं

चरण 1

import UIKit

class ImageCell2: UITableViewCell {

    @IBOutlet weak var imgBookLogo: UIImageView!
    @IBOutlet weak var lblTitle: UILabel!
    @IBOutlet weak var lblPublisher: UILabel!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}

चरण 2 । व्यूकंट्रोलर वर्ग के अनुसार

  import UIKit

    class ImageListVC: UIViewController,UITableViewDataSource,UITableViewDelegate {
    @IBOutlet weak var tblMainVC: UITableView!

    var arrBook : [BookItem] = [BookItem]()

    override func viewDidLoad() {
        super.viewDidLoad()
         //Regester Cell
        self.tblMainVC.register(UINib.init(nibName: "ImageCell2", bundle: nil), forCellReuseIdentifier: "ImageCell2")
        // Response Call adn Disply Record
        APIManagerData._APIManagerInstance.getAPIBook { (itemInstance) in
            self.arrBook = itemInstance.arrItem!
            self.tblMainVC.reloadData()
        }
    }
    //MARK: DataSource & delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.arrBook.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//    [enter image description here][2]
        let cell  = tableView.dequeueReusableCell(withIdentifier: "ImageCell2") as! ImageCell2
        cell.lblTitle.text = self.arrBook[indexPath.row].title
        cell.lblPublisher.text = self.arrBook[indexPath.row].publisher
        if let authors = self.arrBook[indexPath.row].author {
            for item in authors{
                print(" item \(item)")
            }
        }
        let  url  = self.arrBook[indexPath.row].imageURL
        if url == nil {
            cell.imgBookLogo.kf.setImage(with: URL.init(string: ""), placeholder: UIImage.init(named: "download.jpeg"))
        }
        else{
            cell.imgBookLogo.kf.setImage(with: URL(string: url!)!, placeholder: UIImage.init(named: "download.jpeg"))
        }
        return cell
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 90
    } 

}

2

मुझे यह सुनिश्चित करना था कि जब मैं सेल को हुक कर रहा हूं, यह निर्दिष्ट करने के लिए आउटलेट का निर्माण करें, न कि ऑब्जेक्ट के स्वामी। जब मेनू इसे नाम देता है तो आपको इसे 'ऑब्जेक्ट' ड्रॉपडाउन मेनू में चुनना होगा। बेशक आपको सेल को अपनी कक्षा के रूप में भी घोषित करना होगा, न कि सिर्फ 'टेबल व्यूसेलक्लास'। वरना मैं क्लास को नहीं रख पाती।


1

साधारण वर्ग UITableViewCell के साथ एक xib ले लो । पुनर्मूल्यांकन के अनुसार UI सेट करें और IBOutlet असाइन करें। सेलफोररौट () की तालिका दृश्य की तरह इसका उपयोग करें:

//MARK: - table method

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.arrayFruit.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell:simpleTableViewCell? = tableView.dequeueReusableCell(withIdentifier:"simpleTableViewCell") as? simpleTableViewCell
    if cell == nil{
        tableView.register(UINib.init(nibName: "simpleTableViewCell", bundle: nil), forCellReuseIdentifier: "simpleTableViewCell")
        let arrNib:Array = Bundle.main.loadNibNamed("simpleTableViewCell",owner: self, options: nil)!
        cell = arrNib.first as? simpleTableViewCell
    }

    cell?.labelName.text = self.arrayFruit[indexPath.row]
    cell?.imageViewFruit.image = UIImage (named: "fruit_img")

    return cell!

}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
 return 100.0
}

यहां छवि विवरण दर्ज करें

बिना किसी मुद्दे के 100% काम करना (परीक्षण)


? यह कहते नियंत्रण सेल .labelName नहीं के बराबर है
विग्नेश
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.