Reputation: 1
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
Upvotes: 0
Views: 741
Reputation: 16327
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:
@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 ...
}
Upvotes: 0
Reputation: 3008
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)
}
}
}
Upvotes: 1