J'ai une classe de cellules personnalisée avec quelques IBOutlets. J'ai ajouté la classe au storyboard. J'ai connecté tous mes points de vente. ma fonction cellForRowAtIndexPath ressemble à ceci:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as SwipeableCell
cell.mainTextLabel.text = self.venueService.mainCategoriesArray()[indexPath.row]
return cell
}
Voici ma classe de cellule personnalisée:
class SwipeableCell: UITableViewCell {
@IBOutlet var option1: UIButton
@IBOutlet var option2: UIButton
@IBOutlet var topLayerView : UIView
@IBOutlet var mainTextLabel : UILabel
@IBOutlet var categoryIcon : UIImageView
init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
}
Lorsque je lance l'application, toutes mes cellules sont vides. Je me suis déconnecté self.venueService.mainCategoriesArray()
et il contient toutes les chaînes correctes. J'ai également essayé de mettre une chaîne réelle égale à l'étiquette, et cela produit le même résultat.
Qu'est-ce que je rate? Toute aide est appréciée.
Merci pour toutes les suggestions différentes, mais j'ai finalement compris. La classe personnalisée a été configurée correctement. Tout ce que je devais faire, c’était dans le storyboard où je choisissais la classe personnalisée: supprimez-la et sélectionnez-la à nouveau. Cela n'a pas beaucoup de sens, mais cela a fini par fonctionner pour moi.
Testé avec Xcode 9 et Swift 4
Le demandeur de la question initiale a résolu son problème. J'ajoute cette réponse en tant que mini-projet d'exemple autonome pour ceux qui essaient de faire la même chose.
Le projet fini devrait ressembler à ceci:
Il peut s'agir simplement d'une application à vue unique.
Ajoutez un nouveau fichier Swift à votre projet. Nommez-le MyCustomCell.Swift. Cette classe contient les points de vente des vues que vous ajoutez à votre cellule dans le storyboard.
import UIKit
class MyCustomCell: UITableViewCell {
@IBOutlet weak var myView: UIView!
@IBOutlet weak var myCellLabel: UILabel!
}
Nous connecterons ces prises plus tard.
Ouvrez ViewController.Swift et assurez-vous que vous avez le contenu suivant:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// These strings will be the data for the table view cells
let animals: [String] = ["Horse", "Cow", "Camel", "Sheep", "Goat"]
// These are the colors of the square views in our table view cells.
// In a real project you might use UIImages.
let colors = [UIColor.blue, UIColor.yellow, UIColor.Magenta, UIColor.red, UIColor.brown]
// Don't forget to enter this in IB also
let cellReuseIdentifier = "cell"
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// number of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.animals.count
}
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myView.backgroundColor = self.colors[indexPath.row]
cell.myCellLabel.text = self.animals[indexPath.row]
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
}
Ajoutez une vue Table à votre contrôleur de vue et utilisez la présentation automatique pour l'épingler aux quatre côtés du contrôleur de vue. Faites ensuite glisser une cellule de la vue tableau dans la vue tableau. Ensuite, faites glisser une vue et une étiquette sur la cellule Prototype. (Vous devrez peut-être sélectionner la cellule d'affichage du tableau et définissez manuellement la hauteur de ligne pour qu'elle soit plus haute dans l'inspecteur de taille afin de disposer de davantage d'espace pour travailler.) Utilisez la disposition automatique pour corriger l'affichage et le Indiquez comment vous souhaitez les organiser dans la vue Contenu de la cellule Table View. Par exemple, j'ai créé une vue 100x100.
Nom de classe et identifiant personnalisés
Sélectionnez la cellule de la vue tableau et définissez la classe personnalisée sur MyCustomCell
(le nom de la classe dans le fichier Swift que nous avons ajouté). Définissez également l'identificateur sur cell
(la même chaîne que celle utilisée pour cellReuseIdentifier
dans le code ci-dessus.
Raccordez les prises
tableView
du code ViewController
.myView
et myCellLabel
de la classe MyCustomCell
.C'est ça. Vous devriez pouvoir exécuter votre projet maintenant.
UIImageView
.Ceci est pour qui travaille cellule personnalisée avec .xib
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let identifier = "Custom"
var cell: CustomCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomCel
if cell == nil {
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: identifier)
cell =tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomCell
}return cell}
J'ai le même problème.
Généralement ce que j'ai fait est le même que toi.
class dynamicCell: UITableViewCell {
@IBOutlet var testLabel : UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
et dans la méthode uitableviewcell:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell :dynamicCell = tableView.dequeueReusableCellWithIdentifier("cell") as dynamicCell
cell.testLabel.text = "so sad"
println(cell.testLabel)
return cell;
}
et oui la table ne montre rien! Mais devinez quoi, cela montre en réalité quelque chose ... parce que le journal que je tire de println (cell.testLabel) montre que toutes les étiquettes sont réellement affichées.
MAIS! leurs cadres est étrange, qui ont quelque chose comme ça:
cadre = (0 à 21; 42 à 21);
il a donc un (0, -21) comme (x, y), ce qui signifie que l'étiquette apparaît juste à quelque part en dehors de la limite de la cellule.
donc j'essaye d'ajouter ajuster le cadre manuellement comme ceci:
cell.testLabel.frame = CGRectMake (10, 10, 42, 21)
et malheureusement, ça ne marche pas.
--------------- mise à jour après 10 min -----------------
I DID IT. Il semble donc que le problème vienne des classes de taille.
Cliquez sur votre fichier .storyboard et accédez à l'onglet Inspecteur de fichier.
Décochez la case de la classe de taille
et finalement, mon label "tellement triste" sort!
La dernière version mise à jour est avec xCode 6.1
class StampInfoTableViewCell: UITableViewCell{
@IBOutlet weak var stampDate: UILabel!
@IBOutlet weak var numberText: UILabel!
override init?(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init(coder aDecoder: NSCoder) {
//fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
[1] D'abord, concevez votre cellule tableview dans StoryBoard.
[2] Mettez en dessous de la méthode déléguée de la vue tablea
// MARK: - Méthodes de délégué Tableview
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return <“Your Array”>
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
var totalHeight : CGFloat = <cell name>.<label name>.frame.Origin.y
totalHeight += UpdateRowHeight(<cell name>.<label name>, textToAdd: <your array>[indexPath.row])
return totalHeight
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : <cell name>! = tableView.dequeueReusableCellWithIdentifier(“<cell identifire>”, forIndexPath: indexPath) as! CCell_VideoCall
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("<cell identifire>", owner: self, options: nil)[0] as! <cell name>;
}
<cell name>.<label name>.text = <your array>[indexPath.row] as? String
return cell as <cell name>
}
// MARK: - Méthodes personnalisées
func UpdateRowHeight ( ViewToAdd : UILabel , textToAdd : AnyObject ) -> CGFloat{
var actualHeight : CGFloat = ViewToAdd.frame.size.height
if let strName : String? = (textToAdd as? String)
where !strName!.isEmpty
{
actualHeight = heightForView1(strName!, font: ViewToAdd.font, width: ViewToAdd.frame.size.width, DesignTimeHeight: actualHeight )
}
return actualHeight
}
import UIKit
// MARK: - IdentifiableCell protocol will generate cell identifire based on the class name
protocol Identifiable: class {}
extension Identifiable { static var identifier: String { return "\(self)"} }
// MARK: - Functions which will use a cell class (conforming Identifiable protocol) to `dequeueReusableCell`
extension UITableView {
typealias IdentifiableCell = UITableViewCell & Identifiable
func register<T: IdentifiableCell>(class: T.Type) { register(T.self, forCellReuseIdentifier: T.identifier) }
func register(classes: [Identifiable.Type]) { classes.forEach { register($0.self, forCellReuseIdentifier: $0.identifier) } }
func dequeueReusableCell<T: IdentifiableCell>(aClass: T.Type, initital closure: ((T) -> Void)?) -> UITableViewCell {
guard let cell = dequeueReusableCell(withIdentifier: T.identifier) as? T else { return UITableViewCell() }
closure?(cell)
return cell
}
func dequeueReusableCell<T: IdentifiableCell>(aClass: T.Type, for indexPath: IndexPath, initital closure: ((T) -> Void)?) -> UITableViewCell {
guard let cell = dequeueReusableCell(withIdentifier: T.identifier, for: indexPath) as? T else { return UITableViewCell() }
closure?(cell)
return cell
}
}
extension Array where Element == UITableViewCell.Type {
var onlyIdentifiables: [Identifiable.Type] { return compactMap { $0 as? Identifiable.Type } }
}
// Define cells classes
class TableViewCell1: UITableViewCell, Identifiable { /*....*/ }
class TableViewCell2: TableViewCell1 { /*....*/ }
// .....
// Register cells
tableView.register(classes: [TableViewCell1.self, TableViewCell2.self]. onlyIdentifiables)
// Create/Reuse cells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.row % 2) == 0 {
return tableView.dequeueReusableCell(aClass: TableViewCell1.self, for: indexPath) { cell in
// ....
}
} else {
return tableView.dequeueReusableCell(aClass: TableViewCell2.self, for: indexPath) { cell in
// ...
}
}
}
N'oubliez pas d'ajouter le code de la solution ici
import UIKit
class ViewController: UIViewController {
private weak var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
}
// MARK: - Setup(init) subviews
extension ViewController {
private func setupTableView() {
let tableView = UITableView()
view.addSubview(tableView)
self.tableView = tableView
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.register(classes: [TableViewCell1.self, TableViewCell2.self, TableViewCell3.self].onlyIdentifiables)
tableView.dataSource = self
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int { return 1 }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch (indexPath.row % 3) {
case 0:
return tableView.dequeueReusableCell(aClass: TableViewCell1.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
case 1:
return tableView.dequeueReusableCell(aClass: TableViewCell2.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
default:
return tableView.dequeueReusableCell(aClass: TableViewCell3.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
}
}
}
C’est purement Swift fonctionne pour moi)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cellIdentifier:String = "CustomFields"
var cell:CustomCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomCell
if (cell == nil)
{
var nib:Array = NSBundle.mainBundle().loadNibNamed("CustomCell", owner: self, options: nil)
cell = nib[0] as? CustomCell
}
return cell!
}
Décochez la case "Classes de taille" pour moi aussi, mais vous pouvez également ajouter les contraintes manquantes dans le générateur d'interface. Utilisez simplement la fonction intégrée si vous ne voulez pas ajouter les contraintes vous-même. À mon avis, le meilleur moyen consiste à utiliser des contraintes, car la mise en page est indépendante de l'appareil (iPhone ou iPad).
La documentation de référence Apple est assez complète
Faites défiler jusqu'à ce que vous voyez cette partie
Définir une balise pour imageview et une étiquette dans la cellule
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("imagedataCell", forIndexPath: indexPath) as! UITableViewCell
let rowData = self.tableData[indexPath.row] as! NSDictionary
let urlString = rowData["artworkUrl60"] as? String
// Create an NSURL instance from the String URL we get from the API
let imgURL = NSURL(string: urlString!)
// Get the formatted price string for display in the subtitle
let formattedPrice = rowData["formattedPrice"] as? String
// Download an NSData representation of the image at the URL
let imgData = NSData(contentsOfURL: imgURL!)
(cell.contentView.viewWithTag(1) as! UIImageView).image = UIImage(data: imgData!)
(cell.contentView.viewWithTag(2) as! UILabel).text = rowData["trackName"] as? String
return cell
}
[~ # ~] ou [~ # ~]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "imagedataCell")
if let rowData: NSDictionary = self.tableData[indexPath.row] as? NSDictionary,
urlString = rowData["artworkUrl60"] as? String,
imgURL = NSURL(string: urlString),
formattedPrice = rowData["formattedPrice"] as? String,
imgData = NSData(contentsOfURL: imgURL),
trackName = rowData["trackName"] as? String {
cell.detailTextLabel?.text = formattedPrice
cell.imageView?.image = UIImage(data: imgData)
cell.textLabel?.text = trackName
}
return cell
}
voir aussi le chargeur de tableImage de github