Good afternoon,
I'm trying to show a UIView when (in my case) there isn't any result to show in a tableView filled with products. When I detect 0 products, I show a UIView which contains a Label, a TextField and a Button, but I can't interact with my TextField and neither with the Button.
It's my first time using this technique to show a UIView when something went wrong with the tableView so I would like to know what's wrong in my code and what I'm missing because it's really weird.
Here is my code (when I print "Product not found" is where I show the UIView):
import UIKit
import Social
class ProductoCamViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var productoImageView:UIImageView!
#IBOutlet var tableView:UITableView!
#IBOutlet weak var noEncontrado:UIView!
var productoImage:String!
var ean:String!
var producto:Producto!
var productos = [Producto]()
#IBOutlet weak var toolBar: UIToolbar!
#IBOutlet weak var cargando: UIActivityIndicatorView!
override func viewDidLoad() {
toolBar.hidden = true
noEncontrado.hidden = true
cargando.hidden = false
super.viewDidLoad()
// Set table view background color
self.tableView.backgroundColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.2)
// Remove extra separator
self.tableView.tableFooterView = UIView(frame: CGRectZero)
// Change separator color
self.tableView.separatorColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.8)
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0
requestPost()
cargando.hidden = true
tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
tableView.reloadData()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.hidesBarsOnSwipe = false
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func requestPost () {
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.mywebsite.com/product.php")!)
request.HTTPMethod = "POST"
let postString = "ean="+ean
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
// JSON RESULTADO ENTERO
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
if (responseString == "Product not found")
{
self.noEncontrado.hidden = false
self.tableView.reloadData()
return
}
else
{
self.productos = self.parseJsonData(data!)
self.toolBar.hidden = false
// Reload table view
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}
task.resume()
}
func parseJsonData(data: NSData) -> [Producto] {
var productos = [Producto]()
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
noEncontrado.hidden = true
// Parse JSON data
let jsonProductos = jsonResult?["lista_productos"] as! [AnyObject]
for jsonProducto in jsonProductos {
let producto = Producto()
producto.imagen = jsonProducto["imagen"] as! String
producto.nombre = jsonProducto["nombre"] as! String
producto.descripcion = jsonProducto["descripcion"] as! String
producto.modo_de_empleo = jsonProducto["modo_de_empleo"] as! String
producto.marca = jsonProducto["marca"] as! String
producto.linea = jsonProducto["linea"] as! String
producto.distribuidor = jsonProducto["distribuidor"] as! String
producto.tamano = jsonProducto["tamano"] as! String
producto.precio = jsonProducto["precio"] as! String
producto.codigo_nacional = jsonProducto["codigo_nacional"] as! String
productos.append(producto)
}
}
catch let parseError {
print(parseError)
}
return productos
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return productos.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
title = productos[indexPath.row].nombre
let cell = tableView.dequeueReusableCellWithIdentifier("CellDetail", forIndexPath: indexPath) as! ProductoTableViewCell
cell.selectionStyle = .None
if let url = NSURL(string: productos[indexPath.row].imagen) {
if let data = NSData(contentsOfURL: url) {
self.productoImageView.image = UIImage(data: data)
}
}
cell.nombre.text = productos[indexPath.row].nombre
cell.descripcion.text = productos[indexPath.row].descripcion
cell.modo_de_empleo.text = productos[indexPath.row].modo_de_empleo
cell.marca.text = productos[indexPath.row].marca
cell.linea.text = productos[indexPath.row].linea
cell.distribuidor.text = productos[indexPath.row].distribuidor
cell.tamano.text = productos[indexPath.row].tamano
cell.precio.text = productos[indexPath.row].precio
cell.codigo_nacional.text = productos[indexPath.row].codigo_nacional
cell.layoutIfNeeded()
return cell
}
}
Thanks in advance.
At first, please try to provide english code :) but anyways. I think the view what should appear is nonEncontrado.
There could be some issues but i need to see the storyboard.
The view has userInteraction not enabled. Its a property and can also be activated in the storyboard
The view is overlayed by something else. Maybe the empty tableView.
As an suggestion you could provide this fields in the tableView and just load another DataSource. Than you dont need to fight with extra views. If you provide screens from the Storyboard i could help a bit more.
Good Luck :)
Related
I am admitting defeat with these custom headers in Swift. I have tried for days to prevent the labels and images inside of the section headers from duplicating. Basically on scroll the labels/images inside the headers duplicate and lay on top of each other.
Would someone please for the love of god explain to me why this is happening and how to fix it.
The circular image keeps creating images and laying them on top of the previous, the same with the name and date labels!!
Here is my ViewController:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var navigationBar: UINavigationItem!
#IBOutlet weak var tableView: UITableView!
var list = []
var audioPlayer:AVAudioPlayer!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getListBro() -> NSArray {
return list
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self;
tableView.delegate = self;
self.tableView.rowHeight = UITableViewAutomaticDimension
let streamURL = NSURL(string: "http://192.241.174.8:8000/beat-stream-all/")!
let stuff = GetBeatStream(url:streamURL)
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 50.0; //
stuff.downloadJSONFromURL {
(let jsonDictionary) in
if let jsonList = jsonDictionary["results"] as? NSArray {
self.list = jsonList
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
self.tableView.reloadData()
}
}
}
}//end view did load
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("streamCell", forIndexPath: indexPath) as! StreamTableViewCell
cell.beatCover.image = UIImage(named: "imgres")
if let id = list[indexPath.section] as? NSDictionary {
if let beatID = id["id"] as? NSInteger {
cell.setID(beatID)
}
}
if let beat_cover = list[indexPath.section] as? NSDictionary {
if let beat_cover_image = beat_cover["beat_cover"] as? String {
cell.beatCover.downloadImageFrom(link: beat_cover_image, contentMode: UIViewContentMode.ScaleToFill) //set your image from link array.
}
}
if let audio = list[indexPath.section] as? NSDictionary {
if let audio_url = audio["audio"] as? String {
cell.url = audio_url
cell.buildPlayer()
}
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return list.count
}
func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let beatAuthorLabel = UILabel(frame: CGRectMake(55, 5, 200, 40))
//USER PIC
let profilePictureImageView = UIImageView(frame: CGRectMake(5, 5, 40, 40));
profilePictureImageView.layer.borderWidth = 0
profilePictureImageView.layer.masksToBounds = false
profilePictureImageView.layer.borderColor = UIColor.blackColor().CGColor
profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.height/2
profilePictureImageView.clipsToBounds = true
profilePictureImageView.layer.masksToBounds = true
profilePictureImageView.image = UIImage(named: "imgres") //set placeholder image first.
if let userPicSection = list[section] as? NSDictionary {
if let artist = userPicSection["artist"] as? NSDictionary {
if let profilePic = artist["profile_pic"] as? String {
profilePictureImageView.downloadImageFrom(link: profilePic, contentMode: UIViewContentMode.ScaleAspectFit)
}
}
}
if let nameSection = list[section] as? NSDictionary {
if let name = nameSection["artist"] as? NSDictionary {
if let adminName = name["admin_name"] as? NSString {
print(adminName)
beatAuthorLabel.text = adminName as String
beatAuthorLabel.font = UIFont(name: beatAuthorLabel.font.fontName, size: 14)
}
}
}
var dateLabel = UILabel(frame: CGRectMake(225, 5, 200, 40))
if let created = list[section] as? NSDictionary {
if let date = created["created_at"] as? String {
dateLabel.text = date as String
dateLabel.font = UIFont(name: dateLabel.font.fontName, size: 8)
}
}
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.addSubview(beatAuthorLabel)
header.contentView.addSubview(dateLabel)
header.contentView.addSubview(dateLabel)
header.contentView.addSubview(profilePictureImageView)
header.contentView.backgroundColor = UIColor(red: 179/255, green: 194/255, blue: 191/255, alpha:1)
header.textLabel!.textColor = UIColor.whiteColor()
header.alpha = 1
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRowAtIndexPath(indexPath!)! as! StreamTableViewCell
currentCell.player.play()
}
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let leavingCell = cell as! StreamTableViewCell
leavingCell.player.pause()
}
}
Header views, like cells, are reused. So, when the table view sends you tableView(_:willDisplayHeaderView:), it might not be the first time you've received that message for that header view. Yet every time you receive the message, you add four subviews to it.
Don't implement tableView(_:willDisplayHeaderView:forSection:) at all.
Instead, make a subclass of UITableViewHeaderFooterView with properties for the different subviews. This is just like how you created a subclass of UITableViewCell named StreamTableViewCell. Maybe you could call your header subview class StreamSectionHeaderView. Then you have two options for setting up the header view's subviews.
Option 1: In StreamSectionHeaderView.initWithFrame(_:), create the subviews of the header view (and store them in the instance properties and add them as subviews). This is essentially what you're doing now in tableView(_:willDisplayHeaderView:forSection:), but you would move most of the code into the StreamSectionHeaderView class. Register the StreamSectionHeaderView class with the table view using UITableView.registerClass(_:forHeaderFooterViewReuseIdentifier:).
Option 2: Design the header view and its subviews in a XIB (you can't do it in a storyboard), connect the subviews to the StreamSectionHeaderView properties (which must be IBOutlets in this case), and register the XIB in the table view with UITableView.registerNib(_:forHeaderFooterViewReuseIdentifier:).
To produce section, implement tableView(_:viewForHeaderInSection:) by calling tableView.
dequeueReusableHeaderFooterViewWithIdentifier(_:) and then configuring the header view's subviews, which already exist by the time dequeueReusableHeaderFooterViewWithIdentifier(_:) returns.
UPDATE
Here's your StreamSectionHeaderView, assuming you want to set up its subviews in code:
class StreamSectionHeaderView: UITableViewHeaderFooterView {
// Make these IBOutlets if you design StreamSectionHeaderView in a XIB.
var beatAuthorLabel = UILabel(frame: CGRectMake(55, 5, 200, 40))
var profilePictureImageView = UIImageView(frame: CGRectMake(5, 5, 40, 40))
var dateLabel = UILabel(frame: CGRectMake(225, 5, 200, 40))
init(frame: CGRect) {
profilePictureImageView.layer.borderWidth = 0
profilePictureImageView.layer.masksToBounds = false
profilePictureImageView.layer.borderColor = UIColor.blackColor().CGColor
profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.height/2
profilePictureImageView.clipsToBounds = true
profilePictureImageView.layer.masksToBounds = true
profilePictureImageView.image = UIImage(named: "imgres")
beatAuthorLabel.font = UIFont(name: beatAuthorLabel.font.fontName, size: 14)
dateLabel.font = UIFont(name: dateLabel.font.fontName, size: 8)
contentView.addSubview(beatAuthorLabel)
contentView.addSubview(dateLabel)
contentView.addSubview(profilePictureImageView)
contentView.backgroundColor = UIColor(red: 179/255, green: 194/255, blue: 191/255, alpha:1)
textLabel!.textColor = UIColor.whiteColor()
alpha = 1
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Then, in your table view controller:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// blah blah blah other stuff
tableView.registerClass(StreamSectionHeaderView.self, forHeaderFooterViewReuseIdentifier: "Header")
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("Header") as! StreamSectionHeaderView
if let userPicSection = list[section] as? NSDictionary {
if let artist = userPicSection["artist"] as? NSDictionary {
if let profilePic = artist["profile_pic"] as? String {
header.profilePictureImageView.downloadImageFrom(link: profilePic, contentMode: UIViewContentMode.ScaleAspectFit)
}
}
}
if let nameSection = list[section] as? NSDictionary {
if let name = nameSection["artist"] as? NSDictionary {
if let adminName = name["admin_name"] as? NSString {
print(adminName)
header.beatAuthorLabel.text = adminName as String
}
}
}
if let created = list[section] as? NSDictionary {
if let date = created["created_at"] as? String {
header.dateLabel.text = date as String
}
}
return header
}
}
I have to retrieve images from Parse, and I am working on this code:
class ViewControllerHome: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var MessageTable: UITableView!
let color = UIColor(red: 0.0/255.0, green: 105.0/255.0, blue: 92.0/255.0, alpha: 1)
let colore = UIColor.whiteColor()
let coloree = UIColor(red: 33.0/255.0, green: 33.0/255.0, blue: 33.0/255.0, alpha: 1)
var Username = [String]()
var Image = [PFFile]()
var Likes = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
var refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: Selector("refreshPulled"), forControlEvents: UIControlEvents.ValueChanged)
loadData()
self.MessageTable.reloadData()
self.navigationController?.navigationBar.barTintColor = color
self.navigationController?.navigationBar.tintColor = colore
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: colore]
UITabBar.appearance().barTintColor = coloree
UITabBar.appearance().tintColor = colore
UITabBar.appearance().translucent = false
self.MessageTable.delegate = self
self.MessageTable.dataSource = self
func refreshPulled() {
loadData()
self.MessageTable.reloadData()
refreshControl.endRefreshing()
}
}
func loadData() {
let query = PFQuery(className: "Messages")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(posts: [PFObject]?, error: NSError?) -> Void in
if (error == nil) {
if let posts = posts as [PFObject]? {
for post in posts{
self.Image.append(post["Post"] as! PFFile)
self.Username.append(post["Name"] as! String)
self.Likes.append(post["Vote"] as! Int)
}
}
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.MessageTable.dequeueReusableCellWithIdentifier("cell")! as! TableViewCellHome
var imagesToLoad = self.Image[indexPath.row] as PFFile
var imagesUser = self.Username[indexPath.row] as String
var imageLikes = self.Likes[indexPath.row] as Int
//This line gives me an error: call can throw, but is not marked with 'try' and the error is not handled
var imagesdata = imagesToLoad.getData()
var finalizedImage = UIImage(data: imagesdata)
cell.PostImage.image = finalizedImage
cell.UsernameLabel.text = imagesUser
cell.LikesLabel.text = "\(imageLikes)"
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Username.count
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
This code should get and display Image, string and Int Value from parse's backend. The problem is that nothing is displayed. How can I change the code so that this will display correctly? There is also an error at the line:
var imagesdata = imagesToLoad.getData()
This line tells me
call can throw, but is not marked with 'try' and the error is not handled
Thanks in advance to anyone that can help me solve this problem.
I'm trying to use two custom cells for displaying the product information, on the first one I show the product main information and in the second one I display the comments of this product.
At the moment everything is linked in the StoryBoard and I have my tableview prepared for storing the comment information in the second custom cell (I have checked the requestComments() function and It's working fine but I can't make them appear.
Is it something related to the numberOfRowsInSection? Because I tried to SUM the products.count with the comments.count and It's showing an error.
It's my first time using two custom cells so I hope someone can help me.
Here is my code:
import UIKit
import Social
class MarcaProductoViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var productoImageView:UIImageView!
#IBOutlet var tableView:UITableView!
#IBOutlet var votarFrame:UIView!
#IBOutlet var votarBarra:UISlider!
#IBOutlet var votarLabel:UILabel!
var productoImage:String!
var nombre:String!
var producto:Producto!
var productos = [Producto]()
var mensaje:Mensaje!
var mensajes = [Mensaje]()
var img:UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Set table view background color
self.tableView.backgroundColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.2)
// Remove extra separator
self.tableView.tableFooterView = UIView(frame: CGRectZero)
// Change separator color
self.tableView.separatorColor = UIColor(red: 240.0/255.0, green: 240.0/255.0, blue: 240.0/255.0, alpha: 0.8)
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0
requestPost()
requestComments()
tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
tableView.reloadData()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.hidesBarsOnSwipe = false
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func requestPost () {
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.website.es/product.php")!)
request.HTTPMethod = "POST"
let postString = "name="+name
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
self.productos = self.parseJsonData(data!)
// Reload table view
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
task.resume()
tableView.reloadData()
}
func parseJsonData(data: NSData) -> [Producto] {
var productos = [Producto]()
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
// Parse JSON data
let jsonProductos = jsonResult?["lista_productos"] as! [AnyObject]
for jsonProducto in jsonProductos {
let producto = Producto()
producto.image = jsonProducto["image"] as! String
producto.name = jsonProducto["name"] as! String
producto.desc = jsonProducto["desc"] as! String
productos.append(producto)
}
}
catch let parseError {
print(parseError)
}
return productos
}
func requestComments () {
//print("Hola")
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.website.es/comments.php")!)
request.HTTPMethod = "POST"
let postString = "name="+name
//print(postString)
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
print("mensajes = \(responseString)")
self.mensajes = self.parseJsonDataComments(data!)
// Reload table view
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
task.resume()
tableView.reloadData()
}
func parseJsonDataComments(data: NSData) -> [Mensaje] {
var messages = [Mensaje]()
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
// Parse JSON data
let jsonProductos = jsonResult?["messages"] as! [AnyObject]
for jsonProducto in jsonProductos {
let message = Mensaje()
message.author = jsonProducto["author"] as! String
message.message = jsonProducto["message"] as! String
message.date = jsonProducto["date"] as! String
messages.append(message)
}
}
catch let parseError {
print(parseError)
}
return message
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return productos.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
title = productos[indexPath.row].nombre
if indexPath.row == 0 {
print("11")
let cell = tableView.dequeueReusableCellWithIdentifier("CellDetail", forIndexPath: indexPath) as! ProductoTableViewCell
cell.selectionStyle = .None
if let url = NSURL(string: productos[indexPath.row].imagen) {
if let data = NSData(contentsOfURL: url) {
self.productoImageView.image = UIImage(data: data)
}
}
cell.name.text = productos[indexPath.row].name
cell.desc.text = productos[indexPath.row].desc
cell.layoutIfNeeded()
return cell
}
else {
print("22")
let cell2 = tableView.dequeueReusableCellWithIdentifier("MostrarComentarios", forIndexPath: indexPath) as! ComentariosTableViewCell
cell2.selectionStyle = .None
cell2.author.text = mensajes[indexPath.row].author
cell2.comment.text = mensajes[indexPath.row].comments
cell2.date.text = mensajes[indexPath.row].date
cell2.layoutIfNeeded()
return cell2
}
} }
Update:
I have made the following changes:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return productos.count+mensajes.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return productos.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
title = productos[indexPath.row].nombre
if indexPath.section == 0 {
print("11")
let cell = tableView.dequeueReusableCellWithIdentifier("CellDetail", forIndexPath: indexPath) as! ProductoTableViewCell
cell.selectionStyle = .None
if let url = NSURL(string: productos[indexPath.row].imagen) {
if let data = NSData(contentsOfURL: url) {
self.productoImageView.image = UIImage(data: data)
}
}
cell.nombre.text = productos[indexPath.row].nombre
cell.descripcion.text = productos[indexPath.row].descripcion
cell.modo_de_empleo.text = productos[indexPath.row].modo_de_empleo
cell.marca.text = productos[indexPath.row].marca
cell.linea.text = productos[indexPath.row].linea
cell.distribuidor.text = productos[indexPath.row].distribuidor
cell.tamano.text = productos[indexPath.row].tamano
cell.precio.text = productos[indexPath.row].precio
cell.codigo_nacional.text = productos[indexPath.row].codigo_nacional
cell.layoutIfNeeded()
return cell
}
else {
let cell2 = tableView.dequeueReusableCellWithIdentifier("MostrarComentarios", forIndexPath: indexPath) as! ComentariosTableViewCell
print(mensajes[indexPath.row].mensaje)
cell2.selectionStyle = .None
cell2.comentario.text = mensajes[indexPath.row].mensaje
cell2.fecha.text = mensajes[indexPath.row].fecha
cell2.layoutIfNeeded()
return cell2
}
}
At the moment, I can display the comments perfectly, but the problem is that the messages from this product are always the same (repeated in every new comment row) I just need to change something (I don't know what exactly) to show the correct information for the messages without beeing duplicated.
Thanks in advance.
I think you have to use return products.count
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count
}
And you have to use % 2 == 0 instead of == 0
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
title = productos[indexPath.row].nombre
if indexPath.row % 2 == 0 { // runs if indexPath.row = 0, 2, 4, 6 etc
let cell = tableView.dequeueReusableCellWithIdentifier("CellDetail", forIndexPath: indexPath) as! ProductoTableViewCell
return cell
} else { // runs if indexPath.row = 1, 3, 5, 7 etc
let cell2 = tableView.dequeueReusableCellWithIdentifier("MostrarComentarios", forIndexPath: indexPath) as! ComentariosTableViewCell
return cell2
}
}
Remainder Operator
The remainder operator (a % b) works out how many multiples of b will
fit inside a and returns the value that is left over (known as the
remainder).
Here’s how the remainder operator works. To calculate 9 % 4, you first
work out how many 4s will fit inside 9:
You can fit two 4s inside 9, and the remainder is 1 (shown in orange).
In Swift, this would be written as:
9 % 4 // equals 1
If someone has the same problem:
else {
let cell2 = tableView.dequeueReusableCellWithIdentifier("MostrarComentarios", forIndexPath: indexPath) as! ComentariosTableViewCell
cell2.selectionStyle = .None
cell2.comentario.text = mensajes[(indexPath.section)-1].mensaje
cell2.fecha.text = mensajes[(indexPath.section)-1].fecha
cell2.layoutIfNeeded()
return cell2
}
Regards,
I tried to reverse my table view in the view did load method by reversing the arrays but it's not working. I'm trying to make it so that it sorts the feed from the time it was created from top to bottom. Am I doing it wrong? If so what should I do?
class Feed: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var table: UITableView!
#IBOutlet var feedBar: UINavigationBar!
var titles = [String]()
var messages = [String]()
var usernames = [String]()
var types = [String]()
override func viewDidLoad() {
super.viewDidLoad()
table.dataSource = self
messages.reverse()
titles.reverse()
usernames.reverse()
types.reverse()
}
func UIColorFromRGB(rgbValue: UInt) -> UIColor {
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
override func viewDidAppear(animated: Bool) {
println("View appeared")
self.messages.removeAll(keepCapacity: true)
self.titles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
self.types.removeAll(keepCapacity: true)
var postQuery = PFQuery(className: "Post")
postQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"] as! String)
self.titles.append(object["title"] as! String)
self.usernames.append(object["username"] as! String)
self.types.append(object["type"] as! String)
self.table.reloadData()
}
}
})
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let postCell = tableView.dequeueReusableCellWithIdentifier("feedPost", forIndexPath: indexPath) as! PostCell
var post = PFObject(className: "Post")
if messages.isEmpty == false {
postCell.message.text = messages[indexPath.row]
}
if titles.isEmpty == false {
postCell.postTtitle.text = titles[indexPath.row]
}
if usernames.isEmpty == false {
postCell.posterName.setTitle(usernames[indexPath.row], forState: .Normal)
}
if self.types[indexPath.row] == "post1" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFCFFBD)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFCFFBD)
} else if self.types[indexPath.row] == "post2" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFFB4AC)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFFB4AC)
} else if self.types[indexPath.row] == "post3" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFFD5A4)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFFD5A4)
}
postCell.selectionStyle = .None
postCell.message.scrollRangeToVisible(NSMakeRange(0, 0))
return postCell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usernames.count
}
}
Observe that in the view's life cycle the viewDidAppear gets called after your viewDidLoad method. It appears that you try to reload the contents from within your viewDidAppear method, and there you are clearing those arrays which you had reversed earlier in viewDidLoad. This is the reason why you are not seeing any effect. You might want to reverse your arrays there.
You are reversing array in viewDidLoad, but you append something in viewDidAppear. viewDidAppear call after viewDidLoad. You should reverse array in the end of viewDidAppear before call self.table.reloadData()
override func viewDidAppear(animated: Bool) {
println("View appeared")
self.messages.removeAll(keepCapacity: true)
self.titles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
self.types.removeAll(keepCapacity: true)
var postQuery = PFQuery(className: "Post")
postQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"] as! String)
self.titles.append(object["title"] as! String)
self.usernames.append(object["username"] as! String)
self.types.append(object["type"] as! String)
}
messages.reverse()
titles.reverse()
usernames.reverse()
types.reverse()
self.table.reloadData()
}
})
}
I figured it out what I did was I did this instead of append...
self.messages.insert(object["message"] as! String, atIndex: 0)
What this basically does is appends the newest message to the beginning of the array.
In my app, I'm showing user a table view of entries and when they tap on one, they're taken to a screen with a TextView so they can edit the contents of that cell. When they save, they're transitioned back to the tableView. The problem is that the data isn't reloading when they return to the tableView, it shows the same data as before they edited the contents of a cell
I've tried putting self.tableView.reloadData() in both viewWillAppear and viewDidAppear but neither are working. I've read a bunch of answers pertaining to this and none have worked. I'd love your help. Thanks!
PastSessionsViewController.swift
class PastSessionsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayOfEntriesNew: [Entry] = [Entry]()
let transitionManager = TransitionManager()
var entry: String?
var entryDate: NSDate?
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let gradient: CAGradientLayer = CAGradientLayer()
let arrayColors: [AnyObject] = [
UIColor(red: 0.302, green: 0.612, blue: 0.961, alpha: 1.000).CGColor,
UIColor(red: 0.247, green: 0.737, blue: 0.984, alpha: 1.000).CGColor
]
tableView.backgroundColor = nil
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 168.0
gradient.frame = view.bounds
gradient.colors = arrayColors
view.layer.insertSublayer(gradient, atIndex: 0)
prepareEntries()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
self.tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
func prepareEntries() {
let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
let managedObjectContext = appDelegate.managedObjectContext!
let request = NSFetchRequest(entityName: "Meditation")
let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
request.sortDescriptors = [sortDescriptor]
var error: NSError?
var showStreak = (top: false, bottom: false)
let result = managedObjectContext.executeFetchRequest(request, error: &error)
if let objects = result as? [Meditation] {
for (index, object) in enumerate(objects) {
var timeLabel = lengthMinutesLabel(minutesString: lengthMinutes(object.length))
var entry = Entry(sessionLength: lengthMinutes(object.length), sessionTimeUnit: timeLabel, sessionStartTime: "\(object.date.format())", sessionJournalEntry: object.journalEntry, sessionStreakTop: showStreak.top, sessionStreakBottom: showStreak.bottom)
arrayOfEntriesNew.append(entry)
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfEntriesNew.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: EntryCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as EntryCell
let entry = arrayOfEntriesNew[indexPath.row]
var journalEntry = entry.sessionJournalEntry
cell.sessionStartTimeLabel.text = entry.sessionStartTime
cell.sessionJournalEntryLabel.text = journalEntry
cell.sessionLengthLabel.text = entry.sessionLength
cell.sessionTimeUnitLabel.text = entry.sessionTimeUnit
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// janky but works, probably a better way to do this. Will figure it out after v1
if sender is UIButton {
let destinationVC = segue.destinationViewController as ViewController
destinationVC.showJournalButton = false
} else {
let path = self.tableView.indexPathForSelectedRow()!
let location = path.row
let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
let managedObjectContext = appDelegate.managedObjectContext!
let request = NSFetchRequest(entityName: "Meditation")
let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
request.sortDescriptors = [sortDescriptor]
var error: NSError?
let result = managedObjectContext.executeFetchRequest(request, error: &error)
if let objects = result as? [Meditation] {
var journalVC = segue.destinationViewController as EditJournalViewController
journalVC.journalEntryCoreDataLocation = path.row
journalVC.journalEntryToEdit = objects[location].journalEntry
journalVC.journalEntryToEditTimestamp = objects[location].date
let transitionManager = self.transitionManager
transitionManager.presenting = true
transitionManager.direction = "left"
journalVC.transitioningDelegate = transitionManager
}
}
}
}
add prepareEntries() in viewWillAppear