Custom UITableViewCell from nib in Swift - ios

I'm trying to create a custom table view cell from a nib. I'm referring to this article here. I'm facing two issues.
I created a .xib file with a UITableViewCell object dragged on to it. I created a subclass of UITableViewCell and set it as the cell's class and Cell as the reusable identifier.
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
}
}
In the UITableViewController I have this code,
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
}
}
This code complies with no errors but when I run it in the simulator, it looks like this.
In the UITableViewController in the storyboard I haven't done anything to the cell. Blank identifier and no subclass. I tried adding the Cell identifier to the prototype cell and ran it again but I get the same result.
Another error I faced is, when I tried to implement the following method in the 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]
}
As shown in the article I mentioned I changed the cell parameter's type form UITableViewCell to CustomOneCell which is my subclass of UITableViewCell. But I get the following error,
Overriding method with selector 'tableView:willDisplayCell:forRowAtIndexPath:' has incompatible type '(UITableView!, CustomOneCell!, NSIndexPath!) -> ()'
Anyone have any idea how to resolve these errors? These seemed to work fine in Objective-C.
Thank you.
EDIT: I just noticed if I change the simulator's orientation to landscape and turn it back to portrait, the cells appear! I still couldn't figure out what's going on. I uploaded an Xcode project here demonstrating the problem if you have time for a quick look.

With Swift 5 and iOS 12.2, you should try the following code in order to solve your problem:
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
}
}
The image below shows a set of constraints that work with the provided code without any constraints ambiguity message from Xcode:

Here's my approach using Swift 2 and Xcode 7.3. This example will use a single ViewController to load two .xib files -- one for a UITableView and one for the UITableCellView.
For this example you can drop a UITableView right into an empty TableNib.xib file. Inside, set the file's owner to your ViewController class and use an outlet to reference the tableView.
and
Now, in your view controller, you can delegate the tableView as you normally would, like so
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
...
To create your Custom cell, again, drop a Table View Cell object into an empty TableCellNib.xib file. This time, in the cell .xib file you don't have to specify an "owner" but you do need to specify a Custom Class and an identifier like "TableCellId"
Create your subclass with whatever outlets you need like so
class TableCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
}
Finally... back in your View Controller, you can load and display the entire thing like so
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)
}
The code shows how you can simply load and display a nib file (the table), and second how to register a nib for cell use.
Hope this helps!!!

Swift 4
Register Nib
override func viewDidLoad() {
super.viewDidLoad()
tblMissions.register(UINib(nibName: "MissionCell", bundle: nil), forCellReuseIdentifier: "MissionCell")
}
In 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
}

Detailed Solution with Screenshots
Create an empty user interface file and name it MyCustomCell.xib.
Add a UITableViewCell as the root of your xib file and any other visual components you want.
Create a cocoa touch class file with class name MyCustomCell as a subclass of UITableViewCell.
Set the custom class and reuse identifier for your custom table view cell.
Open the assistant editor and ctrl+drag to create outlets for your visual components.
Configure a UIViewController to use your custom cell.
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
}
...
}
}

swift 4.1.2
xib.
Create ImageCell2.swift
Step 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)
}
}
step 2 . According Viewcontroller class
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
}
}

You did not register your nib as below:
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")

Another method that may work for you (it's how I do it) is registering a class.
Assume you create a custom tableView like the following:
class UICustomTableViewCell: UITableViewCell {...}
You can then register this cell in whatever UITableViewController you will be displaying it in with "registerClass":
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UICustomTableViewCell.self, forCellReuseIdentifier: "UICustomTableViewCellIdentifier")
}
And you can call it as you would expect in the cell for row method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UICustomTableViewCellIdentifier", forIndexPath: indexPath) as! UICustomTableViewCell
return cell
}

For fix the "Overriding method... has incompatible type..." error I've changed the function declaration to
override func tableView(tableView: (UITableView!),
cellForRowAtIndexPath indexPath: (NSIndexPath!))
-> UITableViewCell {...}
(was -> UITableViewCell! -- with exclamation mark at the end)

I had to make sure that when creating the outlet to specify that I was hooking to the cell, not the object's owner. When the menu appears to name it you have to select it in the 'object' dropdown menu. Of course you must declare the cell as your class too, not just 'TableViewCellClass'. Otherwise I would keep getting the class not key compliant.

Simple take a xib with class UITableViewCell. Set the UI as per reuirement and assign IBOutlet. Use it in cellForRowAt() of table view like this:
//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% working without any issue (Tested)

This line add in TableView cell:
static var nib : UINib{
return UINib(nibName: identifier, bundle: nil)
}
static var identifier : String{
return String(describing: self)
}
And register in viewcontroller like
This line use in viewDidLoad
tableview.register(TopDealLikedTableViewCell.nib, forCellReuseIdentifier: TopDealLikedTableViewCell.identifier)
cell for row at indexpath
if let cell = tableView.dequeueReusableCell(withIdentifier:
TopDealLikedTableViewCell.identifier) as? TopDealLikedTableViewCell{
return cell
}
return UITableViewCell()

Set on cell
static var identifier : String {
return String(describing: self)
}
static var nib : UINib {
return UINib(nibName: identifier, bundle: nil)
}

Related

I was wondering how to make a cell go to another view controller in Xcode 9, swift

I've been trying to figure out how to configure a cell to go to another view, in this case, I'm listing a group of services after login and when the user taps on a service they like, it takes them to a map. But I don't know how to set the cell up in a way that it takes them to the map when its tapped. I've tried creating a segue but nothing happens when the cell is tapped. I'm new to programming and was wondering if someone could explain this.
I've watched a bunch of youtube videos which gave me the understanding on how to set up the cell (basic stuff).
Would really appreciate some advice, thanks!
Hope this post helps anyone that's dipping their feet into the programming journey!
Thank you, happy coding!
Here is the code I currently have:
import UIKit
struct cellData {
let cell : Int!
let text : String!
let image : UIImage! }
class ListServicesTVC: UITableViewController {
var arrayOfCellData = [cellData]()
override func viewDidLoad() {
arrayOfCellData = [cellData(cell : 1, text : "Barber Services", image : #imageLiteral(resourceName: "barberservice") ),
cellData(cell : 2, text : "Salon Services", image : #imageLiteral(resourceName: "salonservice"))]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfCellData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if arrayOfCellData[indexPath.row].cell == 1 {
let cell = Bundle.main.loadNibNamed("BarberServiceCell", owner: self, options: nil)?.first as! BarberServiceCell
cell.barberImageView.image = arrayOfCellData[indexPath.row].image
cell.barberServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
else if arrayOfCellData[indexPath.row].cell == 2 {
let cell = Bundle.main.loadNibNamed("SalonServicesCell", owner: self, options: nil)?.first as! SalonServicesCell
cell.salonImageView.image = arrayOfCellData[indexPath.row].image
cell.salonServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
else {
let cell = Bundle.main.loadNibNamed("BarberServiceCell", owner: self, options: nil)?.first as! BarberServiceCell
cell.barberImageView.image = arrayOfCellData[indexPath.row].image
cell.barberServicesLabel.text = arrayOfCellData[indexPath.row].text
return cell
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if arrayOfCellData[indexPath.row].cell == 1 {
return 120
}
else if arrayOfCellData[indexPath.row].cell == 2 {
return 120
}
else {
return 120
}
}
}
Just follow the steps below:
create A tableView Outlet in ViewController Class.
create a TableViewCell Class and register with tableView Outlet.
then, create a DetailViewController Class ( i.e, When You click on a particular cell, it should show details of that particular cell)
In main "ViewController" do the following code
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {'
#IBOutlet var tableView: UITableView!
var tableData: [String] = ["Apple", "Samsung", "LG"]
// 1
override func viewDidLoad() {
super.viewDidLoad()
// Register customCell with tableView Outlet
let nib = UINib(nibName: "CustomTableViewCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
}
// 2
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
// 3
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: CustomTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! CustomTableViewCell
// injecting data to cell
cell.lblCompanyName.text = tableData[indexPath.row]
cell.imgCompanyName.image = UIImage(named: tableData[indexPath.row])
return cell
}
// 4
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let detailObj=DetailViewController(nibName: "DetailViewController", bundle: nil)
self.navigationController?.pushViewController(detailObj, animated: true)
detailObj.nameVar=tableData[indexPath.row]
detailObj.imgStr=tableData[indexPath.row]
}
In "CustomTableViewCell" class
class CustomTableViewCell: UITableViewCell {
#IBOutlet var imgCompanyName: UIImageView!
#IBOutlet var lblCompanyName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}}
in "DetailViewController"
class DetailViewController: UIViewController {
#IBOutlet var name: UILabel!
#IBOutlet var image: UIImageView!
var nameVar:String?
var imgStr:String?
override func viewDidLoad() {
name.text=nameVar
image.image=UIImage(named: imgStr!)
super.viewDidLoad()
// Do any additional setup after loading the view.
}}
End of the Code
I think I am clear, if you have any quires just comment below.
Hi try the following set of code, I have added few additional changes in your code which is necessary for passing the details, I hope it will solve your issue.
I have added only the extra codes which you needed
class ListServicesTVC: UITableViewController {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: cellData?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Now maintain the selected data in the local variable we declared
selectedItem = arrayOfCellData[indexPath.row]
// Now perform the segue operation
performSegue(withIdentifier: "VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS" {
let destinationVC = segue.destination as? VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS
destinationVC?.selectedItem = self.selectedItem // Pass the selected item here which we have saved on didSelectRotAt indexPath delegate
}
}
In Second class:
class VIEW_CONTROLLER_IDENTIFIER_OF_MAP_CLASS: UIViewController {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: cellData?

Custom cell content doesn't show Swift

I want to create a custom table view. I have an UITableViewController:
class MainListView: UITableViewController{
var invoceList: [InvoceObject] = []
#IBOutlet var tbMain: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(CustomCell.self, forCellReuseIdentifier: "cell")
tbMain.delegate = self
self.tbMain.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.invoceList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.lblBuyerName?.text = self.invoceList[indexPath.row].BUYER_NAME
cell.lblDate?.text = self.invoceList[indexPath.row].CREATED_AT
cell.lblPriceGross?.text = self.invoceList[indexPath.row].PRICE + " " + self.invoceList[indexPath.row].CURRENCY
cell.backgroundColor = UIColor(white: 1, alpha: 0.5)
return cell
}
}
And my UITableViewCell class:
class CustomCell: UITableViewCell {
#IBOutlet weak var lblBuyerName: UILabel!
#IBOutlet weak var lblDate: UILabel!
#IBOutlet weak var lblPriceGross: UILabel!
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
}
}
After build I get an empty cells. I have a number of rows like invoceList.count, but there is no labels and it looks as empty table. What I'm doing wrong?
Since you are using UITableViewController there is an implicit tableView property with connected data source and delegate. You should use that to avoid confusion.
And delete the line self.tableView.register... if you are using prototype cells.
If the cell's contents are defined in a separate xib file, you need to register that, not the class - if you only register the class, the actual labels are not being created because the class itself does not create them.
//Replacing CustomCellNibName with the name of your xib file
tableView.register(UINib.init(nibName: "CustomCellNibName", bundle: nil), forCellReuseIdentifier: "Cell")
If the cell is being created in the storyboard as a prototype cell, you do not need to register it, but just associate the class with your cell in the storyboard file (under the identity inspector tab, Custom Class), and fill in the name you want to use (in this case, "Cell") under the Attributes inspector field Identifier.

Standard UITableViewCell overlaps my Custom Cell

Here what I've done : I made a big custom cell in nib that is much bigger than standard cell and has a blue background.
Here it is, CommonListViewCell.xib
Here's a screenshot that it's connected to a proper class :
Here is this class :
import UIKit
class CommonListViewCell: UITableViewCell {
#IBOutlet var background: UIView!
#IBOutlet var titleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
titleLabel.font = UIFont(name: "roboto", size: titleLabel.font.pointSize)
NSLog("CommonListViewCell font changed")
}
}
And here's my ViewController that has this TableView :
import UIKit
class CommonListFragment: BaseFragment,UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate{
#IBOutlet var lvMain: UITableView!
var prayerList = [PrayerDescription]()
override func viewDidLoad() {
super.viewDidLoad()
self.lvMain.delegate = self;
self.lvMain.dataSource = self;
self.lvMain.registerNib(UINib(nibName: "CommonListViewCell", bundle: nil), forCellReuseIdentifier: "commonlistidentifier")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
convenience init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle? , listType type:Int) {
self.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
switch type{
case A.PRAYERS_TO_SAINTS:
prayerList = PrayerDescriptionEngine.saints
break
case A.CANNONS_AND_ACATHISTS:
prayerList = PrayerDescriptionEngine.acathistsAndCannons
break
default :
prayerList = PrayerDescriptionEngine.allPurpose
break
}
}
override func nightCheck() {
Utils.nightCheck([lvMain])
lvMain.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return prayerList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("commonlistidentifier", forIndexPath: indexPath) as! CommonListViewCell
// Configure the cell...
cell.textLabel?.text = prayerList[indexPath.row].name
setLabelFont(cell.textLabel!)
Utils.nightCheck([cell.textLabel!])
return cell
}
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
parentVC.immedeateClose()
}
func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath){
parentVC.showActions(false)
NSLog("You selected cell #\(prayerList[ indexPath.row].resId)!")
let vc = AllPrayer(nibName :"AllPrayer", bundle: nil)
_=PrayerDescriptionEngine()
vc.setResId(prayerList[ indexPath.row].resId)
self.presentViewController(vc, animated: true, completion: nil)
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
}
And here is the ugly result :
So, my custom table cell is obviously behind standard cell. By some reason, standard cell has the data filled right, and custom cell on the back has "Label" text on it. And custom cell is not the size I specified.
So, please, help me with this one - I need my custom cell to be the only one in TableView, having my color and my size I specified in xib
In tablviewdelegate method, you r accessing cell.textlabel of current tableview while you have to access cell.titlelabel of your custom cell. And you are setting background color of cell, thats why it overlapping it.
You have to access properties of custom cell not of current cell.
So,
Replace cell.textlabel with cell.titlelabel
And as you r loading custom cell remove prototype cell of tableview in storyboard if you have one.
Hope this will work
Is your table view in storyborad?
Select your tableview cell and in the identity inspector make recognise the custom cell class.

Split View Controller - Custom UITableViewCell

I am trying to add a custom UITableViewCell to my Split View Controller Master. When I run my app the cells don't appear, although they do carry the information as confirmed by a println statement. After some research I found out that only standard UITableViewCells are generated.
The Table ViewController has the Data Source and Delegate connected via the Storyboard and the UITableViewCell has a custom Class with Identifier.
The TableView & TableViewCell are in the same ViewController.
The TableViewCell reusable identifier is "ArtistCell" and it's class is ArtistCell.
import UIKit
import MediaPlayer
class ArtistsMasterTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
var artistsQuery:MPMediaQuery!
var artists:NSArray!
var artistAlbums:NSArray!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
artistsQuery = MPMediaQuery.artistsQuery()
artists = artistsQuery.collections
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return artists.count
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println(artists[indexPath.row].items)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ArtistCell", forIndexPath: indexPath) as! ArtistCell
cell.backgroundColor = UIColor.clearColor()
var rowItem:MPMediaItem = artists.objectAtIndex(indexPath.row).representativeItem
if let artwork = rowItem.valueForProperty(MPMediaItemPropertyArtwork) as? MPMediaItemArtwork {
cell.artistImage!.image = artwork.imageWithSize(cell.artistImage.bounds.size)
}
cell.artistNameLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.albumsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.songsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
return cell
}
The custom cell:
class ArtistCell: UITableViewCell {
#IBOutlet weak var artistImage: UIImageView!
#IBOutlet weak var artistNameLabel: UILabel!
#IBOutlet weak var albumsLabel: UILabel!
#IBOutlet weak var songsLabel: UILabel!
}
Here are some Storyboard screenshots:
Great question. From what I've seen the way to implement this is to create a custom xib file that you dequeue. Here is the best article on the subject in objective-c: https://medium.com/#musawiralishah/creating-custom-uitableviewcell-using-nib-xib-files-in-xcode-9bee5824e722
Essentially, you do the following:
Setup your table just like you have minus the reusable cell
Create a custom xib file and make it look like your prototype cell (you can simply do this by making an empty object and dragging a tableviewcell onto the storyboard
Make sure to set the class type of the xib to ArtistCell in the Identity Inspector
Create a custom class ArtistCell to hook the xib up to
Use this code when you are setting up your cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as? ArtistCell
if cell == nil{
tableView .registerNib(UINib(nibName: "ArtistCell", bundle: nil), forCellReuseIdentifier: "cell")
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? ArtistCell
}
cell?.nameLabel.text = "Hello World"
return cell!
}
Here's a screen cap just in case:
This code has been fully tested and works for me. FYI. :-) Hope this helps!
Cheers!
Rob Norback

Xib for UITableViewCell

I want to use a Xib for use as a View for a UITableViewCell. But i'm unsure if i'm doing it the right way (i'm not sure if its dequeuing the cells)
Option #1 where i can call the method "test"
Option #1:
class MainMenuVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
let nib = UINib(nibName: "MenuEntryRomaView", bundle: nil)
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerNib(nib, forCellReuseIdentifier: "cell") // Im guessing this line actually doesnt apply here...
}
#IBAction func test(sender: AnyObject) {
println("go!")
}
}
extension MainMenuVC: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = nib.instantiateWithOwner(self, options: nil).first as MenuEntryView
cell.menuImageView.image = UIImage(named: "close_button")
cell.menuLabel.text = "Texto de menu"
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000
}
}
However i found another solution in this post:
Assigning the outlet for a UITableViewCell using UINib
And could apply in my example like this:
Option 2
class MainMenuVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "MenuEntryRomaView", bundle: nil)
self.tableView.registerNib(nib, forCellReuseIdentifier: "cell")
}
#IBAction func test(sender: AnyObject) {
println("go!")
}
}
extension MainMenuVC: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as MenuEntryView
cell.menuImageView.image = UIImage(named: "close_button")
cell.menuLabel.text = "Texto de menu"
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000
}
}
But im no setting the owner anywhere in this solution, and when i call the method "test" from the xib i get an error. I tried to do nib.instantiateWithOwner(self, options: nil)
after instantianting the nib UINib(nibName..) but with no succeed. Notice i tried both code on the phone with 1k rows and i'm not experiencing any kind of lag (5s). My questions would be: in #option 1 its really dequeing the cells? and what can i do in option 2 to set the owner to MainMenuVC to be able to call the method test from the cells?
UPDATE
Here is a link with a sample project i created, im trying to call from the button inside the cell a method inside the VC.
http://www.ruiznadal.com/TestXibCell.zip

Resources