TableView within TableviewCell not displaying cells - swift

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")!
}
}

Related

Deselect Previous isSelected CollectionView Swift

I did set initial values for my model.
class SurveyViewModel {
var surveyColors: [SurveyModel] = []
func getSurveys() {
surveyColors = [
SurveyModel(isSelected: true),
SurveyModel(isSelected: false),
SurveyModel(isSelected: false),
SurveyModel(isSelected: false)
]
}
}
struct SurveyModel {
var isSelected: Bool
}
And inside VC I am trying to edit this selection. But whatever I try I can not deselect the first cell.
func configCollectionView() {
surveyViewModel.getSurveys()
surveyColors = surveyViewModel.surveyColors
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.register(SurveyColorCollectionViewCell.self)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
surveyViewModel.getSurveys()
surveyColors = surveyViewModel.surveyColors
collectionView.allowsMultipleSelection = false
self.surveyColors[indexPath.row].isSelected = true
}
class SurveyColorCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var innerCircle: UIView!
#IBOutlet weak var midCircle: UIView!
#IBOutlet weak var outerCircle: UIView!
#IBOutlet weak var bigSquare: UIView!
override var isSelected: Bool {
didSet{
UIView.animate(withDuration: 0.3) { [self] in // for animation effect
self.outerCircle.backgroundColor = isSelected ? KSColor.ocean500Base.getColor() : KSColor.neutral150.getColor()
self.midCircle.backgroundColor = isSelected ? KSColor.bwWhite.getColor() : KSColor.bwWhite.getColor()
self.innerCircle.backgroundColor = isSelected ? KSColor.ocean500Base.getColor() : KSColor.bwWhite.getColor()
}
}
}
static let identifier = String(describing: SurveyColorCollectionViewCell.self)
override func awakeFromNib() {
super.awakeFromNib()
}
func setup(_ survey: SurveyModel) {
bigSquare.layer.borderWidth = 1
bigSquare.layer.borderColor = KSColor.neutral100.getColor().cgColor
bigSquare.layer.cornerRadius = 8
self.innerCircle.layer.cornerRadius = 6
self.midCircle.layer.cornerRadius = 17 / 2
self.outerCircle.layer.cornerRadius = 11
self.isSelected = survey.isSelected
self.setupGradient(survey)
}
}
How should I modify my code so when other than the first model is selected it will select the new one and remove the previous one?
Here is the video link of the problem.

Label Data lost when scrolling in UITableView

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])"
}
}

Autoresize static cell by overweight label

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

All Items From Array Not In UITableView

Below is the CatalogViewController, which holds a tableview. The tableview has 1 prototype cell, ShopCell. When I print the items in the loop, they print correct, but when shown in the table, items are missing.
(Removing the shuffle() method does nothing & removing removeDuplicates(), items appear more than once). I didn't include the addToFavorites(cell: ShopCell) because I'm testing it. It does nothing.
protocol ShopCellDelegate {
func addToFavorites(cell: ShopCell)
}
class ShopCell: UITableViewCell {
#IBOutlet weak var productImageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var descTV: UITextView!
#IBOutlet weak var favoriteButton: UIButton!
var delegate: ShopCellDelegate?
override func prepareForReuse() {
super.prepareForReuse()
self.productImageView.image = nil
self.titleLabel.text = ""
self.priceLabel.text = ""
self.descTV.text = ""
self.favoriteButton.isHidden = true
}
func setProduct(product: Product) {
productImageView.sd_setImage(with: URL(string: product.urlToImage!), placeholderImage: UIImage(named: "1024ELP.png"))
titleLabel.text = product.itemName!
priceLabel.text = product.priceTag!
descTV.text = product.itemDesc!
}
#IBAction func favOrUnfav(_ sender: UIButton) {
if let delegate = self.delegate {
delegate.addToFavorites(cell: self)
}
}
}
//
class CatelogViewController: UIViewController, GADInterstitialDelegate, SFSafariViewControllerDelegate, UITableViewDelegate, UITableViewDataSource, ShopCellDelegate {
#IBOutlet weak var tableView: UITableView!
static var shopType = String()
static var linkToVisit = String()
var myProducts = [Product]()
var productKeys = [String]()
var interstitial: GADInterstitial!
override func viewWillAppear(_ animated: Bool) {
visuals() // Sets Nav Bar color & changes cell size if device == ipad
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.navigationController?.navigationBar.tintColor = UIColor.black
if CatelogViewController.shopType == "Apparel" {
self.title = NSLocalizedString("Shop Apparel", comment: "")
fetchProductLinks(child1: "ProductList", child2: "Products")
}else{
self.title = NSLocalizedString("Shop Others", comment: "")
fetchProductLinks(child1: "OtherList", child2: "OtherProducts")
//shuffleItems()
}
if let index = self.tableView.indexPathForSelectedRow{
self.tableView.deselectRow(at: index, animated: true)
}
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myProducts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ShopCell
let product = myProducts[indexPath.row]
cell.delegate = self
cell.favoriteButton.isHidden = true
cell.setProduct(product: product)
return cell
}
func fetchProductLinks(child1: String, child2: String) {
let ref = Database.database().reference()
let prodRef = ref.child(child1).child(child2)
prodRef.observeSingleEvent(of: .value, with: { snapshot in
self.myProducts.removeAll()
for items in snapshot.children {
let item = items as! DataSnapshot
let product = item.value as! [String : String]
let name = product["Name"]
let link = product["Link"]
let img = product["urlToImage"]
let desc = product["Description"]
let price = product["Price"]
let newProduct = Product(urlToImage: img, itemName: name, itemLink: link, itemDesc: desc, priceTag: price)
self.myProducts.append(newProduct)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
self.myProducts = self.shuffleArray(array: self.myProducts) as! [Product]
self.myProducts = self.myProducts.removeDuplicates()
})
ref.removeAllObservers()
}
extension Array where Element:Equatable {
func removeDuplicates() -> [Element] {
var result = [Element]()
for value in self {
if result.contains(value) == false {
result.append(value)
}
}
return result
}
}
You shuffle your array and you remove duplicates, but you don't reload data after it. So reload data of table view
self.myProducts = self.shuffleArray(array: self.myProducts) as! [Product]
self.myProducts = self.myProducts.removeDuplicates()
self.tableView.reloadData()

How can I return multiple elements in a cell?

I would like to return multiple elements of a cell. How can I do it? This is the code I'm working on
//
// TableViewControllerCompiti.swift
// Secondo B
//
// Created by Edoardo on 23/12/15.
// Copyright © 2015 ERC. All rights reserved.
//
import UIKit
import Parse
class TableViewControllerCompiti: UITableViewController {
var selfTable: NSMutableArray = NSMutableArray()
#IBOutlet var MessageTable: UITableView!
#IBOutlet weak var Compiti: UILabel!
#IBOutlet weak var DescrizioneCompiti: UITextView!
#IBOutlet weak var DataCompiti: UILabel!
var messagesArray: [String] = [String]()
var descriptionArray: [String] = [String]()
var dateArray: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
func retrieveMessages() {
let query = PFQuery(className: "Compiti")
query.findObjectsInBackgroundWithBlock {
(remoteObjects: [PFObject]?, error: NSError?) -> Void in
for messageObject in remoteObjects! {
let messageText: String? = (messageObject as PFObject) ["Materia"] as? String
let descriptionText: String? = (messageObject as PFObject) ["Compiti"] as? String
let date: String? = (messageObject as PFObject) ["Data"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
if descriptionText != nil {
self.descriptionArray.append(descriptionText!)
}
if date != nil {
self.dateArray.append(date!)
}
}
self.MessageTable.reloadData()
}
}
retrieveMessages()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell?()
cell = tableView.dequeueReusableCellWithIdentifier("cell")
Compiti.text = self.messagesArray[indexPath.row]
DataCompiti.text = self.dateArray[indexPath.row]
DescrizioneCompiti.text = self.descriptionArray[indexPath.row]
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "ReUseCell")
}
return cell!
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.messagesArray.count
}
}
When I run it, the simulator just returns a bunch of empty cells. How can I do to return the elements?
Remark From your code:
you cannot implement and call the function inside of viewDidLoad(), you implement all functions/methods outside of the life cycle then call inside.
I don't think its a good idea of having three different arrays to contain your data,you should learn struct or class data structures to group your data since you are getting them from the same class.
struct myDataContainer
{
var message:String?
var descriptionText:String?
var date:String?
}
var arrayOfContainers = [myDataContainer]() //<-- this will be your new array
I saw that you had a customize cell where you wanted to have 2 Labels and UITextView.. you should create a subclass of UITableViewCell then group them inside.
class CustomizeCell :UITableViewCell
{
#IBOutlet weak var Compiti: UILabel!
#IBOutlet weak var DescrizioneCompiti: UITextView!
#IBOutlet weak var DataCompiti: UILabel!
} //<--- Subclass of UITableViewCell above
struct myDataContainer
{
var message:String?
var descriptionText:String?
var date:String?
}
class TableViewControllerCompiti: UITableViewController {
var arrayOfContainers = [myDataContainer]() //<-- this will be your new array
override func viewDidLoad()
{
super.viewDidLoad()
retrieveMessages() //<--- call function
}
func retrieveMessages()
{
var objectT = myDataContainer()
let query = PFQuery(className: "Compiti")
query.findObjectsInBackgroundWithBlock {(objects: [PFObject]?, error: NSError?) -> Void in
if let remoteObjects = objects
{
for messageObject in remoteObjects
{
let messageText = messageObject["Materia"] as? String
let description = messageObject["Compiti"] as? String
let date = messageObject["Data"] as? String
objectT.message = messageText!
objectT.descriptionText = description!
objectT.date = date!
self.arrayOfContainers.append(objectT)
}
self.tableView.reloadData()
}
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomizeCell
// as! CustomizeCell technically speaking make sure that we access our customize cell
let data = self.arrayOfContainers[indexPath.row]
cell.Compiti.text = data.message
cell.DataCompiti.text = data.descriptionText
cell.DescrizioneCompiti.text = data.date
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOfContainers.count
}
}