How to initialize customized UITableViewCell ui-related property - ios

I am created a custom UITableViewCell and added some outlet fields which connect to the UI elements on storyboard. Please see below as an example. But I always got nil pointer exception on the line "self.skillBtn.backgroundColor = UIColor.redColor()" in "required init?(coder aDecoder: NSCoder) " method. It means that the skillBtn has not been initialized yet. I wander where I should do the UI initialization on a UITableViewCell?
#IBOutlet weak var backgroundImg: UIImageView!
#IBOutlet weak var userNameLabel: UILabel!
var delegate: UserHomeCategorySelectionDelegate?
#IBOutlet weak var skillBtn: UserHomeCategoryButton!
#IBOutlet weak var speakBtn: UserHomeCategoryButton!
#IBOutlet weak var friendsBtn: UserHomeCategoryButton!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.skillBtn.backgroundColor = UIColor.redColor()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.skillBtn.backgroundColor = UIColor.redColor()
}

Thats because the views are not yet connected from your Storyboard/XIB to your class instance,
to achieve what you want, override awakeFromNib method and put self.skillBtn.backgroundColor = UIColor.redColor() inside it.
awakeFromNib is called after view is loaded from the XIB/Storyboard and outlets are connected.

Related

How can I use a custom initializer on a UITableViewCell?

I have a custom UITableViewCell and I'd like to use it in my table view. Here's my code for the cell:
class ReflectionCell: UITableViewCell {
#IBOutlet weak var header: UILabel!
#IBOutlet weak var content: UILabel!
#IBOutlet weak var author: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
init(data: Reflection) {
self.header.text = data.title
self.content.text = data.content
self.author.text = data.author.name
super.init(style: UITableViewCellStyle.default, reuseIdentifier: "reflectionCell")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
I have a model class Reflection that I'd like to initialize the cell with. However, in my view controller I need to use tableView.dequeueReusableCell(withIdentifier: "reflectionCell", for: indexPath). Is there any way for me to use a custom initializer like the one I made?
If you use dequeueReusableCell you cannot change which initializer method that is called. But you can write your own method to update the IBOutlets which you then call after you successfully dequeue a cell.
class ReflectionCell: UITableViewCell {
#IBOutlet weak var header: UILabel!
#IBOutlet weak var content: UILabel!
#IBOutlet weak var author: UILabel!
func update(for reflection: Reflection) {
header.text = reflection.title
content.text = reflection.content
author.text = reflection.author.name
}
}
And
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! ReflectionCell
cell.update(for: reflections[indexPath.row])
return cell
}

Property 'self.delegate' not initialised at super.init

I am trying to make a protocol in a UITableViewCell class but when i declare my delegate, I get an error in both required init?(coder aDecoder: NSCoder) and override init(style: UITableViewCellStyle, reuseIdentifier: String?)
Error : - Property 'self.delegate' not initialised at super.init
This is my subclass:-
import UIKit
protocol tableCellBtnActionDelegate{
func removeRowAtIndex(_: Int)
}
class FriendsListTableViewCell: UITableViewCell {
#IBOutlet weak var friendListAddBtn: UIButton!
var usersId : String!
var buttonText : String!
var indexPath : Int!
let delegate : tableCellBtnActionDelegate!
override func awakeFromNib() {
super.awakeFromNib()
friendListAddBtn.layer.cornerRadius = 4
friendListAddBtn.layer.backgroundColor = UIColor(red: 121.0/255.0, green: 220.0/255.0, blue: 1, alpha: 1).CGColor
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
}
Well you haven't initialize it, so the compiler gives you a warning.
I would advise you to modify the delegate to be optional and set your delegate whenever you need it.
var delegate : tableCellBtnActionDelegate?
You should also handle the case where delegate is not set(nil).
Change
let delegate : tableCellBtnActionDelegate!
to
var delegate : tableCellBtnActionDelegate!
or you can't set value to delegate property ever
You got a warning because you are not initialising the delegate property. It should actually be a weak property, or you will retain a reference to the delegate object, which you usually don't want to do. So the best approach would be:
weak var delegate : tableCellBtnActionDelegate?
And then you have to use it like this:
self.delegate?.notifyAboutSomething()

ScrollView in NIB File Swift

I'm trying to create a nib file where the view outlet is a uiview with a fullscreen UIScrollView. I want to add the actual view into the scrollview, if that makes sense (I will attach screen shots). I've tried a few different approaches, most being in Objective-C, but can't get this approach working. When i run the code below I get (lldb) in the console with no other error text.
class ScrollViewVC: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
#IBOutlet var contentView: UIView!
#IBOutlet weak var contentViewTitle: UILabel!
#IBOutlet weak var contentViewPrice: UILabel!
#IBOutlet weak var contentViewImageContainer: UIScrollView!
#IBOutlet var imageContainer: UIView!
#IBOutlet weak var imageOne: UIImageView!
#IBOutlet weak var imageTwo: UIImageView!
#IBOutlet weak var imageThree: UIImageView!
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
convenience init() {
self.init(nibName: "ScrollViewVC", bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.mainScrollView.addSubview(contentView)
self.mainScrollView.contentSize = self.contentView.frame.size
self.contentViewImageContainer.addSubview(self.imageContainer)
self.contentViewImageContainer.contentSize = self.imageContainer.frame.size
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
self.mainScrollView.addSubview(contentView)
this line crashes your app. Check where your contentView outlet points. It points to the view which in your IB has a name "Main Scroll View". Inside if it you have a scroll view to which you have a mainScrollView outlet connection.
So, you are trying to add to the scroll view the view which contains this scroll view. No wonder your app crashes.
Be very careful with the outlets which you assign.

How do I set an initializer for a custom UITableViewCell class?

I've searched around for an answer to this, but each solution just brings new compiler errors.
How do I set up the initializers for a class that inherits from UITableViewCell?
This is what I have so far, any help would be greatly appreciated:
SettingCell.swift
class SettingCell: UITableViewCell {
#IBOutlet weak var settingsLabel: UILabel!
#IBOutlet weak var settingsSwitch: UISwitch?
#IBOutlet weak var timeSetting: UILabel?
var cellDelegate: SettingCellDelegate?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
init(settingLabel: UILabel!, settingSwitch: UISwitch?, timeSetting: UILabel?) {
super.init(style: UITableViewCellStyle, reuseIdentifier: String?)
self.settingsLabel = settingLabel
self.settingsSwitch = settingSwitch
self.timeSetting = timeSetting
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#IBAction func handledSwitchChange(sender: UISwitch) {
self.cellDelegate?.didChangeSwitchState(sender: self, isOn:settingsSwitch!.on)
}
...
}
Fix-It Error:
Compiler Error:
'UITableViewCellStyle.Type' is not convertible to 'UITableViewCellStyle'
When you call this line:
super.init(style: UITableViewCellStyle, reuseIdentifier: String?)
you need to supply an actual cell style and an actual reuse identifier. You code at the moment is written as if this line is a function definition, not a function invocation.
Change it to something like:
super.init(style: .Default, reuseIdentifier: "SettingCell")
(though preferably at least the reuse identifier should be provided by the caller, not statically)

TableViewController with custom cells in swift

I'm having an issue with custom TableViewCell in Swift. I'm trying to display a custome TableViewCell in a TableView but that doesn't work well. I got a grey square on the screen... I found some answers on the Internet that recommend to disable Auto-Layout. I did it but now, my cell is displayed but there is a mess with the height of the cells. As you can see, my cell that is supposed to have red background is displayed on the height of 3 cells while the background is on only 1 cell. The height of the cell and the Row Height are both set to 150px.
With Auto-Layout: Without Auto-Layout:
Here is the Cell code:
class CharacterDescription : UITableViewCell {
#IBOutlet var imageProfile: UIImageView!
#IBOutlet var name: UILabel!
#IBOutlet var hp: UILabel!
#IBOutlet var damages: UILabel!
#IBOutlet var range: UILabel!
#IBOutlet var mp: UILabel!
#IBOutlet var critChances: UILabel!
#IBOutlet var critModifier: UILabel!
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
}
}
And the TableViewController code:
class CharacterDescriptionsViewController : UITableViewController, UITableViewDataSource, UITableViewDelegate {
var userProfile: UserProfile!
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init() {
super.init()
}
override func viewDidLoad() {
var nibName = UINib(nibName: "CharacterDescription", bundle:nil)
self.tableView.registerNib(nibName, forCellReuseIdentifier: "CharacterDescription")
}
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return userProfile.characters!.count
}
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
var cell = self.tableView.dequeueReusableCellWithIdentifier("CharacterDescription", forIndexPath: indexPath) as CharacterDescription
//!TODO: Init of cell
return cell
}
}
You have to override TableView.heightForRowAtIndexPath to return the height of your custom cell.

Resources