How replace a table view by a collection view? - ios

I want to replace a table view by a collection view, the table view is inside a tab from XLPagerTabStrip.
I already tried to replace some things but I get some errors, can someone put me on the right direction ?
import UIKit
import XLPagerTabStrip
class BooksChildViewController: UITableViewController,
IndicatorInfoProvider {
let cellIdentifier = "postCell"
var blackTheme = false
var itemInfo = IndicatorInfo(title: "Livros")
init(style: UITableViewStyle, itemInfo: IndicatorInfo) {
self.itemInfo = itemInfo
super.init(style: style)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
// MARK: - IndicatorInfoProvider
func indicatorInfo(for pagerTabStripController:
PagerTabStripViewController) -> IndicatorInfo {
return itemInfo
}
}

Your class BooksChildViewController should inherit UICollectionViewController instead of UITableViewController.
Also, you need modify your init() . UICollectionViewController can be initializer with a UICollectionViewLayout instead with a style like UITableViewController.

Related

IOS swift5 UIController call uitableview function problem. Please assist

I have a UIController class and a Tableview class. I would like to include tableview inside uicontroller. But i cannot access tableview inside functions (even static or public). how can i access tableview function from uicontroller?
Million thanks. Struggling with this problem long
import Foundation
import UIKit
class UIController: UIViewController {
private var tableView: UITableView = RegDropdownMenu(identifier: RegStepTwoIndentifier.regStepTwoTable)
init(identifier: String) {
super.init()
view.addSubview(tableView)
// Cannot call the func
tableView.testingFunc()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class TableView: UITableView {
private var identifier: String
init(identifier: String) {
self.identifier = identifier
super.init(frame: .zero, style: .plain)
configTable()
}
private func configTable() {
self.delegate = self
self.dataSource = self
self.translatesAutoresizingMaskIntoConstraints = false
self.register(CellClass.self, forCellReuseIdentifier: identifier)
self.allowsSelection = true
self.separatorStyle = .none
self.layer.masksToBounds = true
self.backgroundColor = .white
self.layer.borderColor = Styles.borderColor.cgColor
self.layer.borderWidth = Styles.borderWidth
}
func testingFunc() {
print("123")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You have created a custom UITableView subclass called TableView
This is the line of code that does this class TableView: UITableView
However, in your ViewController you are creating a generic UITableView
private var tableView: UITableView
This should be changed to
private var tableView: TableView which is the name of the custom UITableView class you created.
After this, tableView.testingFunc() should work.

Pass Data From View Controller to View in MVC - Swift

Passing data between UIViewControllers is fairly straightforward, but passing data from a controller to a view is something I can't seem to figure out.
In my specific case the user taps on an "event" cell, and transitions into a detailed view.
How do I pass the "event" from the tapped cell, to the detail view?
// Inside Starting View Controller
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = EventDetailController()
let vcView = vc.view as! EventDetailView
vcView.event = model.events[indexPath.item]
navigationController?.pushViewController(vc, animated: true)
}
// Second View
class EventDetailView: UIView {
var event: Event?
let model = EventsModel()
override init(frame: CGRect) {
super.init(frame: frame)
print("selected event: \(event)") <<<<--- Prints "nil"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// Second Controller
class EventDetailController: UIViewController {
var eventDetailView: EventDetailView!
override func loadView() {
super.loadView()
view = eventDetailView
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
You are passing data which is not the correct way to do this. You should never access the view until it's been shown or loaded correctly.
In your class EventDetailController add the property
var event: Event?
and replace this method like below
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = EventDetailController()
vc.event = model.events[indexPath.item]
navigationController?.pushViewController(vc, animated: true)
}
and
override func viewDidLoad() {
super.viewDidLoad()
eventDetailView.event = self.event
}
Hope it helps
EDIT
In load view method add the following line at the start of the method
`eventDetailView = EventDetailView(frame:CGRect(x:0,y:0,width:UIScreen.main.bounds.width,height:UIScreen.main.bounds.height))`
// First View Controller
let vc = EventDetailController()
vc.eventDetailView.event = "TEST"
navigationController?.pushViewController(vc, animated: true)
// Second View
class EventDetailView: UIView {
var event: String?
var model = EventsModel()
override init(frame: CGRect) {
super.init(frame: frame)
print("selected event: \(event)")
}
override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(event as Any?, forKey: "event")
aCoder.encode(model as Any?, forKey: "model")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
event = aDecoder.decodeObject(forKey: "event") as? String? ?? ""
model = aDecoder.decodeObject(forKey: "model") as! EventsModel? ?? EventsModel()
}
}
// Second Controller
class EventDetailController: UIViewController {
var eventDetailView = EventDetailView()
override func loadView() {
super.loadView()
view = eventDetailView
}
override func viewDidLoad() {
super.viewDidLoad()
print(eventDetailView.event)
}
}

Cannot assign value of type 'UIViewController' to type 'LeftViewController!'. Why?

I have a class LeftViewController:
protocol LeftMenuProtocol: class {
func actionOpenHome()
func actionOpenTakeSnap()
func actionOpenGallery()
func actionOpenProfiles()
func actionOpenSettings()
func actionOpenHelp()
func actionOpenContactUs()
func actionOpenBarCode()
func actionOpenAbout()
func actionCloseSideVC()
}
class LeftViewController : UIViewController {
#IBOutlet weak var tableView: UITableView!
var leftMenuDelegate : LeftMenuProtocol?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.view.layoutIfNeeded()
}
}
I am trying to add it into another class like this
var leftViewController: LeftViewController!
leftViewController = self.storyboard!.instantiateViewControllerWithIdentifier("LeftViewController")
self.addChildViewController(leftViewController)
self.view!.addSubview(leftViewController.view!)
leftViewController.didMoveToParentViewController(self)`
But getting this error. Somebody knows what is wrong?
change the variable declaration to
leftViewController = self.storyboard!.instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController
You need to explicitly cast it.

Display custom UITableViewCell from an array of cells

I have an UIViewController that creates a custom UITableViewCell and insert it into an array. Then I've a UITableViewController and I want to show cells from previous array. The problem is that in tableView(tableView:cellForRowAtIndexPath) I don't want to use dequeueReusableCellWithIdentifier because I just want to get the cells from the array and use them.
Unfortunately this doesn't work. I read dequeueReusableCellWithIdentifier permits to save in memory only the necessary cells.
I'm thinking about a method to "push" my custom cells in that queue but I can't find anything. So at the end I'm not able to show my custom cells.
Note: I can't obtain the cell using dequeueReusableCellWithIdentifier and than set each properties because one of them is a UIProgressView and it's updated within my custom cell class so I need to display that cell.
This is the code within the UIViewController which create the custom cell and set it into the array:
//here I create my custom cell (DownloadTVCell)
let cell = DownloadTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: "DownloadRootTVC_IDcell")
cell.nomeFileInDownloadLabel.text = nomeCompletoMp3
//this is a method in DownloadTVCell that starts a download task
cell.createDownloadTask()
//here i got the navigationController in order to obtain the instance of
//the UITableViewController. In this method when a user tap on the
//UITableViewController it's already instantiated
let nc = self.tabBarController!.viewControllers![1] as! UINavigationController
let drtvc = nc.topViewController as! DownloadRootTVC
//now drtvc is the instance of DOwnloadRootTVC which is my custom UITableViewController
//add the cell to the array
drtvc.listOfCellsDownlaod.append(cell)
This is my custom cell:
class DownloadTVCell: MGSwipeTableCell, NSURLSessionDownloadDelegate {
//******************************************************************
// IBOUtlet
//******************************************************************
#IBOutlet var nomeFileInDownloadLabel: UILabel!
#IBOutlet var quantitaScaricataLabel: UILabel!
#IBOutlet var progressView: UIProgressView!
private var downloadTask: NSURLSessionDownloadTask?
//******************************************************************
// METODI
//******************************************************************
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
log("ACTION", text: "Metodo chiamato")
build()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
log("ACTION", text: "Metodo chiamato")
build()
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
private func build() {
self.nomeFileInDownloadLabel = UILabel()
self.quantitaScaricataLabel = UILabel()
self.progressView = UIProgressView()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
//here there is some logic for download
...
}
And finally this is my custom UITableView:
class DownloadRootTVC: UITableViewController {
//******************************************************************
// PROPRIETA' GENERICHE
//******************************************************************
var listOfCellsDownlaod = [DownloadTVCell]()
//******************************************************************
// METODI
//******************************************************************
override func viewDidLoad() {
log(text: "self.listOfCellsDownlaod.count: \(self.listOfCellsDownlaod.count)")
self.tableView.delegate = self
self.tableView.dataSource = self
self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadTableData:", name: "reload", object: nil)
//self.tableView.registerClass(DownloadTVCell.self, forCellReuseIdentifier: "DownloadRootTVC_IDcell")
super.viewDidLoad()
}
func refresh(sender:AnyObject) {
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
func reloadTableData(notification: NSNotification) {
tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.listOfCellsDownlaod.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCellWithIdentifier("DownloadRootTVC_IDcell", forIndexPath: indexPath) as! DownloadTVCell
//I just want to return my custom cell
return self.listOfCellsDownlaod[indexPath.row]
}
}
Instead of adding UITableViewCells to your array you should probably add only the cell identifiers and then dequeue the cells in cellForRowAtIndexPath and do the set up there. If you can't retrieve the information to populate the cells in cellForRowAtIndexPath, then create a class or object to save the cell identifiers together with all the info you need to populate the cells (texts for labels, image file names for image views, etc).
Remember that table view cells are view objects and you should not include logic in view objects. Put all the logic into a separate object and then just fill the cells as needed.

Swift fatal error: unexpectedly found nil while unwrapping an Optional value (lldb) in Tableview [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have custom cell in table view. When I am running my code I am getting
below error
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
My code is below:
class viewCompanyResultController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var uiTblCompanyResultView: UITableView!
var companyName=""
var countryCode=""
var townCode=""
var element=""
var resultDict: NSDictionary=[:]
var comapniesArr:[Company] = [Company]()
override func viewDidLoad() {
super.viewDidLoad()
self.uiTblCompanyResultView.delegate=self
self.uiTblCompanyResultView.dataSource=self
self.comapniesArr.append(Company(orgName: "cbre", orgCode: "orgCode2", imageName: "3.png"))
// 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.
}
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
return self.comapniesArr.count
}
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
let cell: CompantResultCell = tableView .dequeueReusableCellWithIdentifier("cell") as CompantResultCell
let companyResult=comapniesArr[indexPath.row]
println("dgfdf \(companyResult.orgName)")
cell.setCompanyCell(uiImgConComp: companyResult.imageName,lblCompanyName: companyResult.orgName)
return cell
}
}
Custome Cell Class
import UIKit
class CompantResultCell: UITableViewCell {
#IBOutlet var uiImgConComp: UIImageView!
#IBOutlet var lblCompanyName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
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)
}
func setCompanyCell(imageName: String,lblCompanyName: String)
{
self.uiImgConComp.image=UIImage(named: imageName)
self.lblCompanyName.text=lblCompanyName;
}
}
Custom cell class looks perfect!
You need to unwrapped custom cell object in tableView:(_cellForRowAtIndexPath:) method like below:
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
var cell: CompantResultCell! = tableView .dequeueReusableCellWithIdentifier("cell") as? CompantResultCell
if (cell == nil) {
cell = CompantResultCell(style: UITableViewCellStyle.Default, reuseIdentifier:"cell")
}
let companyResult=comapniesArr[indexPath.row]
println("dgfdf \(companyResult.orgName)")
cell.setCompanyCell(uiImgConComp: companyResult.imageName,lblCompanyName: companyResult.orgName)
return cell
}
Edit:
Also unwrapped UIImage object in setCompanyCell method:
func setCompanyCell(imageName: String,lblCompanyName: String) {
var cellImage = UIImage(named: imageName as String!) as UIImage!
self.uiImgConComp.image = cellImage
self.lblCompanyName.text=lblCompanyName;
}
Calling the function behaviour is different in Swift, not like in Objective C. Call this function as below line:
cell.setCompanyCell(companyResult.imageName, lblCompanyName: companyResult.orgName)

Resources