I have some static cells and this don't want to change their size by overweight content in label. I have all constraints(top, bottom, leading,tralling) in each cells, also I have this code:
import UIKit
class FilmTableViewController: UITableViewController {
#IBOutlet weak var posterView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var yearLabel: UILabel!
#IBOutlet weak var directorLabel: UILabel!
#IBOutlet weak var actorsLabel: UILabel!
#IBOutlet weak var countryLabel: UILabel!
#IBOutlet weak var plotLabel: UILabel!
#IBOutlet weak var RatingLabel: UILabel!
private let networkingService = NetworkingService()
var filmImbdbID = ""
override func viewDidLoad() {
super.viewDidLoad()
loadFilm(filmImbdbID)
}
override func viewDidAppear(_ animated: Bool) {
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 80
}
private func loadFilm(_ film: String) {
networkingService.fetchFilmRecording(matching: film) { [weak self] response in
guard let `self` = self else {
return
}
self.directorLabel.text = response.recordings?.director
self.titleLabel.text = response.recordings?.title
self.yearLabel.text = response.recordings?.year
self.actorsLabel.text = response.recordings?.actors
self.countryLabel.text = response.recordings?.country
self.plotLabel.text = response.recordings?.plot
self.RatingLabel.text = response.recordings?.rating
if let imageUrl = URL(string: response.recordings!.poster) {
guard let data = try? Data(contentsOf: imageUrl) else { return }
let image = UIImage(data: data)
self.posterView.image = image
}
}
}
}
Also numberOfLines is 0.
When I see this view, it don't work, however if I slide down it looks like this:
Please, some idea to fix it? :(
You need to update your code, cause is not clear what's happening.
Anyway you should use or:
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 80
or delegate methods
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableView.automaticDimension
}
not both
Related
I made a table view with a label that increments and decrements on pressing a button and another button to show the text in another label outside the UItableView. Everything works fine but when I scroll the Tableview the value resets to zero!
Before Scrolling
After Scrolling
My ViewController class
class ViewController: UIViewController{
var numArray = [Value]()
var initialValue = 0
#IBOutlet weak var tableView : UITableView!
#IBOutlet weak var lblOutput : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0 ... 100{
numArray.append(Value(number: initialValue))
}
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? ControllerTableViewCell else{fatalError("Error in creating cells")}
cell.delegate = self
cell.data = numArray[indexPath.row]
cell.lblInput.text = "\(cell.data.number)"
return cell
}
}
extension ViewController : MyTableViewCellDelegate{
func DidPrint(Data: String) {
self.lblOutput.text = "\(Data)"
}
}
My TableViewCell class
protocol MyTableViewCellDelegate : AnyObject {
func DidPrint(Data: String)
}
class ControllerTableViewCell: UITableViewCell {
weak var delegate : MyTableViewCellDelegate?
var data : Value!
private var counterValue = 0
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func DidPressPrint(){
self.data.number = counterValue
delegate?.DidPrint(Data: "\(data.number)")
print(data.number)
}
#IBAction func DidPressPlus(){
counterValue += 1
data.number = counterValue
self.lblInput.text = "\(data.number)"
}
#IBAction func DidPressMinus(){
if(counterValue > 0){
counterValue -= 1
data.number = counterValue
}
else{
counterValue = 0
data.number = 0
}
self.lblInput.text = "\(data.number)"
}
}
My Data Model
import Foundation
struct Value{
var number : Int
}
As #El Tomato suggested, you are not updating your data source, that's why your changes gets "forgotten" on scroll.
Try to move your didPressPlus, didPressMinus and didPressPrint in your ViewController class and redefine your table view delegate like below.
By passing the tag attributes to the buttons, you can then retrieve the index of the item pressed in the functions and edit the correct data source item.
Also remove the unnecessary MyTableViewCellDelegate.
class ViewController: UIViewController{
var numArray = [Value]()
var initialValue = 0
#IBOutlet weak var tableView : UITableView!
#IBOutlet weak var lblOutput : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0 ... 100 {
numArray.append(Value(number: initialValue))
}
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController : UITableViewDelegate, UITableViewDataSource
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? ControllerTableViewCell else {fatalError("Error in creating cells")}
let indexItem = indexPath.row
let valueItem = numArray[indexItem]
cell.lblInput.text = valueItem.number
cell.btnMinus.tag = indexItem
cell.btnMinus.addTarget(self, action: #selector(didPressMinus(_:)), for: .touchUpInside)
cell.btnPlus.tag = indexItem
cell.btnPlus.addTarget(self, action: #selector(didPressPlus(_:)), for: .touchUpInside)
cell.btnPrint.tag = indexItem
cell.btnPrint.addTarget(self, action: #selector(didPressPrint(_:)), for: .touchUpInside)
return cell
}
#objc private func didPressPlus(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
let numArrayItem = numArray[dataIndex]
if (numArrayItem.number >= 0) {
numArray[dataIndex].number -= 1
}
tableView.reloadData()
}
#objc private func didPressMinus(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
numArray[dataIndex].number += 1
tableView.reloadData()
}
#objc private func didPressPrint(_ sender: UIButton) {
let dataIndex = sender.tag
if numArray.count < dataIndex { return }
self.lblOutput.text = "\(numArray[dataIndex].number)"
}
}
In order to move the three methods in the ViewController you'll need to remove the two correspondent IBAction from the UITableViewCell class.
Also, remove the linkage with the ControllerTableViewCell actions.
Here is the resulting ControllerTableViewCell:
class ControllerTableViewCell: UITableViewCell {
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
}
Your TableView's numberOfRowsInSection is using numArray as a source (numArray.count) and so is your cellForRowAt function, but your cell functions are updating your 'data' variable. Your 'data' variable is locally defined to your tableView and gets reset every time it is activated (including when you scroll).
You need to update the numArray or some other global resource to make it work. This involves using indexpath of the cell value inside the cell functions, meaning you need a way to refer to indexPath inside the cell. This article explains how to use tags or delegates, https://fluffy.es/handling-button-tap-inside-uitableviewcell-without-using-tag/.
Here's a solution using the existing delegate.
import UIKit
import Foundation
var initialValue = 0
var numArray = Array(repeating: initialValue, count: 100)
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var lblOutput: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.lblOutput.text = "\(initialValue)"
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
// Do any additional setup after loading the view.
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as? ControllerTableViewCell else{fatalError("Error in creating cells")}
cell.indexPath = indexPath
cell.delegate = self
cell.lblInput.text = String(numArray[indexPath.row])
return cell
}
}
extension ViewController : MyTableViewCellDelegate{
func DidPrint(Data: String) {
self.lblOutput.text = "\(Data)"
}
}
protocol MyTableViewCellDelegate : AnyObject {
func DidPrint(Data: String)
}
class ControllerTableViewCell: UITableViewCell {
weak var delegate : MyTableViewCellDelegate?
var indexPath : IndexPath?
private var counterValue = 0
#IBOutlet var lblInput : UILabel!
#IBOutlet var btnPrint : UIButton!
#IBOutlet var btnPlus : UIButton!
#IBOutlet var btnMinus : UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBAction func DidPressPrint(){
delegate?.DidPrint(Data: "\(numArray[indexPath!.row])")
}
#IBAction func DidPressPlus(){
numArray[indexPath!.row] = numArray[indexPath!.row] + 1
self.lblInput.text = "\(numArray[indexPath!.row])"
}
#IBAction func DidPressMinus(){
if(numArray[indexPath!.row] > 0){
numArray[indexPath!.row] = numArray[indexPath!.row] - 1
}
else{
numArray[indexPath!.row] = 0
}
self.lblInput.text = "\(numArray[indexPath!.row])"
}
}
I have a few UITableViewCell's that have a few different layouts depending on if they're teammates, enemies, etc. But I have to treat each type differently etc. So I tried to cut down on replicated code by using a protocol,
I've created a protocol for a UITableViewCell like so:
protocol ViewCellProtocol {
var teamRank: UILabel! { get set }
var ranking: UILabel! { get set }
var rankDelta: UILabel! { get set }
var upDownIndicator: UILabel! { get set }
var textLabel : UILabel? { get }
}
This is my class:
import UIKit
class TeamStatsTableViewCell: UITableViewCell {
#IBOutlet weak var teamRank: UILabel!
#IBOutlet weak var ranking: UILabel!
#IBOutlet weak var rankDelta: UILabel!
#IBOutlet weak var upDownIndicator: 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
}
}
Then when I try to use it
func playerViewCell(_ tableView: UITableView, indexPath: IndexPath) -> ViewCellProtocol {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamNameCell")! as! TeamStatsTableViewCell
let rank = sections[indexPath.section].data[indexPath.row]["rank"] as? Int
let (rating, ratingDelta) = selectRating(section: indexPath.section, row: indexPath.row)
let indicator = decideRatingIndicator(ratingDelta: ratingDelta, cell: cell)
cell.upDownIndicator?.text = "\(indicator)"
cell.teamRank?.text = "#\(rank!)"
cell.ranking?.text = String(rating)
cell.rankDelta.text = String(format: "%.0f", ratingDelta)
cell.textLabel?.text = sections[indexPath.section].data[indexPath.row]["username"] as? String
return cell as! ViewCellProtocol
}
I get an error:
Could not cast value of type '.TeamStatsTableViewCell' (0x1008d35d8) to '.ViewCellProtocol' (0x10ea37db8).
2018-04-24 22:00:27.137516-0600[434:72294] Could not cast value of type '.TeamStatsTableViewCell' (0x1008d35d8) to '.ViewCellProtocol' (0x10ea37db8).
I wish it would tell me what part it doesn't conform to. Any suggestions? Fairly new to swift kind of looking at protocols like interface{} in Go. Thanks.
Your custom cell class might be implementing all the stuff that's in the protocol, and that'd be enough in objC perhaps, but here you must declare that you implement that protocol explicitly
class TeamStatsTableViewCell: UITableViewCell, ViewCellProtocol {
#IBOutlet weak var teamRank: UILabel!
#IBOutlet weak var ranking: UILabel!
#IBOutlet weak var rankDelta: UILabel!
#IBOutlet weak var upDownIndicator: 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
}
}
You need to declare that TeamStatsTableViewCell conforms to ViewCellProtocol, for example by adding this extension:
extension TeamStatsTableViewCell: ViewCellProtocol { }
After going through about a thousand SO questions, I've given up and am reaching out for help. I have a very straightforward table using custom cells. When a button is pushed, a new item is added to the array, and the table should update to show the new item. That's not happening. The data is all moving correctly but the only way to get the table to update is to quit and relaunch the app. Code below with unnecessary sections about defining variables, etc. removed. Thanks!
UPDATE: I have deleted, recreated, and relinked the table and prototype cell with no change.
class DispatchTableViewCell: UITableViewCell {
#IBOutlet weak var routeLabel: UILabel!
#IBOutlet weak var aircraftLabel: UILabel!
#IBOutlet weak var altitudeLabel: UILabel!
#IBOutlet weak var speedLabel: UILabel!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var departureTimeLabel: UILabel!
#IBOutlet weak var arrivalTimeLabel: UILabel!
#IBOutlet weak var remainingTimeLabel: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
}
class DispatchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var flightsTableView: UITableView!
#IBAction func dispatchButton(_ sender: Any) {
flightsTableView.beginUpdates()
// Do all the things to update the array
// Works fine, array is correct
flightsTableView.endUpdates()
}
let realm = try! Realm()
var flightsArray: [Flight] = []
var originsArray: [String] = []
var destinationsArray: [String] = []
var aircraftNamesArray: [String] = []
var departureTimesArray: [Date] = []
var arrivalTimesArray: [Date] = []
var speedsArray: [Double] = []
var altitudesArray: [Double] = []
override func viewDidLoad() {
flightsTableView!.dataSource = self
flightsTableView!.delegate = self
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
flightsTableView.beginUpdates()
for flight in realm.objects(Flight.self) {
flightsArray.append(flight)
}
for flight in flightsArray {
originsArray.append(flight.originCode)
destinationsArray.append(flight.destinationCode)
aircraftNamesArray.append(flight.aircraftNameShort)
departureTimesArray.append(flight.departureTime)
arrivalTimesArray.append(flight.arrivalTime)
speedsArray.append(flight.cruiseSpeed)
altitudesArray.append(flight.cruiseAltitude)
}
flightsTableView.endUpdates()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return flightsArray.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 90
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "flight", for: indexPath) as! DispatchTableViewCell
let origin = originsArray[indexPath.row]
let destination = destinationsArray[indexPath.row]
cell.routeLabel?.text = "\(origin) -> \(destination)"
print(cell.routeLabel)
cell.aircraftLabel?.text = aircraftNamesArray[indexPath.row]
cell.altitudeLabel?.text = "Altitude: \(Int(altitudesArray[indexPath.row]))"
cell.speedLabel?.text = "Speed: \(Int(speedsArray[indexPath.row]))"
cell.statusLabel?.text = "Test"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "h:mm a"
dateFormatter.timeZone = TimeZone.current
//tempFlight.departureTime = dateFormatter.string(from: tempFlight.departureTime)
//tempFlight.arrivalTime = dateFormatter.string(from: tempFlight.arrivalTime)
cell.departureTimeLabel?.text = dateFormatter.string(from: departureTimesArray[indexPath.row])
cell.arrivalTimeLabel?.text = dateFormatter.string(from: arrivalTimesArray[indexPath.row])
return cell
}
}
.beginUpdates()/.endUpdates() does not actually cause table view to reload the content it displays.
You are updating the data source and, you should let table view know about the changes by calling .reloadData() so it will ask the data source for the changes you've made and reorganize its own content:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
for flight in realm.objects(Flight.self) {
flightsArray.append(flight)
}
for flight in flightsArray {
originsArray.append(flight.originCode)
destinationsArray.append(flight.destinationCode)
aircraftNamesArray.append(flight.aircraftNameShort)
departureTimesArray.append(flight.departureTime)
arrivalTimesArray.append(flight.arrivalTime)
speedsArray.append(flight.cruiseSpeed)
altitudesArray.append(flight.cruiseAltitude)
}
flightsTableView.reloadData()
}
I was calling .reloadData() in the button func but I was not retrieving fresh data from Realm.
I have a UITablaView inside UITableviewCell. Here is my code:
UITableViewCell:
class ProductViewCell: UITableViewCell {
#IBOutlet weak var totalOrderButton: UIButton!
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productNameLabel: UILabel!
#IBOutlet weak var productSubNameLabel: UILabel!
#IBOutlet weak var productBioLabel: UILabel!
#IBOutlet weak var mlButton: UIButton!
#IBOutlet weak var productQuantity: UILabel!
#IBOutlet weak var plusButton: UIButton!
#IBOutlet weak var minusButton: UIButton!
#IBOutlet weak var greenHeartButton: UIButton!
#IBOutlet weak var liquorsTableView: UITableView!
var fourLiquorStores: [LiquorStore] = []
var currentUser: User!
var currentProduct: Product! {
didSet {
updateUI()
}
}
func updateUI() {
downloadProductImage()
productNameLabel.text = currentProduct.name
productSubNameLabel.text = currentProduct.subName
productBioLabel.text = currentProduct.description
productQuantity.text = "\(currentProduct.quantity)"
updateGreenHeart()
}
var cache = SAMCache.shared()
weak var delegate: ProductViewCellDelegate!
override func awakeFromNib() {
super.awakeFromNib()
liquorsTableView.estimatedRowHeight = 65
liquorsTableView.rowHeight = 65
liquorsTableView.delegate = self
liquorsTableView.dataSource = self
fetchLiquorStores()
}
func fetchLiquorStores() {
LiquorStore.observeNewLiquorStore { (liquorStore) in
LiquorStore.observeNewLiquorStore { (liquorStore) in
if !self.fourLiquorStores.contains(liquorStore) {
self.fourLiquorStores.append(liquorStore)
self.delegate.updateTableView()
print(self.fourLiquorStores)
}
}
}
}
func downloadProductImage() {
let productuid = currentProduct.uid
let profileImageKey = "\(productuid)"
if let image = cache?.object(forKey: profileImageKey) as? UIImage {
productImage.image = image
} else {
currentProduct.downloadPopularProductImage { [weak self] (image, error) in
if let error = error {
print(error.localizedDescription)
} else {
self?.productImage.image = image
self?.cache?.setObject(image, forKey: profileImageKey)
}
}
}
}
// Ad o delete Quantities
#IBAction func plusDidTap() {
if currentProduct.quantity >= 1 && currentProduct.quantity <= 60 {
currentProduct.quantity += 1
delegate.updateTableView()
}
}
#IBAction func minusDidTap() {
if currentProduct.quantity > 1 {
currentProduct.quantity -= 1
delegate.updateTableView()
}
}
func updateGreenHeart() {
if let currentUser = currentUser {
if currentUser.favoriteProducts.contains(currentProduct) {
greenHeartButton.setImage(#imageLiteral(resourceName: "GreenHeartFilled"), for: [])
} else {
greenHeartButton.setImage(#imageLiteral(resourceName: "GreenHeart"), for: [])
}
}
}
// Ad or delete Favorite Products
#IBAction func greenHeartDidTap() {
if currentUser.favoriteProducts.contains(currentProduct) {
self.greenHeartButton.setImage(#imageLiteral(resourceName: "GreenHeart"), for: [])
self.currentUser.deleteFavoriteProduct(product: currentProduct)
} else {
self.greenHeartButton.setImage(#imageLiteral(resourceName: "GreenHeartFilled"), for: [])
self.currentUser.addFavoriteProduct(product: currentProduct)
}
}
}
extension ProductViewCell: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return fourLiquorStores.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = liquorsTableView.dequeueReusableCell(withIdentifier: "LiquorStoreViewCell", for: indexPath) as! LiquorStoresViewCell
cell.currentProduct = self.currentProduct
cell.liquorStore = self.fourLiquorStores[indexPath.section]
return cell
}
}
UITablViewCell -2 :
class LiquorStoresViewCell: UITableViewCell {
#IBOutlet weak var liquorStoreNameLabel: UILabel!
#IBOutlet weak var liquorStorePriceLabel: UILabel!
#IBOutlet weak var liquorStoreTimeLabel: UILabel!
#IBOutlet weak var starStackView: UIStackView!
#IBOutlet weak var imageViewBoard: UIImageView!
var currentProduct: Product!
var currentPriceIndex: Int = 0
var liquorStore: LiquorStore! {
didSet {
updateUI()
}
}
func updateUI() {
changeLiquorStoreProductsUid()
liquorStoreNameLabel.text = liquorStore.userName
let index = liquorStore.products.index(of: currentProduct)
if let index = index {
let productPrice = liquorStore.products[index].price[currentPriceIndex]
format(price: productPrice)
}
}
// Format Product Price to Currency
func format(price: Double) {
let formatter = NumberFormatter()
formatter.locale = Locale.current // Change this to another locale if you want to force a specific locale, otherwise this is redundant as the current locale is the default already
formatter.numberStyle = .currency
if let formattedTipAmount = formatter.string(from: price as NSNumber) {
liquorStorePriceLabel.text = "Tip Amount: \(formattedTipAmount)"
}
}
// Func to organize LiquorStores
func changeLiquorStoreProductsUid () {
for product in liquorStore.products {
if self.currentProduct.name == product.name && self.currentProduct.description == product.description && self.currentProduct.subName == product.subName {
let index = liquorStore.products.index(of: product)
if let index = index {
liquorStore.products[index].uid = currentProduct.uid
}
}
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
liquorStorePriceLabel.textColor = UIColor.white
liquorStoreNameLabel.textColor = UIColor.white
liquorStoreTimeLabel.textColor = UIColor.white
imageViewBoard.backgroundColor = #colorLiteral(red: 0.5239839702, green: 0.5239839702, blue: 0.5239839702, alpha: 1)
for view in starStackView.subviews {
let image = view as! UIImageView
image.image = #imageLiteral(resourceName: "WhiteStar")
}
}
}
The UITableView inside the UITableviewCell doesn't show the data :/
What's the problem?
This is what I'm building:
StoryBoard
An this appears in the simulator, as you can see, the second tableview is empty:
Simulator
PD: I'm downloading successfully the liquorStores from firebase.
While it's possible to do what you are trying to do, it would be much simpler to rethink your architecture entirely. If your view controller displays only a single product, plus a list of liquor stores, then the product view shouldn't really be in a cell at all--just make it an ordinary view, and make that view your table's header. The cells will then be the liquor stores, and you no longer have to deal with nesting a table within a cell. Alternately, you can keep the product view in a cell, but just add prototypes for the liquor stores as a second kind of cell in the same table.
EDIT: Now that you've posted your storyboard screenshot, the easiest thing for you to do is to move your liquor store prototype cell up to the top-level table, remove the subtable from the top-level cell, and in your data source, have
func tableView(_ tableView: UITableView, cellForRowAtIndexPath path: NSIndexPath) -> UITableViewCell {
if path.row == 0 {
return tableView.dequeueCellWithIdentifier("productDetailsCell")!
} else {
return tableView.dequeueCellWithIdentifier("liquorStoreCell")!
}
}
i have this problem, no matter what variable "var" i put in the custom uitabelviewcell, it returns nil
while the IBOulets works just fine
tableviewcell.swift
import Foundation
import UIKit
class tableViewCell: UITableViewCell {
#IBOutlet weak var tableViewLabelDate: UILabel!
#IBOutlet weak var tableViewLabelDisplayName: UILabel!
#IBOutlet weak var tableViewLabelSubject: UILabel!
#IBOutlet weak var tableViewTextViewInfo: UITextView!
var messageRenderingOperation: MCOIMAPMessageRenderingOperation!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
tableview.swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell2: tableViewCell = tableView.dequeueReusableCellWithIdentifier(reuseTableViewCellIdentifier, forIndexPath: indexPath) as tableViewCell
cell2.tag = 0
let message: MCOIMAPMessage = mailbox?.messages[indexPath.row] as MCOIMAPMessage!
let uidKey = message.uid
cell2.tableViewLabelDisplayName?.text = mailbox?.messages[indexPath.row].header.from.displayName
cell2.tableViewLabelSubject?.text = mailbox?.messages[indexPath.row].header.subject
println("Got the subject line: \(mailbox?.messages[indexPath.row].header.subject)")
cell2.messageRenderingOperation = self.imapSession.plainTextBodyRenderingOperationWithMessage(message, folder: "INBOX", stripWhitespace: false)
cell2.messageRenderingOperation?.start({ (plaintext: String!, error: NSError!) -> Void in // Crash at this line
if error != nil{
println("ERROR at messageRenderingOperation\(error)")
}else {
cell2.tableViewTextViewInfo.text = plaintext
cell2.messageRenderingOperation = nil
}
})
return cell2
}
it crashes at this line
cell2.messageRenderingOperation?.start({ (plaintext: String!, error: NSError!) -> Void in // Crash at this line
UPDATE
I've tried this aswell
class tableviewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
var messageRenderingOperation: MCOIMAPMessageRenderingOperation?
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
self.messageRenderingOperation = imapSession.plainTextBodyRenderingOperationWithMessage(message, folder: "INBOX")
self.messageRenderingOperation.start({ (plaintext: String!, error: NSError!) -> Void in
if error != nil{
println("ERROR at messageRenderingOperation\(error)")
}else {
cell2.tableViewTextViewInfo.text = plaintext
cell2.messageRenderingOperation = nil
}
})
}
}
UPDATE 2
now if i use
var messageRenderingOperation = MCOIMAPMessageRenderingOperation()
then it's not nil, but still crashes. i think it's a problem with the "plugin" ?
Since your var is initialized later on you should declare it as optional var messageRenderingOperation: MCOIMAPMessageRenderingOperation? and not using force to unwrapping it as you currently declared. Also if you are using storyboard you can initialize it inside awake from nib method
class tableViewCell: UITableViewCell {
#IBOutlet weak var tableViewLabelDate: UILabel!
#IBOutlet weak var tableViewLabelDisplayName: UILabel!
#IBOutlet weak var tableViewLabelSubject: UILabel!
#IBOutlet weak var tableViewTextViewInfo: UITextView!
var messageRenderingOperation: MCOIMAPMessageRenderingOperation?
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
self.MCOIMAPMessageRenderingOperation = //some initialization
}
}