Why won't my subclass of UITableViewCells appear when run? - swift

When I wireframe it, the cell is nested above the TableView. My project structure is that I have a main view controller and a subclass of a TableView that's also using a TableViewCell that I subclassed. Everything is in place, I have no idea why it's not showing.
import UIKit
class ViewController: UIViewController{
#IBOutlet weak var tv: TaskTableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
My subclass of UITableView.
import UIKit
class TaskTableView: UITableView, UITableViewDelegate, UITableViewDataSource {
var title: String = ""
var detail: String = ""
var time: NSDate = NSDate()
var data = ["asdf","asdf","sadf"]
init(frame: CGRect, title: String, detail: String, time: NSDate)
{
self.title = title
self.detail = detail
self.time = time
super.init(frame: frame, style: UITableViewStyle.Plain)
}
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return data.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
tableView.registerNib(UINib(nibName: "NewTVCell", bundle: nil), forCellReuseIdentifier: "toDoCell")
let cell = tableView.dequeueReusableCellWithIdentifier("toDoCell", forIndexPath: indexPath) as! NewTVCell
cell.title.text = data[indexPath.row]
return cell
}

Related

fatal error: init(coder:) has not been implemented error

Xcode is sending me the error "fatal error: init(coder:) has not been implemented error" despite being implemented. I don't know where the problem is.
final class newTableViewController: UITableViewController {
#IBOutlet var inputFormTableView: UITableView!
let form: Form
let note = Note(name: "")
init(form: Form) {
self.form = form
super.init(style: .grouped)
}
convenience init(note: Note) {
let form = Form(sections: [
FormSection(items: [
TextInputFormItem(text: note.name,
placeholder: "Add title",
didChange: { _ in print("hello")})
])
])
self.init(form: form)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
inputFormTableView.rowHeight = 44
inputFormTableView.register(TextInputTableViewCell.self, forCellReuseIdentifier: ReuseIdentifiers.textInput.rawValue)
let new = newTableViewController(note: note)
print(new.note.name)
}
private enum ReuseIdentifiers: String {
case textInput
}
// MARK: - Table view data source
private func model(at indexPath: IndexPath) -> FormItem {
return form.sections[indexPath.section].items[indexPath.item]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return form.sections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return form.sections[section].items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let object = model(at: indexPath)
if let textRow = object as? TextInputFormItem {
let cell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifiers.textInput.rawValue, for: indexPath) as! TextInputTableViewCell
cell.configure(for: textRow)
return cell
}
else {
fatalError("Unknown model \(object).")
}
}
}
I am trying to make UITableView act like an input form. For doing this, I am following this tutoriel : https://augmentedcode.io/2018/11/04/text-input-in-uitableview/. Everything works in the sample project but not mine.
You haven't implemented it, you are just throwing a fatalError, when running from stroy-board this init is getting executed, replace the following code:
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
With this:
required init?(coder: NSCoder) {
form = Form()
super.init(coder: coder)
}

Protocol UITableViewDataSource is not called from xib - Swift

I don't know why my protocol UITableViewDataSource is not execute when i run the APP.
Here my xib design:
My init of class from xib is: CustomSearchDestination
#IBOutlet weak var searchText: UITextField!
#IBOutlet weak var tableView: UITableView!
let xibName = "CustomSearchDestination"
var destinationListLocal: [Destinos] = []
var SearchViewControllerView: SearchViewController?
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
xibSetup(xibName)
SearchViewControllerView = SearchViewController()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
searchText.delegate = self
tableView.delegate = self
tableView.dataSource = self
}
override init(frame: CGRect) {
super.init(frame : frame)
xibSetup(xibName)
}
Inside of this class have implemented the protocol UITableViewDelegate and UITableViewDataSource
extension CustomSearchDestination: UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("El count es: \(destinationListLocal.count)")
return destinationListLocal.count
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedCell: UITableViewCell = tableView.cellForRow(at: indexPath)!
searchText.text = selectedCell.textLabel!.text
}}
extension CustomSearchDestination: UITableViewDataSource {
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
let index = indexPath.row as Int
if destinationListLocal.count == 0 {
if let str = destinationListLocal[index].desDestino {
cell.textLabel?.text = str
}
}
return cell
}}
Can someone point me my mistake?
EDIT: My hierarchy is:
I have a xib where i put other xib like this:
this is my class CustomViewHandler. So.. my class CustomSearchDestination is a class of the superClass CustomViewHandler.
At the same time is a class of CustomSearch
class CustomViewHandler : UIView {
var view: UIView!
var controllerView : UIView!
// Keyboard
var activeField : UITextField?
var isKeyboardVisible = false
var fixValue : CGFloat?
var keyboardSize : CGFloat = 280
fileprivate func loadViewFromNib(_ nibName: String) -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
// Assumes UIView is top level and only object in CustomView.xib file
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
func xibSetup(_ nibName: String) {
view = loadViewFromNib(nibName)
// use bounds not frame or it'll be offset
view.frame = bounds
// Makes the view stretch with containing view
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
}}

UITableview doesn't show the cell I made as nib File in swift

Hello I'm in trouble with making UITableview. I made cell as nib file and want to display the cell in the UITableView. But nib file doesn't show in the UItableview when I start the app. I don't know how to figure this out. the source is below
import UIKit
class DownLoadPlayViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet var tableview: UITableView!
#IBOutlet var totalNumSizeInfo:UILabel!
let cellID:String = "DownLoadPlayViewControllerCell"
var downloadedContents: [Dictionary<String,String>] = []
var showContents: Dictionary<String,String> = [:]
override func viewDidLoad() {
super.viewDidLoad()
self.tableview.delegate = self
self.tableview.dataSource = self
self.tableview.registerClass(DownLoadPlayViewControllerCell.classForCoder(), forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
// self.tableview.registerClass(DownLoadPlayViewControllerCell.self, forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
// self.tableview.registerNib(UINib(nibName: "DownLoadPlayViewControllerCell", bundle: nil), forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
downloadedContents = getDownloadInformation()!;
totalNumSizeInfo.text = "초기화 상태"
// let contentInfo : Dictionary<String,String> = self.downloadedContents[0]
// print(contentInfo["contentTitle"])
// print(contentInfo["viewDate"])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*Podlist에 있는 다운로드 파일정보를 가져온다. */
func getDownloadInformation() -> [Dictionary<String,String>]?{
var returnValue : [Dictionary<String,String>]? =
NSUserDefaults.standardUserDefaults().objectForKey("downloadedContents") as? [Dictionary<String,String>]
if((returnValue?.isEmpty) == true){
returnValue = nil
}
return returnValue
}
// func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// return 1
// }
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return downloadedContents.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// let cell = tableView.dequeueReusableCellWithIdentifier("DownLoadPlayViewControllerCell", forIndexPath: indexPath) as! DownLoadPlayViewControllerCell
let cell = tableView.dequeueReusableCellWithIdentifier("DownLoadPlayViewControllerCell") as! DownLoadPlayViewControllerCell
let contentInfo : Dictionary<String,String> = self.downloadedContents[indexPath.row]
cell.titleLabel?.text = contentInfo["contentTitle"]
cell.dateLabel?.text = contentInfo["viewDate"]
return cell;
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let contentInfo : Dictionary<String,String> = self.downloadedContents[indexPath.row]
print(contentInfo["downLoadURL"])
}
//MARK: ButtonClickArea
#IBAction func closeButtonClick(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
You need reloadData for your tableview after run the command downloadedContents = getDownloadInformation()!. Just run tableview.reloadData() like that:
downloadedContents = getDownloadInformation()!;
tableview.reloadData() //---------> add new like here
totalNumSizeInfo.text = "초기화 상태"
Here is how to use a custom created cell.
Note: I am not using StoryBoard and I have created the cell in a nib.
CustoMCell Class Code:
import UIKit
class ActivityTableViewCell: UITableViewCell {
// MARK: - Constants & variable
// your outlets if any
// MARK: - UITableViewCell methods
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
}
// MARK: - helper methods
class func cellForTableView(tableView: UITableView, atIndexPath indexPath: NSIndexPath) -> ActivityTableViewCell {
let kActivityTableViewCellIdentifier = "kActivityTableViewCellIdentifier"
tableView.registerNib(UINib(nibName: "ActivityTableViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: kActivityTableViewCellIdentifier)
let cell = tableView.dequeueReusableCellWithIdentifier(kActivityTableViewCellIdentifier, forIndexPath: indexPath) as! ActivityTableViewCell
return cell
}
}
And this is how I use it in my TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = ActivityTableViewCell.cellForTableView(tableView, atIndexPath: indexPath)
// access your cell properties here
return cell
}
I solve the problem by modifying the tablecellController like this
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.alpha = 0
UIView.animateWithDuration(0.2, delay: 0, options: .CurveEaseIn, animations: {
self.alpha = 1
}, completion: { finished in
})
}

Swift 'unable to dequeue a cell with identifier intervalCellIdentifier

I recently started programming using swift(swift newbie! :b)
got an error and have no idea how to fix it :c
this is the code of viewcontroller.swift !
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var picker1: UIPickerView!
#IBOutlet weak var keySelect: UITableView!
var Array = ["2", "3", "4"]
#IBOutlet weak var picker1label: UILabel!
#IBOutlet weak var keyselectView: UILabel!
#IBOutlet weak var keylabel: UIButton!
let intervalCellIdentifier = "intervalCellIdentifier"
var intervalNames = ["Q", "W", "E", "R", "T", "Y"]
let limit = 5
var answer1 = 0
override func viewDidLoad() {
super.viewDidLoad()
picker1.delegate = self
picker1.dataSource = self
//edited
keySelect.delegate = self
keySelect.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return Array[row]
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return Array.count
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
#IBAction func submit1(sender: AnyObject) {
if(answer1 == 0) {
picker1label.text = "2"
}
else if(answer1 == 1) {
picker1label.text = "3"
}
else {
picker1label.text = "4"
}
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
answer1 = row
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return intervalNames.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(intervalCellIdentifier,forIndexPath: indexPath) as UITableViewCell
cell.accessoryType = .None
cell.textLabel?.text = intervalNames[indexPath.row]
return cell
}
//MARK: - UITableViewDelegate
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
if let sr = tableView.indexPathsForSelectedRows {
if sr.count == limit {
let alertController = UIAlertController(title: "Oops", message:
"You are limited to \(limit) selections", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: {action in
}))
self.presentViewController(alertController, animated: true, completion: nil)
return nil
}
}
return indexPath
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("selected \(intervalNames[indexPath.row])")
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.selected {
cell.accessoryType = .Checkmark
}
}
if let sr = tableView.indexPathsForSelectedRows {
print("didDeselectRowAtIndexPath selected rows:\(sr)")
}
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
print("deselected \(intervalNames[indexPath.row])")
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
if let sr = tableView.indexPathsForSelectedRows {
print("didDeselectRowAtIndexPath selected rows:\(sr)")
}
}
}
2016-07-28 23:08:29.868 customkeyboard[60865:1611607] * Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.29.5/UITableView.m:6547
2016-07-28 23:08:29.945 customkeyboard[60865:1611607] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier intervalCellIdentifier - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
this is error explanation(?)
help me :3
1. With XIB file
You have to register the cell to table first, may be in viewDidLoad, as:
let nib = UINib(nibName: "CustomCell", bundle: NSBundle.mainBundle())
tableView.registerNib(nib, forCellReuseIdentifier: "CustomCellIdentifier")
This is applicable if we are using a custom cell with .xib file.
2. Without XIB file
And here is a solution if we are not creating separate .xib file for custom cell:
We need to create dynamic prototype for cell in table view as:
Then we need to provide class name and reuse identifier for our custom cell as:
Here, no need to register class or nib!
Here is the cellForRowAtIndexPath implementation:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Configure the cell...
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCellId", forIndexPath: indexPath) as! CustomTableViewCell
cell.setCellIndexLabel(indexPath.row)
return cell
}
This implementation will be same for both the above solutions.
3. Only Class Implementation
Without XIB, without Dynamic Prototype
Here is the custom cell without any XIB or Dynamic Prototype:
class WithoutNibCustomTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//do custom initialisation here, if any
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
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 func identifier() -> String {
return "WithoutNibCustomTableViewCellId"
}
//MARK: Public Methods
func setCellIndexLabel(index: Int) {
let customLbl = UILabel(frame: CGRectMake(0, 0, 100, 40))
customLbl.text = String(index)
contentView.addSubview(customLbl)
}
}
Then, in table view, we need to register cell class as:
tableView!.registerClass(WithoutNibCustomTableViewCell.classForCoder(), forCellReuseIdentifier: WithoutNibCustomTableViewCell.identifier())
cellForRowAtIndexPath also same as above, like:
let cell = tableView.dequeueReusableCellWithIdentifier(WithoutNibCustomTableViewCell.identifier(), forIndexPath: indexPath) as! WithoutNibCustomTableViewCell
cell.setCellIndexLabel(indexPath.row)
return cell
in cellForRow change this :
let cell = tableView.dequeueReusableCellWithIdentifier(intervalCellIdentifier,forIndexPath: indexPath) as UITableViewCell by
let cell = tableView.dequeueReusableCellWithIdentifier(intervalCellIdentifier,forIndexPath: indexPath) as your cell class name .
I published a pod that will make your life easier while working with cells:
https://cocoapods.org/pods/CellRegistration
It simplifies the API to just one-line:
let : MyCustomCell = tableView.dequeueReusableCell(forIndexPath: indexPath)

tableView reloadData + Parse

I'm trying to implement a refresh button in navigationBar, so when the button is clicked I need to reload the tableView, I have this code, but its not working, for sure the func is called because I put a println inside, Im also declare the reload on ViewDidAppear, but nothing happens :
import UIKit
class CommentsTableViewController: PFQueryTableViewController {
#IBOutlet var tabletView: UITableView!
var object : PFObject?
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "gameScore")
query.orderByDescending("createdAt")
query.whereKey("ObjectId", equalTo: "XDP1rc8Rmq")
return query
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
// Refresh the table to ensure any data changes are displayed
self.tabletView.reloadData()
println("Reloading")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell = tableView.dequeueReusableCellWithIdentifier("CommentCellIdentifier") as! CommentsCell!
if cell == nil {
cell = CommentsCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CommentCellIdentifier")
}
if let object = object?["user"] as? String {
cell?.username?.text = object
}
return cell
}
func buttonIconAction(sender:UIButton!)
{
println("Reloading")
self.tableView.reloadData()
}
}
Any suggestions?
Thanks.
Instead of calling tableView.reloadData(), it looks like PFQueryTableViewController has a method called loadObjects(). Try calling that instead.