How do I add a UIButton into my UITableViewCell in Swift 3? - ios

I have an existing UITableView that displays data and is working fine.
However I now want to add an info button into this UITableViewCell.
I added the UIButton directly into the TableViewCell in storyboard. I then tried to declare this button as an outlet but I got the error
"Outlets cannot be connected to repeating content."
I read around the subject and decided to create a new subclass called "
import UIKit
class PersonalStatsTableViewCell: UITableViewCell {
#IBOutlet weak var personalStatsInfoButton: UIButton!
var selectedCellTitle: String?
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
As you can see I have declared the UIButton personalStatsInfoButton in this sub-class.
With more reading around the subject I believe I need to add something like:
personalStatsInfoButton.tag = indexPath.row
personalStatsInfoButton.addTarget(self, action: "infoButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
and then have a function:
function infoButtonClicked(sender:UIButton){
let infoCell = sender.tag
print (infoCell)
}
My issue is I don't know whether I need to take all my existing tableView code and transfer it into the the new sub-class PersonalStatsTableViewCell or just the parts that deal with the info button.
Below is my existing VC code that initially deals with the TableView prior to adding in this new button.
import UIKit
class ShowCommunityViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var membersTableView: UITableView!
#IBOutlet weak var communityName: UILabel!
var communityIsCalled: String?
var comIds = [String]()
var communityId: Int?
var selectedCellTitle: String?
var cellId: Int?
var communityPlayerIds = [String]()
var communityPlayers = [String?]()
override func viewDidLoad() {
super.viewDidLoad()
communityName.text = (communityIsCalled)
self.membersTableView.delegate = self
self.membersTableView.dataSource = self
membersTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.communityPlayers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath)
cell.textLabel?.text = self.communityPlayers[indexPath.row]
cell.textLabel?.font = UIFont(name: "Avenir", size: 12)
cell.textLabel?.textColor = UIColor.white // set to any colour
cell.layer.backgroundColor = UIColor.clear.cgColor
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedCellTitle = self.communityPlayers[indexPath.row]
cellId = indexPath.row
}
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.???.uk/???/specificCommunity.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "id=\(comIds[communityId!])";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
if let arr = json?["players"] as? [[String:String]] {
self.communityPlayerIds = arr.flatMap { $0["id"]!}
self.communityPlayers = arr.flatMap { $0["user_name"]!}
self.membersTableView.reloadData()
print ("names: ",self.communityPlayers)
}
} catch{
print(error)
}
}
}
task.resume()
}
}

You don't need to put any code in your class PersonalStatsTableViewCell you can manage all the things from ShowCommunityViewController what you need to done is in your cellForRowAt method add this
cell.personalStatsInfoButton.tag = indexPath.row
cell.personalStatsInfoButton.addTarget(self, action: #selector(infoButtonClicked(sender:), forControlEvents: UIControlEvents.TouchUpInside)
and add this function
function infoButtonClicked(sender:UIButton){
let infoCell = sender.tag
print (infoCell)
}

Your code and what you are thinking is correct, you just need to change the following line.
Apart from what Arun B has said, you need to make sure xcode knows what kind of class cell will belong to.
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath)
should be
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath) as! PersonalStatsTableViewCell

This happens if the custom class is not set up properly. Make sure that PersonalStatsTableViewCell is set as the Custom class of the UITableViewCell in your storyboard.

Related

UITableViewCell data not showing up in UITableViewController

I am having trouble debugging why my UITableview cell data isn't showing up in the UITableview. The UITableview currently displays blank when the user navigates to it. Data is correctly going into the cellForRowAt and into the function that sets the cell data.
Setting the cell data
class EventInboxTableViewCell: UITableViewCell {
#IBOutlet weak var eventNameLabel: UILabel!
#IBOutlet weak var eventCoverImageView: UIImageView!
#IBOutlet weak var eventStartLabel: UILabel!
#IBOutlet weak var eventEndLabel: UILabel!
var eventStartString = String()
var eventEndString = String()
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
}
func setEvent(_ event:Event) {
eventNameLabel?.text = event.eventName
if event.eventStart != nil {
let eventStartTS = event.eventStart
let eventStartDate = eventStartTS?.dateValue()
self.eventStartString = AppWideService.dateToStringShort(date: eventStartDate!)
}
if event.eventEnd != nil {
let eventEndTS = event.eventEnd
let eventEndDate = eventEndTS?.dateValue()
self.eventEndString = AppWideService.dateToStringShort(date: eventEndDate!)
}
print("Event inbox event \(eventStartString)")
print("Event inbox event \(eventEndString)")
eventStartLabel?.text = self.eventStartString
eventEndLabel?.text = self.eventEndString
guard let urlString = event.eventCoverUrl as? String else { return }
let url = URL(string: urlString)
guard url != nil else {
//Couldn't create url object
return
}
eventCoverImageView?.sd_setImage(with: url) { (image, error, cacheType, url) in
self.eventCoverImageView?.image = image
}}}
For some reason when I remove the ? from setting the label text it says the values like eventName or eventStartString etc are nil, but I have print statements that ensure they are not.
UITableView Datasource
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return retrievedEvents.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EventInboxTableViewCell", for: indexPath) as! EventInboxTableViewCell
let event = retrievedEvents[indexPath.row]
cell.setEvent(event)
return cell
}
Registered the cell in viewDidLoad
tableView.register(EventInboxTableViewCell.self, forCellReuseIdentifier: "EventInboxTableViewCell")
The problem is the way the table view controller was being used.
If you design a View Controller (of any type) in Storyboard, and you want to use it, you cannot simply say:
let vc = EventInboxTableViewController()
you have to instantiate it from the storyboard:
if let vc = storyboard?.instantiateViewController(withIdentifier: "EventInboxTableViewController") as? EventInboxTableViewController {
navigationController?.pushViewControllerFromLeft(controller: vc)
}
So, in Storyboard, assign your custom class to your UITableViewController, and make sure to fill in the Storyboard ID field (with the string you are using in code as the Identifier).

Is there a way to get the id of a UITableViewCell?

my problem: I want to open some kind of Profil if a user pushes a Button in a Table-View Cell. The Cells Data is downloaded from Parse.
The idea is based on Instagram, if you click on the username-button on Insta the profile from the user who posted the image will open. I want to create the same code, but i can't create the code to get the user. Can you help me?
Heres some code:
import UIKit
import Parse
class HomeController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let reuseIdentifer = "FeedCell"
var delegate: HomeControllerDelegate?
var newCenterController: UIViewController!
let tableView = UITableView()
//Für Parse:
var users = [String: String]()
var comments = [String]()
var usernames = [String]()
var lastnames = [String]()
var imageFiles = [PFFileObject]()
var wischen: UISwipeGestureRecognizer!
var wischen2: UISwipeGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
getData()
configureNavigationBar()
configurateTableView()
wischen = UISwipeGestureRecognizer()
wischen.addTarget(self, action: #selector(handleMenuToggle))
wischen.direction = .right
wischen.numberOfTouchesRequired = 1
view.addGestureRecognizer(wischen)
wischen2 = UISwipeGestureRecognizer()
wischen2.addTarget(self, action: #selector(handleMenuToggle))
wischen2.direction = .left
wischen2.numberOfTouchesRequired = 1
view.addGestureRecognizer(wischen2)
}
#objc func handleMenuToggle() {
delegate?.handleMenuToggle(forMenuOption: nil)
}
#objc func showProfile() {
let vc: AProfileViewController!
vc = AProfileViewController()
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
func configureNavigationBar() {
navigationController?.navigationBar.barTintColor = .darkGray
navigationController?.navigationBar.barStyle = .black
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "Noteworthy", size: 22)!, NSAttributedString.Key.foregroundColor: UIColor.white]
//navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationItem.title = "Mobile Job Board"
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_menu_white_3x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleMenuToggle))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_mail_outline_white_2x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(showCreateNewArticle))
}
//MARK: Table View
//skiped table view configuration
}
// - MARK: Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell
imageFiles[indexPath.row].getDataInBackground { (data, error) in
if let imageData = data {
if let imageToDisplay = UIImage(data: imageData) {
cell.postImage.image = imageToDisplay
}
}
}
cell.descriptionLabel.text = comments[indexPath.row]
cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)
cell.userButton.addTarget(self, action: #selector(showProfile), for: .touchUpInside)
return cell
}
//skiped
}
Thanks a lot!
Tom
The issue here is that your button works on a selector and it has no idea about the sender or where it was called from.
I would do this by creating a custom table view cell (e.g. FeedCell) which allows you to set a delegate (e.g. FeedCellDelegate). Set your class as the delegate for the cell and pass into the cell it's current indexPath. You can then return the indexPath in the delegate call.
Example: Note that code has been removed for simplicity and this code has not been tested. This is simply to guide you in the right direction.
View Controller
import UIKit
class HomeController: UIViewController {
// stripped additional information for example
func showProfile(_ username: String) {
let vc: AProfileViewController!
vc = AProfileViewController()
vc.username = username
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
}
extension HomeController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell
cell.delegate = self
cell.descriptionLabel.text = comments[indexPath.row]
cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)
cell.setIndex(indexPath)
return cell
}
}
extension HomeController: FeedCellDelegate {
func didPressButton(_ indexPath: IndexPath) {
let userName = usernames[indexPath.row]
showProfile(username)
}
}
Feed Cell
import UIKit
protocol FeedCellDelegate {
didPressButton(_ indexPath: IndexPath)
}
class FeedCell: UICollectionViewCell {
var delegate: FeedCellDelegate?
var indexPath: IndexPath
#IBOutlet weak var userButton: UIButton
setIndex(_ indexPath: IndexPath) {
self.indexPath = indexPath
}
#IBAction userButtonPressed() {
if(delegate != nil) {
delegate?.didPressButton(indexPath)
}
}
}
You can generically and in a type safe way get the parent responder of any responder with:
extension UIResponder {
func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
return next as? T ?? next.flatMap { $0.firstParent(ofType: type) }
}
}
So:
Get the parent tableviewCell of your button in the target action function
Ask your tableview for the index path
Use the index path.row to index into your users array:
#objc func showProfile(_ sender: UIButton) {
guard let cell = firstParent(ofType: UITableViewCell.self),
let indexPath = tableView.indexPath(for: cell) else {
return
}
let user = users[indexPath.row]
... do other stuff here ...
}

Swift: Cannot put my value into label (optional issue)

I have my value from Firebase but Swift doesn't want to put it in my label.
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
To summarize, my database look like that:
Firebase database
I've created a standard model call ServiceModel:
import Foundation
class ServiceModel {
var name: String?
var category: String?
var pricing: String?
init(name: String?, category: String?, pricing: String?){
self.name = name
self.category = category
self.pricing = pricing
}
}
I want to display this values into a TableView, so I've created a custom cell like this (very standard too):
import UIKit
class SubscriptionTableViewCell: UITableViewCell {
#IBOutlet weak var imageService: UIImageView!
#IBOutlet weak var labelName: UILabel!
#IBOutlet weak var labelCategory: UILabel!
#IBOutlet weak var labelPricing: 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
}
}
And now, here is the controller of my view:
import UIKit
import FirebaseDatabase
class SecondViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
var refServices:DatabaseReference!
#IBOutlet weak var ListSub: UITableView!
var serviceList = [ServiceModel]()
var databaseHandle:DatabaseHandle?
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return serviceList.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCell", for: indexPath) as! SubscriptionTableViewCell
let service: ServiceModel
service = serviceList[indexPath.row]
//cell.imageService.image = UIImage(named: service.name! + ".png")
cell.labelName?.text = service.name //ERROR HERE
cell.labelCategory?.text = service.category
cell.labelPricing?.text = service.pricing
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
ListSub.delegate = self
ListSub.dataSource = self
refServices = Database.database().reference().child("Categories");
refServices.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
self.serviceList.removeAll()
for services in snapshot.children.allObjects as! [DataSnapshot] {
let serviceObject = services.value as? [String: AnyObject]
let serviceName = serviceObject?["Name"]
let serviceCategory = serviceObject?["Category"]
let servicePricing = serviceObject?["Pricing"]
let service = ServiceModel(name: serviceName as! String?, category: serviceCategory as! String?, pricing: servicePricing as! String?)
self.serviceList.append(service)
}
self.ListSub.reloadData()
}
})
}
When I launch this view, I have the error mentioned earlier.
When I debug, I see that I have the right values in service.name, service.category and service.pricing
It seems that I don't correctly handle Optional values, but I cannot see what is wrong.
Thanks for your help.
Potential lines to be crashed in case of optional unwrapping is this line
refServices = Database.database().reference().child("Categories");
refServices.observe(DataEventType.value, with: { (snapshot) in
Try to pur breakpoint and check if refServices is initialised properly or make ti to be optional not using !
Hope this help
Ps. please remove ; out of your Swift code :P
Use this code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCell", for: indexPath) as! SubscriptionTableViewCell
let service = serviceList[indexPath.row]
// If you sure that you have to display all the info use this code
if let name = service.name, let category = service.category, let price = service.pricing {
cell.labelName.text = name
// set other data also here....
}
// If you know any value may be empty or not exists then use this code.
if let name = service.name {
cell.labelName.text = name
}
if let category = service.category {
cell.labelCategory.text = service
}
if let pricing = service.pricing {
cell.labelPricing.text = pricing
}
return cell
}
Did you register your custom UITableViewCell with your tableView? Put this line into the init() function of your ViewController:
ListSub.register(SubscriptionTableViewCell.classForCoder(), forCellReuseIdentifier: "SubCell")
If you debug this function, what did you see for your service
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCell", for: indexPath) as! SubscriptionTableViewCell
let service: ServiceModel
//Put a breakpoint here
service = serviceList[indexPath.row]
//Put a breakpoint here
//cell.imageService.image = UIImage(named: service.name! + ".png")
cell.labelName?.text = service.name
cell.labelCategory?.text = service.category
cell.labelPricing?.text = service.pricing
return cell
}

chat messenger UITableViewCell, loading message

i am trying to load messages into my messenger using firebase, however, it isnt showing. I set my cells background to light gray and i can see it's working as the number of messages in database and cells in light gray matched.
the code i used is
func loadMsg() {
let toId = user!.id!
let fromId = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("privateMessages").child(fromId).child(toId)
ref.observe(.value) { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.messages.removeAll()
for data in snapshot {
let newMsg = Message(dictionary: data.value as! [String: AnyObject])
self.messages.append(newMsg)
}
}
DispatchQueue.main.async {self.tableView.reloadData()}
}
}
my firebase database looks like:
and my simulator looks like
as of my storyboard:
any reason why my text aren't showing???
*UPDATED BELOW
i tried to configure my cells, and now it seems to be going to the right direction but I am having crash on my sentView where it crashes due to
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
my code for my tableview cell is
import UIKit
import Firebase
import FirebaseDatabase
class ChatMessageCell: UITableViewCell {
var message: Message!
#IBOutlet weak var receivedMsgLabel: UILabel!
#IBOutlet weak var sentMsgLabel: UILabel!
#IBOutlet weak var sentView: UIView!
#IBOutlet weak var receivedView: UIView!
var currentUser = Auth.auth().currentUser!.uid
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
}
func configCell(message: Message) {
self.message = message
if message.fromId == currentUser {
sentView.isHidden = false
sentMsgLabel.text = message.textMessages
receivedMsgLabel.text = ""
receivedMsgLabel.isHidden = true
} else {
sentView.isHidden = true
sentMsgLabel.text = ""
receivedMsgLabel.text = message.textMessages
receivedMsgLabel.isHidden = false
}
}
}
as for my table is
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: ChatMessageCell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ChatMessageCell
let message = messages[indexPath.row]
cell.configCell(message: message)
cell.backgroundColor = UIColor.lightGray
return cell
}
am i going in the right direction?? sorry not sure where to post my codes, therefore posting it in answer section.
"The unbalanced calls to begin/end appearance transitions"
Crash occurs when you try and display a content before the cell is finished displaying.
Try by creating new custom cell xib and try.
register like this.
self.tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "TableViewCell")
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
let message = messages[indexPath.row]
cell.configCell(message: message)
cell.backgroundColor = UIColor.lightGray
return cell
}

Pass value to next view when label in Table view cell is tapped

would love to pass the value postArray[indexpath.row].creatorId when the label inside a tableview cell is tapped so it can be passed onto the next view controller so i can load the profile of that particular creator/user. I used custom cells, so how do i get the creator id based on the location of the label(username) selected.
//custom cell
class PostCell : UITableViewCell
{
#IBOutlet weak var timeAgoLabel: UILabel!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var postImageView: UIImageView!
#IBOutlet weak var captionLabel: UILabel!
#IBOutlet weak var postStatsLabel: UILabel!
}
//do something when label is tapped
#objc func tapFunction(sender:UITapGestureRecognizer) {
//userClicked = creatorData
print(userClicked)
appDelegate.profileView()
print("tap working")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}else{
return postsArray.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//var returnCell: UITableViewCell!
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as! statusCell
profilePicture = UserDefaults.standard.object(forKey: "userPic") as? String
if profilePicture != nil {
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(profilePicture)!
let profileURL = URL(string: urlString)
cell.statusProfilePic?.downloadedFrom(url: profileURL!)
} else {
print("you have no profile picture set")
}
return cell
} else {
if postsArray[indexPath.row].photos != nil{
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
}else{
likes = 0
}
//assign post id to PostID
postID = postsArray[indexPath.row].post_id
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.usernameLabel.isUserInteractionEnabled = true
cell.usernameLabel.addGestureRecognizer(tap)
cell.usernameLabel.text = postsArray[indexPath.row].fullname
cell.timeAgoLabel.text = postsArray[indexPath.row].data_created
cell.captionLabel.text = postsArray[indexPath.row].content
cell.timeAgoLabel.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.postStatsLabel.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.profileImageView.downloadedFrom(url: profileURL!)
//iterate through posts images images array
//load post picture from server library
var postImageName : String?
if postsArray[indexPath.row].photos != nil{
let postImage = postsArray[indexPath.row].photos
for postsImage in postImage!{
postImageName = postsImage.filename!
}
let urlPostImageString = "https://test.com/uploads/post-picture/"+(postImageName)!
let postsImageUrl = URL(string: urlPostImageString)
cell.postImageView.downloadedFrom(url: postsImageUrl!)
} else {
print("Post has no picture")
}
//return cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "NoImageCell", for: indexPath) as! NoImageTableViewCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
} else {
likes = 0
}
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.noImageUsername.isUserInteractionEnabled = true
cell.noImageUsername.addGestureRecognizer(tap)
cell.noImageUsername.text = postsArray[indexPath.row].fullname
cell.noImageTime.text = postsArray[indexPath.row].data_created
cell.noImagePost.text = postsArray[indexPath.row].content
cell.noImageTime.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.noImageLikeAndComment.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.noImageProfilePic.downloadedFrom(url: profileURL!)
return cell
}
}
}
Use this for example.
Implement didSelectRow() method and in it write something like this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// this method works, when you taped cell. write here code of you need. Next code only example, which set user info to some VC and push it:
let controller = UserController as? UserController
if let controller = controller {
controller.user = users[indexPath.row]
self.navigationController?.pushViewController(controller, animated: true)
}
}
add this to your Cell's class:
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
// here your code of tap on label
print("label tapped")
}
Check on storyBoard is your label isUserInteractionEnabled? - set it to true. Inside tapRecodnized() method do what are you need. And you need to call method setTap() in your cell's method, which you call in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell.
Update
Simple example. this code know what are you tapped. if you tap cell, but not label, add code of push some controller, else code of push another controller.
Cell's Class:
class MyTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
var mainController: ViewController?
func setText(text: String) {
setTap()
label.text = text
}
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
if let mainController = mainController {
print("label tapped")
mainController.pushSomeVc(cell: self)
}
}
}
Code of main Class:
class ViewController: UIViewController {
#IBOutlet weak var myTableView: UITableView!
var array = ["1", "2", "3", "4", "5", "6"]
override func viewDidLoad() {
super.viewDidLoad()
}
func pushSomeVc(cell: MyTableViewCell) {
let row = myTableView.indexPath(for: cell)?.row
if let row = row {
// write here code of push controller, when label tapped. row property for get some user from array
print("push some vc with \(row)")
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "cell") as? MyTableViewCell
if let cell = cell {
cell.setText(text: array[indexPath.row])
cell.mainController = self
}
return cell ?? UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
// write here code of push controller with comments
print("cell tapped: \(indexPath.row)")
}
}
I tested this code and it's work perfect

Resources