Image are not showing in table View - swift

i am trying to get a list of items from mysql and display them in the app.
names appear but the image and price dose not.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
var cell:UITableViewCell? =
tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
if (cell == nil)
{
cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
reuseIdentifier: "BasicCell")
}
// Get the location to be shown
let item: Location = locations[indexPath.row]
// let price=locations[indexPath.row].price
let price=(item.price as NSString).floatValue
let cellPrice = String(format: "%.2f",price)
let serverurl=NSURL(string: "https://myoscapp.com/boot/images/")
let imageaddress = locations[indexPath.row].image
let imageURL = NSURL.init(string: imageaddress, relativeTo: serverurl! as URL)
cell?.textLabel?.text=locations[indexPath.row].name
cell?.detailTextLabel?.text = cellPrice
cell?.imageView?.sd_setImage(with: imageURL! as URL )
cell?.setNeedsLayout() //invalidate current layout
cell?.layoutIfNeeded() //update immediately
return cell!
}

i got everything to work like this. i don't know if for:indexPath is going to have an effect but i don't see anything
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
let cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
reuseIdentifier: "BasicCell")
// Get the location to be shown
let item: Location = locations[indexPath.row]
// let price=locations[indexPath.row].price
let price=(item.price as NSString).floatValue
let cellPrice = String(format: "%.2f",price)
let serverurl=NSURL(string: "https://myoscapp.com/boot/images/")
let imageaddress = locations[indexPath.row].image
let imageURL = NSURL.init(string: imageaddress, relativeTo: serverurl! as URL)
cell.textLabel?.text=locations[indexPath.row].name
cell.detailTextLabel?.text = cellPrice
cell.imageView?.sd_setImage(with: imageURL! as URL )
cell.setNeedsLayout() //invalidate current layout
cell.layoutIfNeeded() //update immediately
return cell
}

Related

How to add multiple items to a UITableViewCell?

Can anyone help me get the email field to display in the tableView cell? The amount field is showing up, but I can't get the email to show along with it.
struct Posts {
var amount:String
var email:String
}
class PaymentRequestVC: UIViewController, UITableViewDelegate {
let tableView = UITableView()
var posts = [Posts]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
tableView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 900)
setupViews()
setupTableView()
loadPosts()
self.tableView.reloadData()
}
func loadPosts() {
let dbUsers = Firestore.firestore().collection("Payouts")
dbUsers.addSnapshotListener { (querySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
} else {
for document in (querySnapshot?.documents)! {
if let Amount = document.data()["amount"] as? String {
let Email = document.data()["email"] as? String
print(Amount)
var post = Posts(amount: "", email: "")
post.amount = Amount
post.email = Email ?? ""
self.posts.append(post)
}
}
self.tableView.reloadData()
print(self.posts)
}
}
}
private func setupViews() {
let stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.spacing = 28
sv.axis = .vertical
sv.distribution = .fill
sv.alignment = .fill
return sv
}()
view.addSubview(stackView)
view.addSubview(tableView)
}
func setupTableView() {
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor)
])
}
}
extension PaymentRequestVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
}
Swift 5
You need to init the cell with UITableViewCell.CellStyle.subtitle for the detailTextLabel attribute to work.
In your extension, change the cell init:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.text = post.email
cell.detailTextLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
Note that if you want the amount and the mail to both show up, using else will only display either the amount or the email, like in the code below
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
let post = posts[indexPath.row]
cell2.detailTextLabel?.text = post.email
cell2.detailTextLabel?.textColor = UIColor.black
return cell2
}
So a better approach would be to return both, and else display nothing
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.text = post.email
cell.detailTextLabel?.textColor = UIColor.black
return cell
} else {
let cell2 = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell2")
//Empty cell returned if the condition above is not fulfilled
return cell2
}
Hope this helps.
I think your logic in cellForRowAt is incorrect.
You have an array of Posts. And you want to display amount and email in the same cell right? One label being the title and the other being the detailed text.
Both labels are in the same UITableViewCell, so you only need to set it up once per post.
In addition, if indexPath.row is greater than the post count, then posts[indexPath.row] would actually crash your code. So that else statement should actually just log an error or simply do nothing.
Try something like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < posts.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let post = posts[indexPath.row]
cell.textLabel?.text = post.amount
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.detailTextLabel?.text = post.email
cell.textLabel?.detailTextLabel?.textColor = UIColor.black
return cell
} else {
// No cells
}
}

Downloading profile image string from firebase database to an uiimage

User upload image to firebase storage and the url string is added to the firebase database,
How can I take the string in the firebase database and convert it to uiimage to use it as an image ?
The string returned from database is like this:
https://firebasestorage.googleapis.com/v0/b/ichatmessage.appspot.com/o/YNoodTnOSGXl6HkPoqhOPAopb8v1?alt=media&token=738771a5-53e3-46c2-b508-ad5cfa03e74e
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! NewMessageCell
let user = users[indexPath.row]
cell.textLabel?.text = user.username
cell.detailTextLabel?.text = user.email
let currentID = Auth.auth().currentUser?.uid
let databaseRef = Database.database().reference().child("users").child(currentID!)
databaseRef.observe(.value) { (data) in
let dictinoray = data.value as? [String: AnyObject]
let profileImage = dictinoray!["profileimage"] as! String
cell.imageView?.image = profileImage.toImage()
print(profileImage)
}
return cell
}
extention
extension String {
func toImage() -> UIImage? {
if let data = Data(base64Encoded: self, options: .ignoreUnknownCharacters){
return UIImage(data: data)
}
return nil
}
}
I used other way by mapping and using storage downloadurl and it worked
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! NewMessageCell
let user = users[indexPath.row]
cell.textLabel?.text = user.username
cell.detailTextLabel?.text = user.email
let storageref = Storage.storage().reference().child(user.userid)
storageref.downloadURL { (imgurl, er) in
let imagedata = try? Data.init(contentsOf: imgurl!)
cell.imageView?.layer.cornerRadius = (cell.imageView?.frame.size.width)!/2
cell.imageView?.image = UIImage.init(data: imagedata!)
}
Another option would be to load and cache the image through Kingfisher. It's how I would usually load images within a tableView that's from an API.
import Kingfisher above your class.
Then in your cellForRowAtIndexPath, set the image with Kingfisher.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! NewMessageCell
let user = users[indexPath.row]
cell.textLabel?.text = user.username
cell.detailTextLabel?.text = user.email
let currentID = Auth.auth().currentUser?.uid
let databaseRef = Database.database().reference().child("users").child(currentID!)
databaseRef.observe(.value) { (data) in
let dictinoray = data.value as? [String: AnyObject]
let profileImage = dictinoray!["profileimage"] as! String
cell.imageView?.kf.setImage(with: URL(string: profileImage))
}
return cell
}
Not sure if you were looking for an alternative but that's another way to do it.

get label text from cell at row

is there another way i can get the string from the refinementslabel.text when I call did select row , because i think/apparently in the new XCode calling
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
crashes my app
so i am looking for code like
let text = refinementsLabel.text at indexpath.row
but I'm not sure exactly what to type?
let sections = ["All Users & Services","Automotive", "Building & Construction", "Cleaning", "Landscaping & Gardening"]
let services = [["All Users & Services"],["Automotive"],["Air Conditioning & Heating","Bricklaying", "Carpentry","Carpet Layer","Concreting & Paving","Electrical","Fencing and Gates","Flooring","Handyman","Other","Painting & Decorating","Pet Control","Plastering","Plumbing","Roofing","Rubbish Removal","Scaffolding","Tiling"], ["Cleaning"],["Landscaping & Gardening"]]
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
var service = serviceTypeCell.refinementsLabel.text
service = services[indexPath.section][indexPath.row]
defaults.set(service, forKey: "Service being searched")
guard let serviceBeingSearched = self.defaults.string(forKey: "Service being searched") else { return }
navigationItem.title = serviceBeingSearched
tableView.reloadData()
}
Below method is using when create new cell that method is use in cellforRow if you are using that method than app crash
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
If you get cell in didselect method you can use below code
let cell = tableView.cellForRow(at: indexPath) as? ServiceCell
if you get string from you can select cell than use below line
let service = services[indexPath.section][indexPath.row]

How do I use SDImageView to download URL within a TableViewCell?

I am trying to use the SDImageView Cocoapod with a table view to retrieve a URL from a database and turning it into a viewable image. When I use the code bellow I don't get images in return, what is wrong with my code? Thanks!
var posts = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Posts")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let title = value["Title"] as? String else { continue }
guard let downloadURL = value["Download URL"] as? String else { continue }
let post = postStruct(title: title, downloadURL: downloadURL)
self.posts.append(post)
}
self.posts = self.posts.reversed(); self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let imageView = cell?.viewWithTag(200) as! UIImageView
imageView.sd_setImage(with: URL(string: "downloadURL"), placeholderImage: UIImage(named: "placeholder.png"))
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
return cell!
}
You need to change SDWebimage syntax as ->
var posts = [postStruct]()
var downloadURL : String = ""
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Posts")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let title = value["Title"] as? String else { continue }
downloadURL = value["Download URL"] as? String ?? ""
let post = postStruct(title: title, downloadURL: downloadURL)
self.posts.append(post)
}
self.posts = self.posts.reversed(); self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let imageView = cell?.viewWithTag(200) as! UIImageView
imageView.sd_setImage(with: URL(string: downloadURL), placeholderImage: UIImage(named: "placeholder.png"))
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
return cell!
}
Where downloadURL is url String.
You first need to pick the postStruct from the array and then the downloadURL. Change your override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method with this.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let imageView = cell?.viewWithTag(200) as! UIImageView
let post = self.posts[indexPath.row];
imageView.sd_setImage(with: URL(string: post.downloadURL), placeholderImage: UIImage(named: "placeholder"))
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
return cell!
}

How to get the First Image from UICollectionViewCell and Save in UITableViewCell

I want to Save the First or the Last Image from the UICollectionView and Save it in the UITabelView Cell as UIImage.I try it with the first indexPath if indexPath == 0 catch the UIImage and then save it in CoreData as NSData but it doest works. Have anyone an idea how can i make that or gives another way to Display the UIImage in the UITableViewCell? Thanks for Help.
Here was the code from the UICollectionViewCell:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("BookPicCell", forIndexPath: indexPath) as! BookPicCell
let cellcore = picture[indexPath.row]
cell.BookImage.image = UIImage(contentsOfFile: cellcore.foto!)
if indexPath.row == 0 {
let firstpic = cell.BookImage.image
let firstcell = UIImagePNGRepresentation(firstpic!)
let firstimag = NSEntityDescription.insertNewObjectForEntityForName("Book", inManagedObjectContext: self.mgdContext) as! Book
firstimag.firstimage = firstcell!
}
do {
try self.mgdContext.save()
} catch {
print("Error")
}
return cell
}
Here was the Code from the UITableViewCell:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = BookTableView.dequeueReusableCellWithIdentifier("BookCell", forIndexPath: indexPath) as! BookCell
let books = book[indexPath.row]
Cell.BookTitle.text = books.title
let picturecount = books.picture!.count
Cell.BookImageCount.text = "\(picturecount) Picture"
let firstpicture = books.firstimage!
Cell.BookImage.image = UIImage(data: firstpicture)
return Cell
}