UITAbleview Cell For Row at Indexpath Not Called - swift

For some reason, the tableview reloadData function is being called despite the fact that cellForRowAtIndexPath function is not being called. I have posted the full code below. In a nutshell, using the videos as the data source, each time the values of videos changes, the table reloads its data. I have confirmed that this part of functionality works as I have debugged it and the number of videos outputs each time that function occurs. Despite this, cellForRowAtIndexPath fails to be called even once.
import Foundation
import UIKit
import ReactiveCocoa
import enum Result.NoError
public typealias NoError = Result.NoError
public class VideosTable: UITableView, UITableViewDataSource, UITableViewDelegate {
// MARK: Public variables
public var currentVideo: Video!
// MARK: Private variables
private let videos = MutableProperty<[Video]?>(nil)
private let cellId = "cell"
// MARK Initializers
public required init(signal: Signal<[Video]?, NoError>, frame: CGRect) {
super.init(frame: frame, style: .Plain)
self.dataSource = self
self.delegate = self
self.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellId)
videos <~ signal
videos.signal.observeNext{_ in
self.reloadData()
}
}
videos <~ signal
videos.signal.observeNext{_ in
print("values changed")
self.reloadData()
}
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// MARK: DataSource
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let videoCount = videos.value?.count ?? 0
print("Video Count: \(videoCount)")
return videoCount
}
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.dequeueReusableCellWithIdentifier(cellId) ?? UITableViewCell()
cell.textLabel?.text = videos.value![indexPath.row].title
return cell
}
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
// MARK: Delegate
public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("User selected row at \(indexPath.row)")
currentVideo = videos.value![indexPath.row]
}
}

Problem has been solved. The code above is actually all correct, it was in another part of the application that was causing the error. Basically the table wasn't being correctly added to the view hierarchy and thus CellForRow was not being called while tableReload was. Likewise, the height of the table was actually zero upon initialization and remained zero. If the height of each TableCell, which is determined by the callback, heightForRowAtIndexPath exceeds that of the table height, CellForRow will never be called.

Related

API Call is not reloading on TableView (with MVVM)

I'm building an app that works with GEODb Rapid API. It should decode country names and put them in TableView Cells.
Working with MVVM pattern and getting the result of api in my modelView.
My modelView looks as below:
class HomePageViewModel {
var color = UIColor.white
var apiResult: APIResult?
init() {
getAPIResult()
}
private func getAPIResult() {
APIHandler.urlRequest { results in
print(results)
self.apiResult = results
}
}
}
I do get the data. Printing the result is shown as below on terminal.
2021-11-27 19:01:07.687230+0300 Countries[32016:2991279] [boringssl] boringssl_metrics_log_metric_block_invoke(144) Failed to log metrics
APIResult(data: [Countries.APIResultKeys(name: "Vatican City"), Countries.APIResultKeys(name: "Ethiopia"), Countries.APIResultKeys(name: "Montenegro"), Countries.APIResultKeys(name: "Namibia"), Countries.APIResultKeys(name: "Ghana")])
2021-11-27 19:03:28.937963+0300 Countries[32016:2991
I'm aware of boringss1 issue but will handle it later for now.
My main class is as below. I am initializing the class with the viewModel. So I'm getting the data from the main model.
class HomePageViewController: UIViewController {
deinit {
print("HomePageViewController Deinit")
}
//MARK: - Computed Properties
private lazy var countriesTableView: UITableView = {
let temp = UITableView()
temp.translatesAutoresizingMaskIntoConstraints = false
temp.delegate = self
temp.dataSource = self
temp.register(CountriesTableViewCell.self, forCellReuseIdentifier: CountriesTableViewCell.identifier) //Registering Cell
temp.separatorStyle = .none // Removing lines out of tableView
return temp
}()
private var viewModel: HomePageViewModel?
//MARK: - LifeCycle
init(with viewModel: HomePageViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
setupViews()
setupConstraintsForViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
I'm trying to change the text label of the cell inside my main class and via the UITableView stubs as below. But the labels are not changing. I tried to reload the table view in cellForRowAt function but when I do that my table view just disappears.
So what am I doing wrong?
Excuse me if I'm not explaining properly.
extension HomePageViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: CountriesTableViewCell.identifier, for: indexPath) as? CountriesTableViewCell else { return UITableViewCell() }
cell.countryLabel.text = viewModel?.apiResult?.data[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}

Issues with setting up UITableView sections and rows using fetch request results array and a structure

I have some problems that require a solution which is beyond my knowledge unfortunately at the moment.
I perform a fetch request that returns an array of Floors entity object which has 2 attributes (floor number and number of rooms). I want to make a table with the number of sections corresponding the num of floors and the num. of rows in each section corresponding to the number of rooms per floor. I use a struct and 2 for in loops to separate the attributes for the table. The result is baffling me: if i declare one floor it works and a picker in the next vc displays floor "0". If I assign 2 rooms to it I get a giant print response and a table with 10s of rows. Please have a look at the code below and the pictures provided and if someone could help I would be thankful.
class RoomAndAlarmTypeTableVC: UITableViewController, NSFetchedResultsControllerDelegate {
//MARK: - Properties
private var managedObjectContext: NSManagedObjectContext!
private var storedFloors = [Floors]()
private var resultsArray = [Results]()
//MARK: - Actions
override func viewDidLoad() {
super.viewDidLoad()
managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
loadFloorData()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func loadFloorData() {
let floorRequest: NSFetchRequest<Floors> = Floors.fetchRequest()
do {
storedFloors = try managedObjectContext.fetch(floorRequest)
// tableView.reloadData()
print("\(storedFloors)")
} catch {
print("could not load data from core \(error.localizedDescription)")
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return resultsArray.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultsArray[section].sectionObjects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "house cell", for: indexPath) as! ViewRooomNumberCell
cell.floorNumberTxt.text = String(storedFloors[indexPath.section].floorNumber)
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return resultsArray[section].sectionName
}
}
[![enter image description here][1]][1]
[![enter image description here][2]][2]
storedFloors is an array of managedObjects, which already has all the information that you need. The number of sections is storedFloors.count and the number of rows is storedFloors[sectionIndex].numberOfRooms. To build a cell the floor is storedFloors[indexPath.section].floorNumber and the room number is simply indexPath.row.
The other objects you created are wrong and confusing and should be removed.

Inside Subclassed UITableViewCell Override Func LayoutSubviews Being Called Double

I have a subclass of UITableViewCell that has is having override func layoutSubviews() called twice for each cell. This is creating multiple copies of elements within the cell.
The UITableView returns the proper count of cells and displays the correct number of cells but the layout function resets a handful of properties to nil. Therefore rendering a lot of the data incorrectly.
TableView Inside UIViewController:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userMatches.count // return 2 correctly
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.view.bounds.height * 0.20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: MatchTableViewCell = self.matchTableView.dequeueReusableCellWithIdentifier("matchCell", forIndexPath: indexPath) as! MatchTableViewCell
cell.matchDetails = userMatches[indexPath.row]
cell.userInteractionEnabled = true
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell // creates 2 correctly
}
UITableView Subclass:
override func layoutSubviews() {
super.layoutSubviews()
// runs 4 times
let userHelperIconArray = [userZoom, userTakeTwo, userStopper]
let opponentHelperIconArray = [opponentZoom, opponentTakeTwo, opponentStopper]
layoutHelperInventoryIcons(self, opponentHelperIconArray: opponentHelperIconArray, userHelperIconArray: userHelperIconArray, opponentNameLabel: opponentName)
layoutMiniGameboard(self)
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.blackColor().CGColor
print("one")
turnIdentifier(self, matchDetails: matchDetails, opponentNameLabel: opponentName)
}
You should 't be doing this in layoutSubviews anyway. Instead, move the configuration to a separate method, and have your table view data source call that configuration method after dequeing the cell.

UITableViewDataSource not being invoked in Swift, Xcode 7 beta 2

This is a bizarre one, & I'm quite happy to be told that I've missed something obvious, but I can't see it.
Firstly, the UITableViewDataSource methods are not even showing up in autocomplete, then they're not called at runtime. Weirdly, the UITableViewDelegate methods are working on both counts.
Here's the (cut-down) code -
class PopupTable : NSObject, UITableViewDataSource, UITableViewDelegate
{
private var tableView : UITableView
init(rect: CGRect)
{
tableView = UITableView(frame: rect, style: UITableViewStyle.Plain)
super.init()
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "PopupCell")
tableView.dataSource = self
tableView.delegate = self
}
func show()
{
if let mainWindow = UIApplication.sharedApplication().delegate?.window!
{
mainWindow.addSubview(tableView)
}
}
// MARK: TableView Delegate & DataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return myData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("PopupCell")!
cell.detailTextLabel?.text = "some text"
return cell
}
}
I have no problems getting this to work in a UIViewController, but that's not what I want here.

how to hide selection on UITableview?

i want to disable click on particular Cell.it means, i want not to show highlight color(selection indication) when we touch on particular cell? any help please?
Either use cell.selectionStyle = UITableViewCellSelectionStyleNone; or return false or return null in the delegate method tableView:willSelectRowAtIndexPath.
Swift:
If you're using a custom cell:
class YourCustomCell: UITableViewCell {
override func awakeFromNib() {
setup()
}
init() {
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
fileprivate func setup() {
self.selectionStyle = .none
}
}
If you're not using a custom cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifierID")
cell.selectionStyle = .none
return cell
}
Bonus: If you want to hide the cell selection and also don't want to call func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {...} then only set cell.isUserInteractionEnabled = false. However, this is not a good practice.