Swift'te uçtan özel UITableViewCell


140

Bir uçtan özel bir tablo görünümü hücre oluşturmaya çalışıyorum. Burada bu makaleye atıfta bulunuyorum . İki sorunla karşı karşıyayım.

Üzerine sürüklenen bir UITableViewCell nesnesi ile bir .xib dosyası oluşturdum. Bir alt sınıf oluşturdum UITableViewCellve onu hücre sınıfı ve Hücre'yi yeniden kullanılabilir tanımlayıcı olarak ayarladım .

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 bu kod var,

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

Bu kod hiçbir hata ile uyumlu değildir, ancak simülatörde çalıştırdığımda, böyle görünüyor.

resim açıklamasını buraya girin

Film şeridindeki UITableViewController'da hücreye hiçbir şey yapmadım. Boş tanımlayıcı ve alt sınıf yok. Prototip hücresine Hücre tanımlayıcısını eklemeyi denedim ve tekrar çalıştırdım ama aynı sonucu alıyorum.

UITableViewController içinde aşağıdaki yöntemi uygulamaya çalışırken karşılaştığım başka bir hata.

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

Bahsettiğim yazıda gösterildiği gibi Değiştim cellparametrenin tipi formunu UITableViewCelliçin CustomOneCellhangi UITableViewCell benim alt sınıfıdır. Ama şu hatayı alıyorum,

'TableView: willDisplayCell: forRowAtIndexPath:' uyumsuz türüne sahip '(UITableView !, CustomOneCell !, NSIndexPath!) -> ()' seçicisi ile geçersiz kılma yöntemi

Herkes bu hataları çözmek için herhangi bir fikri var mı? Bunlar Objective-C'de işe yaramış gibi görünüyordu.

Teşekkür ederim.

DÜZENLEME: Simülatörün yönünü yatay olarak değiştirip tekrar portre haline döndürürsem, hücreler ortaya çıkıyor! Hala neler olduğunu anlayamıyordum. Bir Xcode projesini yüklenen burada hızlı bir görünüm için zamanınız varsa sorunu gösteren.

Yanıtlar:


213

Swift 5 ve iOS 12.2 ile sorununuzu çözmek için aşağıdaki kodu denemelisiniz:

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
    }

}

Aşağıdaki resim, Xcode'dan herhangi bir kısıtlama belirsizliği mesajı olmadan sağlanan kodla çalışan bir kısıtlama kümesini göstermektedir:

resim açıklamasını buraya girin


1
Yanıt için teşekkürler. Ama bu da işe yaramadı. Tablo görünümü denetleyicisindeki herhangi bir şeyi değiştirmem gerekir mi? Çünkü hala hücreleri prototiplemek için ayarlanmış.
Isuru

1
Prototip hücreleri kullanmaya devam edin. Ancak (Otomatik düzen kullanıyorsanız) iyi Otomatik düzen kısıtlamalarını ayarladığınızdan emin olun.
Imanou Petit

1
Buraya yaşadığım sorunu gösteren bir test projesi yükledim . Vaktiniz varsa lütfen bir göz atabilir misiniz?
Isuru

1
Test projeniz onaylıyor: .xib dosyanızdaki özel hücreniz için otomatik düzen kısıtlamaları ayarladıktan sonra uygulamanızın iyi çalışmasını sağlayabildim. Otomatik düzen hakkında daha fazla bilgi edinmek istiyorsanız bu videoya göz atın .
Imanou Petit

2
@KirillKudaev, Swift 4'te yeniden adlandırılmadı, ancak Swift 3'te: Düzenlemenizi düzelttim.
Octur

30

İşte Swift 2 ve Xcode 7.3 kullanma yaklaşımım. Bu örnek, biri UITableView ve diğeri UITableCellView için olmak üzere iki .xib dosyasını yüklemek için tek bir ViewController kullanacaktır.

resim açıklamasını buraya girin

Bu örnek için UITableView öğesini boş bir TableNib .xib dosyasına bırakabilirsiniz . İçinde, dosyanın sahibini ViewController sınıfınıza ayarlayın ve tableView öğesine başvurmak için bir çıkış kullanın.

resim açıklamasını buraya girin

ve

resim açıklamasını buraya girin

Şimdi, görünüm denetleyicinizde, tableView'e normalde yaptığınız gibi yetki verebilirsiniz

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

        ...

Özel hücrenizi oluşturmak için yine bir Tablo Görünümü Hücresi nesnesini boş bir TableCellNib .xib dosyasına bırakın . Bu kez, hücre .xib dosyasında bir "sahip" belirtmeniz gerekmez, ancak bir Özel Sınıf ve "TableCellId" gibi bir tanımlayıcı belirtmeniz gerekir

resim açıklamasını buraya girin resim açıklamasını buraya girin

İhtiyacınız olan prizlerle alt sınıfınızı oluşturun

class TableCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!

}

Son olarak ... View Controller'ınıza geri döndüğünüzde, her şeyi böyle yükleyebilir ve görüntüleyebilirsiniz

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)

}

Kod, bir uç dosyasını (tablo) nasıl basitçe yükleyip görüntüleyebileceğinizi ve ikinci olarak hücre kullanımı için bir ucun nasıl kaydedileceğini gösterir.

Bu yardımcı olur umarım!!!


2
bu satırda "tableCellId" ne olduğunu açıklayabilir .... self.tableView.registerNib (cellNib, forCellReuseIdentifier: self.tableCellId) .... ne olduğunu tanımladıysanız. ve tanımlayıcıyı xib ile manuel olarak tanımlayamazsınız. Tanımlamak için hiçbir seçenek yoktur
PRADIP KUMAR 27:16

1
Arabirim oluşturucuda, tableCell oluşturduğunuzda, "öznitelik denetçisinde" bir tanımlayıcı tanımlarsınız. Aynı tanımlayıcı, denetleyicinizde nesneye başvurmak için kullandığınız tanımlayıcıdır. let tableCellId = "myAwesomeCell". Sana yardım etmek için başka bir resim ekledim.
internet-nico

16

Hızlı 4

Ucu Kaydet

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

TableView DataSource içinde

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

Ekran Görüntüleri ile Ayrıntılı Çözüm

  1. Boş bir kullanıcı arabirimi dosyası oluşturun ve adlandırın MyCustomCell.xib.

resim açıklamasını buraya girin

  1. Bir ekleme UITableViewCellsenin xib dosyasının kökü ve istediğiniz diğer görsel bileşenleri olarak.

resim açıklamasını buraya girin

  1. Alt sınıfı MyCustomCellolarak sınıf adına sahip bir kakao dokunma sınıfı dosyası oluşturun UITableViewCell.

resim açıklamasını buraya girin resim açıklamasını buraya girin

  1. Özel tablo görünümü hücreniz için özel sınıfı ve yeniden kullanım tanımlayıcısını ayarlayın.

resim açıklamasını buraya girin resim açıklamasını buraya girin

  1. Yardımcı düzenleyiciyi açın ve ctrl+draggörsel bileşenleriniz için çıkışlar oluşturun.

resim açıklamasını buraya girin

  1. A'yı UIViewControllerözel hücrenizi kullanacak şekilde yapılandırın .
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
        }
        ...
    }
}

Günümü kurtardın. MyHeaderView.swiftÖzel hücre için kopyaladım . .swiftBaşlık için görünüm yok identifieriçinde Table View Cellde Attribute Inspector. yani ... çalışma zamanı hatası oluştu.
mazend

Bu arada .. neden biz tanımlayıcı için aynı adı beyan var mı .swiftve de tableView?.register(blahblah, forCellReuseIdentifier: "myCell")? İçlerinden birinin gerekli olmadığını düşündüm ama .. Her ikisinin de gerekli olduğunu gördüm.
mazend

um .. Belki çünkü .. .xibözel hücre için birden fazla içerebilir UITableViewCellböylece .. .xibdoğru hücre bulmak için yeterli değildir ...
mazend

5

Uçunuzu aşağıdaki gibi kaydetmediniz:

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

4

Sizin için çalışabilecek başka bir yöntem de (bunu nasıl yaparım) bir sınıfa kaydolmaktır.

Aşağıdaki gibi özel bir tablo oluşturduğunuzu varsayın:

class UICustomTableViewCell: UITableViewCell {...}

Daha sonra bu hücreyi "registerClass" ile görüntüleyeceğiniz UITableViewController'a kaydedebilirsiniz:

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

Ve satır yöntemi için hücrede beklediğiniz gibi çağırabilirsiniz:

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

3

"Geçersiz kılma yöntemi ... uyumsuz tip var ..." hatası düzeltmek için İşlev bildirimini değiştirdim

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

(sonunda -> UITableViewCell!- ünlem işareti vardı)


2

hızlı 4.1.2

xib.

ImageCell2.swift oluştur

Aşama 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)
    }

}

Adım 2 . Viewcontroller sınıfına göre

  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

Çıkış oluştururken nesnenin sahibine değil, hücreye bağlandığımı belirtmek zorunda kaldım. Menü isimlendirildiğinde göründüğünde 'nesne' açılır menüsünden seçmeniz gerekir. Tabii ki sadece 'TableViewCellClass' değil, aynı zamanda hücre sınıf olarak ilan etmelisiniz. Aksi takdirde sınıf anahtar uyumlu değil almaya devam ediyorum.


1

UITableViewCell sınıfıyla basit bir xib alın . Kullanıcı arayüzünü reuirement'a göre ayarlayın ve IBOutlet'i atayın. Tablo görünümünün cellForRowAt () yönteminde şu şekilde kullanın:

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

resim açıklamasını buraya girin

% 100 sorunsuz çalışıyor (Test edildi)


kontrol hücresi diyor? .labelName nil
Vignesh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.