I have created a TableViewCell entirely in storyboard just as I have in any other app. I want to set the properties however the components inside of it (such as cellScrollView) are returning nil. They are connected via IBOutlet. I have never had this happen to me before, the line where is error occurs is :
cell.cellScrollView.contentSize = CGSizeMake((2 * cell.frame.size.width), cell.frame.size.height)
And the error is:
fatal error: unexpectedly found nil while unwrapping an Optional value
Below is the ViewController..
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var scrollView: UIScrollView!
func random() -> CGFloat { return CGFloat(rand()) / CGFloat(RAND_MAX) }
func randomColor() -> UIColor { return UIColor(red: random(), green: random(), blue: random(), alpha: 1.0) }
override func viewDidLoad() {
super.viewDidLoad()
scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 3, self.view.frame.height)
scrollView.contentOffset = CGPoint(x: self.view.frame.size.width, y: 0)
var tableView = UITableView(frame: CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height))
tableView.dataSource = self
tableView.registerClass(SnapchatTableViewCell.self, forCellReuseIdentifier: "cell")
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
scrollView.addSubview(tableView)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//TableView DataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 80
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as SnapchatTableViewCell
cell.delegate = self
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.cellScrollView.contentSize = CGSizeMake((2 * cell.frame.size.width), cell.frame.size.height) //This is where the crash occurs, the error tells me cell.cellScrollView is nil
return cell
}
}
..and here is the class that inherits UITableViewCell and is the custom class of the cell in storyboard:
import UIKit
class SnapchatTableViewCell: UITableViewCell, UIScrollViewDelegate {
#IBOutlet var cellScrollView: UIScrollView!
#IBOutlet var colorView: UIView!
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
}
//ScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView) {
}
}
Use the viewWithTag() function in the storyboard instead of using outlets.
Give your cellScrollView a tag for example of 100 then simply call cell.viewWithTag(100) as UIScrollView to access your scroll view. Do the same for all subviews in your cell.
Related
I want UI of my app to be similar like as shown in below image.
Using tableview i'm able to get Payment,Delivery,Build Team options as shown in image but for Build Profile,Manage Menu.. how do i do it using tableview ?
If not tableview for these options then what other control i can try.
this type of UI you are looking for and you can easily get by creating different Cell classes
UI Output :
Required Code
Step 1 - Create different Xib of table cell
class viewWithArrow: UITableViewCell {
#IBOutlet weak var headerLabel: 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
}
}
class viewWithShadow: UITableViewCell {
#IBOutlet weak var shadowView: UIView!{
didSet{
shadowView.addShadowToView(color: .black)
}
}
#IBOutlet weak var headerLabel: 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
}
}
Adding Shadow Effect :
extension UIView {
func addShadowToView(color:UIColor)
{
self.layer.shadowColor = color.cgColor
self.layer.shadowOpacity = 0.2
self.layer.masksToBounds = false
self.clipsToBounds = false
self.layer.shadowOffset = CGSize(width: 0, height: 0)
self.layer.shadowRadius = 5
}
}
View controller
class ViewController: UIViewController
{
var dataArray : [String] = ["11","22","33","44","55","66"]
#IBOutlet weak var homeVcTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
homeVcTableView.register(UINib(nibName: "viewWithShadow", bundle: nil), forCellReuseIdentifier: "viewWithShadow")
homeVcTableView.register(UINib(nibName: "viewWithArrow", bundle: nil), forCellReuseIdentifier: "viewWithArrow")
}
override func viewWillAppear(_ animated: Bool) {
self.homeVcTableView.delegate = self
self.homeVcTableView.dataSource = self
}
}
extension ViewController : UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0,1:
let cell = self.homeVcTableView.dequeueReusableCell(withIdentifier: "viewWithShadow", for: indexPath) as! viewWithShadow
cell.headerLabel.text = dataArray[indexPath.row]
return cell
default:
let cell = self.homeVcTableView.dequeueReusableCell(withIdentifier: "viewWithArrow", for: indexPath) as! viewWithArrow
cell.headerLabel.text = dataArray[indexPath.row]
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.homeVcTableView.frame.size.height*0.1
}
}
Working code link - https://drive.google.com/open?id=18mSlWAU_e4XElox4H-oTpqg8clD_HKwu
I'm new to swift and I'm trying to get my cells to show in tableView. I searched for questions here but none could help. The table loads fine and I get no errors regarding the tableView. Is there something I'm missing?
-I've double-checked the reuse identifier, they are the same
-I removed and readied the outlets
Here is my UITableViewController class:
class DrawerViewController: UITableViewController{
#IBOutlet weak var drawerTable: UITableView!
var currentCell = [DrawerModel]()
override func viewDidLoad() {
super.viewDidLoad()
addGradientToView(view: drawerTable)
let temp2Model = DrawerModel()
temp2Model.item = "Profile"
temp2Model.icon = "loginbackground2.jpg"
currentCell.append(temp2Model)
drawerTable.delegate = self
drawerTable.dataSource = self
//self.drawerTable.separatorStyle = UITableViewCellSeparatorStyle.none
//self.drawerTable.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = drawerTable.dequeueReusableCell(withIdentifier: "drawerCell", for: indexPath) as! DrawerTableViewCell
let tempModel: DrawerModel
tempModel = currentCell[indexPath.row]
cell.thisLabel.text = tempModel.item
print("test1" + tempModel.item! as Any)
let currentImage = UIImage(named: "loginbackground2.jpg")
cell.thisImage = UIImageView(image: currentImage)
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1;
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("it ran")
return currentCell.count
}
func addGradientToView(view: UITableView)
{
//gradient layer
let gradientLayer = CAGradientLayer()
//define colors
gradientLayer.colors = [UIColor.init(rgb: 0x4b0082).cgColor, UIColor.init(rgb: 0xfa8072).cgColor]
//define locations of colors as NSNumbers in range from 0.0 to 1.0
//if locations not provided the colors will spread evenly
gradientLayer.locations = [0.0, 0.8]
//define frame
gradientLayer.frame = view.bounds
//insert the gradient layer to the view layer
view.layer.insertSublayer(gradientLayer, at: 0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is my UITableViewCell class:
class DrawerTableViewCell: UITableViewCell {
#IBOutlet weak var thisImage: UIImageView!
#IBOutlet weak var thisLabel: 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
}
}
If you are using UITableViewController (in your case DrawerViewController) it already have a tableView property embedded, which have a delegate and dataSource set to controller.
So when in your case next lines are redundant
drawerTable.delegate = self
drawerTable.dataSource = self
To fix just call tableView.reload() after currentCell.append(temp2Model)
I have the error:
Value of type 'UIView' has no member 'tableView'
occur when I attempt to change the background of the tableView in the viewWillAppear method.
I expected the table view would already be initialised from the viewDidLoad method.
Where should I be trying to change the colours for the tableview? Should I also be changing the other background colours in the same place?
class settingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Table view setup
let tableView = UITableView(frame: view.bounds, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
view.tableView.backgroundColor = UIColor.blackColor() // Error here..
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return settings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(NSStringFromClass(settingsCell), forIndexPath: indexPath) as! settingsCell
// Fetch setting
let cellSetting = settings[indexPath.row]
// Configure Cell
cell.textLabel?.text = cellSetting.name
return cell
}
}
You can make it an instance variable of UITableView like
class settingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Table view setup
tableView = UITableView(frame: view.bounds, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
tableView.backgroundColor = UIColor.blackColor()
}
}
This is not the right way of accessing a subview within a view. You can use viewWithTag: to get the subview by tag:
override func viewDidLoad() {
...
tableView.tag = 100
view.addSubview(tableView)
}
...
override func viewWillAppear(animated: Bool) {
...
if let tableView = view.viewWithTag(100) {
tableView.backgroundColor = UIColor.blackColor()
}
}
Alternatively, you make tableView an instance variable if you need to access it in more than just viewWillAppear:
class SettingsViewController: UIViewController ... {
var tableView: UITableView!
...
override func viewDidLoad() {
...
self.tableView = UITableView(frame: view.bounds, style: .Plain)
...
}
override func viewWillAppear(animated: Bool) {
...
self.tableView.backgroundColor = UIColor.blackColor()
}
}
Declare the tableview in global value, then use the tableview in class, see the below code,
class ViewController: UIViewController {
var tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableview.frame = self.view.bounds
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
self.view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
tableView.backgroundColor = UIColor.blackColor()
}
}
hope its helpful
i'm stuck here since two days ago, and cant find how to manage this..
I have an uitableview, with an array of custom cells and sections, here's what i want to do:
Section 1: just a row with a label inside
Section 2: a datepicker (i used DVDatePickerTableViewCell class for this)
here's the code for the table view
import UIKit
class DettagliRichiestaTVC: UITableViewController {
//sections contiene le sezioni
let sections: NSArray = ["Stato", "Data", "Priorità", "Richiesta", "Risposta"]
//cells contiene tutte le righe della tabella, un 2D array
var cells:NSArray = []
var stato:String = "Completato"
#IBOutlet weak var statoLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// statoLabel.text = stato
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44
// Cells is a 2D array containing sections and rows.
var cellStato = cellDettagli(style: UITableViewCellStyle.Default, reuseIdentifier: "cellStato")
cellStato.label?.text = "Ciao"
cells = [
[cellStato],
[DVDatePickerTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)]
]
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func selectedStato(segue:UIStoryboardSegue) {
let statoRichiesteTVC = segue.sourceViewController as StatoRichiesteTVC
if let selectedStato = statoRichiesteTVC.selectedStato {
statoLabel.text = selectedStato
stato = selectedStato
}
self.navigationController?.popViewControllerAnimated(true)
}
// MARK: - Table view data source
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerFrame:CGRect = tableView.frame
var title = UILabel(frame: CGRectMake(10, 10, 100, 20))
title.font = UIFont.boldSystemFontOfSize(12.0)
title.text = self.sections.objectAtIndex(section) as? String
title.textColor = UIColor(red: 0.6, green: 0.6, blue: 0.6, alpha: 1)
var headerView:UIView = UIView(frame: CGRectMake(0, 0, headerFrame.size.width, headerFrame.size.height))
headerView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.8)
headerView.addSubview(title)
return headerView
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = self.tableView(tableView, cellForRowAtIndexPath: indexPath)
if (cell.isKindOfClass(DVDatePickerTableViewCell)) {
return (cell as DVDatePickerTableViewCell).datePickerHeight()
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return cells.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cells[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cells[indexPath.section][indexPath.row] as UITableViewCell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell = self.tableView(tableView, cellForRowAtIndexPath: indexPath)
if (cell.isKindOfClass(DVDatePickerTableViewCell)) {
var datePickerTableViewCell = cell as DVDatePickerTableViewCell
datePickerTableViewCell.selectedInTableView(tableView)
}
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//println(segue.identifier)
if segue.identifier == "SavePlayerDetail" {
}
if segue.identifier == "SelezionaStatoRichiesta" {
let statoRichiesteTVC = segue.destinationViewController as StatoRichiesteTVC
statoRichiesteTVC.selectedStato = stato
}
}
}
and here's the custom cell class
import UIKit
class cellDettagli: UITableViewCell {
#IBOutlet weak var label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func loadItem(#Label: String) {
label.text = Label
}
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 setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
if i set cellStato.label?.text = "Ciao" , it crashes saying "fatal error: unexpectedly found nil while unwrapping an Optional value" .
I created also the .xib file and assigned that to cellDettagli class.
I always get that error.
How can i set the values of this label, and the date of the datepicker row?
Thank you
I made it work using this:
var cell:cellDettagli? = tableView.dequeueReusableCellWithIdentifier("cellDettagli") as? cellDettagli
if (cell==nil){
var nib:NSArray=NSBundle.mainBundle().loadNibNamed("cellDettagli", owner: self, options: nil)
cell = nib.objectAtIndex(0) as? cellDettagli
}
inside my cellForRowAtIndexPath.
Thank you Alexander for your help! I already use static cells and storyboards...!
You're creating cells using the designated initialiser, which means the views that you've added in the nib won't be there at runtime. You will need to register your nib with the tableview first using registerNib:forCellReuseIdentifier:, then dequeue cells accordingly using dequeueReusableCellWithIdentifier:forIndexPath:.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html
Since it looks like you're using static cells, you might be better off using a storyboard with "Static Cells" content type on your table view instead of "Dynamic Prototypes".
For more information on static cells, see the docs https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/CreateConfigureTableView/CreateConfigureTableView.html
While running the code in XCode 6.1 nothing appears in the ViewController.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView!
var messages: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
self.view.addSubview(self.tableView)
//http://stackoverflow.com/questions/25413239/custom-uitablecellview-programmatically-using-swift
//Auto-set the UITableViewCells height (requires iOS8)
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
// add something to messages
messages.append("foo")
messages.append("bar")
}
// TABLEVIEWS
//func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
// return 1
//}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = messages.count ?? 0
NSLog("message count: \(count)")
return count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//var cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as MyCell
var cell = UITableViewCell()
NSLog("row[\(indexPath.row)]: \(messages[indexPath.row])")
cell.textLabel.text = messages[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Try this Code:
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
self.view.addSubview(self.tableView)
//Auto-set the UITableViewCells height (requires iOS8)
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
tableView.frame = CGRectMake(0, 0, 320, 568)
// add something to messages
messages.append("foo")
messages.append("bar")
}
EDIT:Try this for all size of screen :
tableView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
Hmm why make it so hard for your self. In the story board you can either add a TableViewController to the project or add a tableview to you viewcontroller and it will work out of the box. The controller class should inherit from UITableViewController.