table 视图单元格中的按钮没有响应
Button in table view cell not responding
我正在开发一个社交媒体应用程序,在主要部分(新闻)中,我创建并添加了一个 UITableViewController
自定义 PostCell
。在这个单元格中我添加了一个赞UIButton
。问题是当我点击按钮时,#selector
方法没有响应。
这是我的一些代码:
Post 单元格:
import UIKit
class PostCell: UITableViewCell {
let userDataContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let userImgView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.image = UIImage(named: "person.crop.circle.fill")?.maskWithColor(color: UIColor.mainColor)
return iv
}()
let completeNameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
lbl.textColor = UIColor.darkText
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let usernameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.textColor = UIColor.darkGray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let timestampLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
lbl.textColor = UIColor.gray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let moreOptionsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
return button
}()
let textViewsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let textViewSeparatorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
return view
}()
let postTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 22, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
return tv
}()
let resourceTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 18, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
tv.isSelectable = true
return tv
}()
let actionsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.isUserInteractionEnabled = true
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let likesLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "0"
lbl.textColor = UIColor.mainColor
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let commentsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bubble.left"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let bookmarkButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bookmark"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
override func layoutSubviews() {
super.layoutSubviews()
userImgView.circleImageView()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
addSubview(userDataContainerView)
userDataContainerView.addSubview(userImgView)
userDataContainerView.addSubview(completeNameLabel)
userDataContainerView.addSubview(usernameLabel)
userDataContainerView.addSubview(moreOptionsButton)
addSubview(textViewsContainerView)
addSubview(textViewSeparatorView)
textViewsContainerView.addSubview(postTextView)
textViewsContainerView.addSubview(resourceTextView)
addSubview(actionsContainerView)
actionsContainerView.addSubview(likeButton)
actionsContainerView.addSubview(likesLabel)
actionsContainerView.addSubview(commentsButton)
actionsContainerView.addSubview(bookmarkButton)
actionsContainerView.addSubview(timestampLabel)
setUpConstraints()
}
func setUpConstraints() {
// needs x, y, h, w anchors
userDataContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
userDataContainerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
userDataContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/5).isActive = true
userDataContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
userImgView.leftAnchor.constraint(equalTo: userDataContainerView.leftAnchor, constant: 8).isActive = true
userImgView.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 8).isActive = true
userImgView.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, constant: -16).isActive = true
userImgView.widthAnchor.constraint(equalTo: userImgView.heightAnchor).isActive = true
// needs x, y, h, w anchors
completeNameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
completeNameLabel.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 4).isActive = true
completeNameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
completeNameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
usernameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
usernameLabel.topAnchor.constraint(equalTo: completeNameLabel.bottomAnchor, constant: 4).isActive = true
usernameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
usernameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, w, anchors
moreOptionsButton.rightAnchor.constraint(equalTo: userDataContainerView.rightAnchor, constant: -16).isActive = true
moreOptionsButton.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 16).isActive = true
moreOptionsButton.heightAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 1/4, constant: -4).isActive = true
moreOptionsButton.widthAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 2/3).isActive = true
// needs x, y, h, w anchors
textViewSeparatorView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewSeparatorView.bottomAnchor.constraint(equalTo: userDataContainerView.bottomAnchor).isActive = true
textViewSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
textViewSeparatorView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
textViewsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewsContainerView.topAnchor.constraint(equalTo: userDataContainerView.bottomAnchor, constant: 12).isActive = true
textViewsContainerView.bottomAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
textViewsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
postTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
postTextView.topAnchor.constraint(equalTo: textViewsContainerView.topAnchor, constant: 4).isActive = true
postTextView.bottomAnchor.constraint(equalTo: resourceTextView.topAnchor, constant: -8).isActive = true
postTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
resourceTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
resourceTextView.bottomAnchor.constraint(equalTo: textViewsContainerView.bottomAnchor, constant: -4).isActive = true
resourceTextView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/8).isActive = true
resourceTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
actionsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
actionsContainerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
actionsContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/4).isActive = true
actionsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
timestampLabel.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 8).isActive = true
timestampLabel.topAnchor.constraint(equalTo: likeButton.bottomAnchor, constant: 2).isActive = true
timestampLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/3, constant: -8).isActive = true
timestampLabel.widthAnchor.constraint(equalTo: actionsContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
likeButton.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 12).isActive = true
likeButton.topAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
likeButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likeButton.widthAnchor.constraint(equalTo: likeButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
likesLabel.leftAnchor.constraint(equalTo: likeButton.rightAnchor, constant: 12).isActive = true
likesLabel.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
likesLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likesLabel.widthAnchor.constraint(equalTo: likesLabel.heightAnchor).isActive = true
// needs x, y, h, w anchors
commentsButton.leftAnchor.constraint(equalTo: likesLabel.rightAnchor, constant: -8).isActive = true
commentsButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
commentsButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
commentsButton.widthAnchor.constraint(equalTo: commentsButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
bookmarkButton.leftAnchor.constraint(equalTo: commentsButton.rightAnchor, constant: 12).isActive = true
bookmarkButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
bookmarkButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
bookmarkButton.widthAnchor.constraint(equalTo: bookmarkButton.heightAnchor).isActive = true
}
func configCell(post: Post) {
userImgView.loadImageUsingCacheWithUrlString(urlString: post.userImg!)
completeNameLabel.text = post.userCompleteName
usernameLabel.text = "@\(post.username!)"
if let seconds = post.timestamp?.doubleValue {
let timestampDate = Date(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
self.timestampLabel.text = dateFormatter.string(from: timestampDate)
}
postTextView.text = post.postText
resourceTextView.text = post.postResource
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
新闻负责人:
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class NewsViewController: UITableViewController {
var activityIndicator = UIActivityIndicatorView(style: .large)
var aiView = UIView()
let cellId = "cellId"
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
setUpActivityIndicator()
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "arrow.clockwise"), style: .plain, target: self, action: #selector(handleRefresh))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "square.and.pencil"), style: .done, target: self, action: #selector(didTapCreateButton))
navigationItem.rightBarButtonItem?.tintColor = UIColor.mainColor
navigationItem.leftBarButtonItem?.tintColor = UIColor.mainColor
view.backgroundColor = .systemBackground
title = "News"
tableView.register(PostCell.self, forCellReuseIdentifier: cellId)
startAI()
observePosts()
}
func observePosts() {
let ref = Database.database().reference().child("posts")
ref.observe( .value, with: { (snapshot) in
self.stopAI()
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.posts.removeAll()
for data in snapshot.reversed() {
if let postDict = data.value as? [String: AnyObject] {
let post = Post(dictionary: postDict, key: data.key)
self.posts.append(post)
}
}
self.tableView.reloadData()
}
}, withCancel: nil)
}
func setUpActivityIndicator() {
aiView.layer.zPosition = 0.1
aiView.backgroundColor = UIColor.gray
aiView.alpha = 0
aiView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(aiView)
aiView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true
aiView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor, constant: -60).isActive = true
aiView.heightAnchor.constraint(equalToConstant: 150).isActive = true
aiView.widthAnchor.constraint(equalToConstant: 150).isActive = true
aiView.layer.masksToBounds = true
aiView.layer.cornerRadius = 15
activityIndicator.layer.zPosition = 0.2
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(activityIndicator)
activityIndicator.centerXAnchor.constraint(equalTo: aiView.centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: aiView.centerYAnchor).isActive = true
}
func startAI() {
activityIndicator.startAnimating()
aiView.alpha = 0.80
tableView.isUserInteractionEnabled = false
}
func stopAI() {
self.activityIndicator.stopAnimating()
self.tableView.isUserInteractionEnabled = true
self.aiView.alpha = 0
}
@objc func handleRefresh() {
startAI()
observePosts()
Alert.showAlert(vc: self, title: "Refreshed!", message: "News were refreshed successfully!")
}
@objc func didTapCreateButton() {
let newPostVC = NewPostViewController()
navigationController?.pushViewController(newPostVC, animated: true)
}
@objc func handleLike(_ sender: UIButton) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference()
guard let key = ref.child("posts").childByAutoId().key else { return }
let selectedPost = posts[sender.tag]
var hasLiked = false
ref.child("users").child(uid).child("liked").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
guard let postId = selectedPost.postKey else { return }
if let liked = snapshot.value as? [String: AnyObject] {
for (ke, value) in liked {
if value as? String == postId {
// User has liked post
hasLiked = true
ref.child("users").child(uid).child("liked/\(ke)").removeValue()
ref.child("posts").child(postId).child("likes/\(ke)").removeValue()
sender.likeButton()
}
}
}
if !hasLiked {
ref.child("users").child(uid).child("liked/\(key)").setValue(postId)
ref.child("posts").child(postId).child("likes/\(key)").setValue(uid)
sender.unlikeButton()
}
}, withCancel: nil)
ref.removeAllObservers()
}
func checkLiked(row: Int, cell: PostCell) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference()
let selectedPost = posts[row]
ref.child("users").child(uid).child("liked").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
guard let postId = selectedPost.postKey else { return }
if let liked = snapshot.value as? [String: AnyObject] {
for (_, value) in liked {
if value as? String == postId {
cell.likeButton.unlikeButton()
}
}
}
}, withCancel: nil)
ref.removeAllObservers()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 375
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as? PostCell else { return UITableViewCell() }
checkLiked(row: indexPath.row, cell: cell)
cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: #selector(handleLike(_:)), for: .touchUpInside)
cell.configCell(post: posts[indexPath.row])
return cell
}
}
extension UIButton {
func likeButton() {
self.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
self.tintColor = UIColor.mainColor
}
func unlikeButton() {
self.setImage(UIImage(systemName: "hand.thumbsup.fill"), for: .normal)
self.tintColor = UIColor.mainColor
}
}
这里我给点赞按钮添加目标:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as? PostCell else { return UITableViewCell() }
checkLiked(row: indexPath.row, cell: cell)
cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: #selector(handleLike(_:)), for: .touchUpInside)
cell.configCell(post: posts[indexPath.row])
return cell
}
我找到了解决方法,问题是视图需要添加到 contentView
而不是 PostCell
代码如下:
import UIKit
class PostCell: UITableViewCell {
let userDataContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let userImgView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.image = UIImage(named: "person.crop.circle.fill")?.maskWithColor(color: UIColor.mainColor)
return iv
}()
let completeNameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
lbl.textColor = UIColor.darkText
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let usernameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.textColor = UIColor.darkGray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let timestampLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
lbl.textColor = UIColor.gray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let moreOptionsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
return button
}()
let textViewsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let textViewSeparatorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
return view
}()
let postTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 22, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
return tv
}()
let resourceTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 18, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
tv.isSelectable = true
return tv
}()
let actionsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.isUserInteractionEnabled = true
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let likesLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "0"
lbl.textColor = UIColor.mainColor
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let commentsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bubble.left"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let bookmarkButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bookmark"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
override func layoutSubviews() {
super.layoutSubviews()
userImgView.circleImageView()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
contentView.addSubview(userDataContainerView)
userDataContainerView.addSubview(userImgView)
userDataContainerView.addSubview(completeNameLabel)
userDataContainerView.addSubview(usernameLabel)
userDataContainerView.addSubview(moreOptionsButton)
contentView.addSubview(textViewsContainerView)
contentView.addSubview(textViewSeparatorView)
textViewsContainerView.addSubview(postTextView)
textViewsContainerView.addSubview(resourceTextView)
contentView.addSubview(actionsContainerView)
actionsContainerView.addSubview(likeButton)
actionsContainerView.addSubview(likesLabel)
actionsContainerView.addSubview(commentsButton)
actionsContainerView.addSubview(bookmarkButton)
actionsContainerView.addSubview(timestampLabel)
setUpConstraints()
}
func setUpConstraints() {
// needs x, y, h, w anchors
userDataContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
userDataContainerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
userDataContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/5).isActive = true
userDataContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
userImgView.leftAnchor.constraint(equalTo: userDataContainerView.leftAnchor, constant: 8).isActive = true
userImgView.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 8).isActive = true
userImgView.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, constant: -16).isActive = true
userImgView.widthAnchor.constraint(equalTo: userImgView.heightAnchor).isActive = true
// needs x, y, h, w anchors
completeNameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
completeNameLabel.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 4).isActive = true
completeNameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
completeNameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
usernameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
usernameLabel.topAnchor.constraint(equalTo: completeNameLabel.bottomAnchor, constant: 4).isActive = true
usernameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
usernameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, w, anchors
moreOptionsButton.rightAnchor.constraint(equalTo: userDataContainerView.rightAnchor, constant: -16).isActive = true
moreOptionsButton.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 16).isActive = true
moreOptionsButton.heightAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 1/4, constant: -4).isActive = true
moreOptionsButton.widthAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 2/3).isActive = true
// needs x, y, h, w anchors
textViewSeparatorView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewSeparatorView.bottomAnchor.constraint(equalTo: userDataContainerView.bottomAnchor).isActive = true
textViewSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
textViewSeparatorView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
textViewsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewsContainerView.topAnchor.constraint(equalTo: userDataContainerView.bottomAnchor, constant: 12).isActive = true
textViewsContainerView.bottomAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
textViewsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
postTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
postTextView.topAnchor.constraint(equalTo: textViewsContainerView.topAnchor, constant: 4).isActive = true
postTextView.bottomAnchor.constraint(equalTo: resourceTextView.topAnchor, constant: -8).isActive = true
postTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
resourceTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
resourceTextView.bottomAnchor.constraint(equalTo: textViewsContainerView.bottomAnchor, constant: -4).isActive = true
resourceTextView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/8).isActive = true
resourceTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
actionsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
actionsContainerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
actionsContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/4).isActive = true
actionsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
timestampLabel.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 8).isActive = true
timestampLabel.topAnchor.constraint(equalTo: likeButton.bottomAnchor, constant: 2).isActive = true
timestampLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/3, constant: -8).isActive = true
timestampLabel.widthAnchor.constraint(equalTo: actionsContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
likeButton.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 12).isActive = true
likeButton.topAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
likeButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likeButton.widthAnchor.constraint(equalTo: likeButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
likesLabel.leftAnchor.constraint(equalTo: likeButton.rightAnchor, constant: 12).isActive = true
likesLabel.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
likesLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likesLabel.widthAnchor.constraint(equalTo: likesLabel.heightAnchor).isActive = true
// needs x, y, h, w anchors
commentsButton.leftAnchor.constraint(equalTo: likesLabel.rightAnchor, constant: -8).isActive = true
commentsButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
commentsButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
commentsButton.widthAnchor.constraint(equalTo: commentsButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
bookmarkButton.leftAnchor.constraint(equalTo: commentsButton.rightAnchor, constant: 12).isActive = true
bookmarkButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
bookmarkButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
bookmarkButton.widthAnchor.constraint(equalTo: bookmarkButton.heightAnchor).isActive = true
}
func configCell(post: Post) {
userImgView.loadImageUsingCacheWithUrlString(urlString: post.userImg!)
completeNameLabel.text = post.userCompleteName
usernameLabel.text = "@\(post.username!)"
if let seconds = post.timestamp?.doubleValue {
let timestampDate = Date(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
self.timestampLabel.text = dateFormatter.string(from: timestampDate)
}
postTextView.text = post.postText
resourceTextView.text = post.postResource
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我正在开发一个社交媒体应用程序,在主要部分(新闻)中,我创建并添加了一个 UITableViewController
自定义 PostCell
。在这个单元格中我添加了一个赞UIButton
。问题是当我点击按钮时,#selector
方法没有响应。
这是我的一些代码:
Post 单元格:
import UIKit
class PostCell: UITableViewCell {
let userDataContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let userImgView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.image = UIImage(named: "person.crop.circle.fill")?.maskWithColor(color: UIColor.mainColor)
return iv
}()
let completeNameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
lbl.textColor = UIColor.darkText
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let usernameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.textColor = UIColor.darkGray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let timestampLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
lbl.textColor = UIColor.gray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let moreOptionsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
return button
}()
let textViewsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let textViewSeparatorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
return view
}()
let postTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 22, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
return tv
}()
let resourceTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 18, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
tv.isSelectable = true
return tv
}()
let actionsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.isUserInteractionEnabled = true
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let likesLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "0"
lbl.textColor = UIColor.mainColor
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let commentsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bubble.left"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let bookmarkButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bookmark"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
override func layoutSubviews() {
super.layoutSubviews()
userImgView.circleImageView()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
addSubview(userDataContainerView)
userDataContainerView.addSubview(userImgView)
userDataContainerView.addSubview(completeNameLabel)
userDataContainerView.addSubview(usernameLabel)
userDataContainerView.addSubview(moreOptionsButton)
addSubview(textViewsContainerView)
addSubview(textViewSeparatorView)
textViewsContainerView.addSubview(postTextView)
textViewsContainerView.addSubview(resourceTextView)
addSubview(actionsContainerView)
actionsContainerView.addSubview(likeButton)
actionsContainerView.addSubview(likesLabel)
actionsContainerView.addSubview(commentsButton)
actionsContainerView.addSubview(bookmarkButton)
actionsContainerView.addSubview(timestampLabel)
setUpConstraints()
}
func setUpConstraints() {
// needs x, y, h, w anchors
userDataContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
userDataContainerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
userDataContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/5).isActive = true
userDataContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
userImgView.leftAnchor.constraint(equalTo: userDataContainerView.leftAnchor, constant: 8).isActive = true
userImgView.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 8).isActive = true
userImgView.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, constant: -16).isActive = true
userImgView.widthAnchor.constraint(equalTo: userImgView.heightAnchor).isActive = true
// needs x, y, h, w anchors
completeNameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
completeNameLabel.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 4).isActive = true
completeNameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
completeNameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
usernameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
usernameLabel.topAnchor.constraint(equalTo: completeNameLabel.bottomAnchor, constant: 4).isActive = true
usernameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
usernameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, w, anchors
moreOptionsButton.rightAnchor.constraint(equalTo: userDataContainerView.rightAnchor, constant: -16).isActive = true
moreOptionsButton.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 16).isActive = true
moreOptionsButton.heightAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 1/4, constant: -4).isActive = true
moreOptionsButton.widthAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 2/3).isActive = true
// needs x, y, h, w anchors
textViewSeparatorView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewSeparatorView.bottomAnchor.constraint(equalTo: userDataContainerView.bottomAnchor).isActive = true
textViewSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
textViewSeparatorView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
textViewsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewsContainerView.topAnchor.constraint(equalTo: userDataContainerView.bottomAnchor, constant: 12).isActive = true
textViewsContainerView.bottomAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
textViewsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
postTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
postTextView.topAnchor.constraint(equalTo: textViewsContainerView.topAnchor, constant: 4).isActive = true
postTextView.bottomAnchor.constraint(equalTo: resourceTextView.topAnchor, constant: -8).isActive = true
postTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
resourceTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
resourceTextView.bottomAnchor.constraint(equalTo: textViewsContainerView.bottomAnchor, constant: -4).isActive = true
resourceTextView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/8).isActive = true
resourceTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
actionsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
actionsContainerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
actionsContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/4).isActive = true
actionsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
timestampLabel.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 8).isActive = true
timestampLabel.topAnchor.constraint(equalTo: likeButton.bottomAnchor, constant: 2).isActive = true
timestampLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/3, constant: -8).isActive = true
timestampLabel.widthAnchor.constraint(equalTo: actionsContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
likeButton.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 12).isActive = true
likeButton.topAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
likeButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likeButton.widthAnchor.constraint(equalTo: likeButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
likesLabel.leftAnchor.constraint(equalTo: likeButton.rightAnchor, constant: 12).isActive = true
likesLabel.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
likesLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likesLabel.widthAnchor.constraint(equalTo: likesLabel.heightAnchor).isActive = true
// needs x, y, h, w anchors
commentsButton.leftAnchor.constraint(equalTo: likesLabel.rightAnchor, constant: -8).isActive = true
commentsButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
commentsButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
commentsButton.widthAnchor.constraint(equalTo: commentsButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
bookmarkButton.leftAnchor.constraint(equalTo: commentsButton.rightAnchor, constant: 12).isActive = true
bookmarkButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
bookmarkButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
bookmarkButton.widthAnchor.constraint(equalTo: bookmarkButton.heightAnchor).isActive = true
}
func configCell(post: Post) {
userImgView.loadImageUsingCacheWithUrlString(urlString: post.userImg!)
completeNameLabel.text = post.userCompleteName
usernameLabel.text = "@\(post.username!)"
if let seconds = post.timestamp?.doubleValue {
let timestampDate = Date(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
self.timestampLabel.text = dateFormatter.string(from: timestampDate)
}
postTextView.text = post.postText
resourceTextView.text = post.postResource
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
新闻负责人:
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class NewsViewController: UITableViewController {
var activityIndicator = UIActivityIndicatorView(style: .large)
var aiView = UIView()
let cellId = "cellId"
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
setUpActivityIndicator()
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "arrow.clockwise"), style: .plain, target: self, action: #selector(handleRefresh))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "square.and.pencil"), style: .done, target: self, action: #selector(didTapCreateButton))
navigationItem.rightBarButtonItem?.tintColor = UIColor.mainColor
navigationItem.leftBarButtonItem?.tintColor = UIColor.mainColor
view.backgroundColor = .systemBackground
title = "News"
tableView.register(PostCell.self, forCellReuseIdentifier: cellId)
startAI()
observePosts()
}
func observePosts() {
let ref = Database.database().reference().child("posts")
ref.observe( .value, with: { (snapshot) in
self.stopAI()
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.posts.removeAll()
for data in snapshot.reversed() {
if let postDict = data.value as? [String: AnyObject] {
let post = Post(dictionary: postDict, key: data.key)
self.posts.append(post)
}
}
self.tableView.reloadData()
}
}, withCancel: nil)
}
func setUpActivityIndicator() {
aiView.layer.zPosition = 0.1
aiView.backgroundColor = UIColor.gray
aiView.alpha = 0
aiView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(aiView)
aiView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true
aiView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor, constant: -60).isActive = true
aiView.heightAnchor.constraint(equalToConstant: 150).isActive = true
aiView.widthAnchor.constraint(equalToConstant: 150).isActive = true
aiView.layer.masksToBounds = true
aiView.layer.cornerRadius = 15
activityIndicator.layer.zPosition = 0.2
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(activityIndicator)
activityIndicator.centerXAnchor.constraint(equalTo: aiView.centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: aiView.centerYAnchor).isActive = true
}
func startAI() {
activityIndicator.startAnimating()
aiView.alpha = 0.80
tableView.isUserInteractionEnabled = false
}
func stopAI() {
self.activityIndicator.stopAnimating()
self.tableView.isUserInteractionEnabled = true
self.aiView.alpha = 0
}
@objc func handleRefresh() {
startAI()
observePosts()
Alert.showAlert(vc: self, title: "Refreshed!", message: "News were refreshed successfully!")
}
@objc func didTapCreateButton() {
let newPostVC = NewPostViewController()
navigationController?.pushViewController(newPostVC, animated: true)
}
@objc func handleLike(_ sender: UIButton) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference()
guard let key = ref.child("posts").childByAutoId().key else { return }
let selectedPost = posts[sender.tag]
var hasLiked = false
ref.child("users").child(uid).child("liked").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
guard let postId = selectedPost.postKey else { return }
if let liked = snapshot.value as? [String: AnyObject] {
for (ke, value) in liked {
if value as? String == postId {
// User has liked post
hasLiked = true
ref.child("users").child(uid).child("liked/\(ke)").removeValue()
ref.child("posts").child(postId).child("likes/\(ke)").removeValue()
sender.likeButton()
}
}
}
if !hasLiked {
ref.child("users").child(uid).child("liked/\(key)").setValue(postId)
ref.child("posts").child(postId).child("likes/\(key)").setValue(uid)
sender.unlikeButton()
}
}, withCancel: nil)
ref.removeAllObservers()
}
func checkLiked(row: Int, cell: PostCell) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference()
let selectedPost = posts[row]
ref.child("users").child(uid).child("liked").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
guard let postId = selectedPost.postKey else { return }
if let liked = snapshot.value as? [String: AnyObject] {
for (_, value) in liked {
if value as? String == postId {
cell.likeButton.unlikeButton()
}
}
}
}, withCancel: nil)
ref.removeAllObservers()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 375
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as? PostCell else { return UITableViewCell() }
checkLiked(row: indexPath.row, cell: cell)
cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: #selector(handleLike(_:)), for: .touchUpInside)
cell.configCell(post: posts[indexPath.row])
return cell
}
}
extension UIButton {
func likeButton() {
self.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
self.tintColor = UIColor.mainColor
}
func unlikeButton() {
self.setImage(UIImage(systemName: "hand.thumbsup.fill"), for: .normal)
self.tintColor = UIColor.mainColor
}
}
这里我给点赞按钮添加目标:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as? PostCell else { return UITableViewCell() }
checkLiked(row: indexPath.row, cell: cell)
cell.likeButton.tag = indexPath.row
cell.likeButton.addTarget(self, action: #selector(handleLike(_:)), for: .touchUpInside)
cell.configCell(post: posts[indexPath.row])
return cell
}
我找到了解决方法,问题是视图需要添加到 contentView
而不是 PostCell
代码如下:
import UIKit
class PostCell: UITableViewCell {
let userDataContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let userImgView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.image = UIImage(named: "person.crop.circle.fill")?.maskWithColor(color: UIColor.mainColor)
return iv
}()
let completeNameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
lbl.textColor = UIColor.darkText
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let usernameLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.textColor = UIColor.darkGray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let timestampLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
lbl.textColor = UIColor.gray
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let moreOptionsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
return button
}()
let textViewsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let textViewSeparatorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
return view
}()
let postTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 22, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
return tv
}()
let resourceTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.isEditable = false
tv.font = UIFont.systemFont(ofSize: 18, weight: .medium)
tv.adjustsFontForContentSizeCategory = true
tv.layer.masksToBounds = true
tv.layer.cornerRadius = 16
tv.layer.borderWidth = 0.5
tv.layer.borderColor = CGColor.mainColor
tv.isSelectable = true
return tv
}()
let actionsContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.isUserInteractionEnabled = true
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let likesLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "0"
lbl.textColor = UIColor.mainColor
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.adjustsFontSizeToFitWidth = true
return lbl
}()
let commentsButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bubble.left"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
let bookmarkButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bookmark"), for: .normal)
button.tintColor = UIColor.mainColor
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
return button
}()
override func layoutSubviews() {
super.layoutSubviews()
userImgView.circleImageView()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
contentView.addSubview(userDataContainerView)
userDataContainerView.addSubview(userImgView)
userDataContainerView.addSubview(completeNameLabel)
userDataContainerView.addSubview(usernameLabel)
userDataContainerView.addSubview(moreOptionsButton)
contentView.addSubview(textViewsContainerView)
contentView.addSubview(textViewSeparatorView)
textViewsContainerView.addSubview(postTextView)
textViewsContainerView.addSubview(resourceTextView)
contentView.addSubview(actionsContainerView)
actionsContainerView.addSubview(likeButton)
actionsContainerView.addSubview(likesLabel)
actionsContainerView.addSubview(commentsButton)
actionsContainerView.addSubview(bookmarkButton)
actionsContainerView.addSubview(timestampLabel)
setUpConstraints()
}
func setUpConstraints() {
// needs x, y, h, w anchors
userDataContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
userDataContainerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
userDataContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/5).isActive = true
userDataContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
userImgView.leftAnchor.constraint(equalTo: userDataContainerView.leftAnchor, constant: 8).isActive = true
userImgView.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 8).isActive = true
userImgView.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, constant: -16).isActive = true
userImgView.widthAnchor.constraint(equalTo: userImgView.heightAnchor).isActive = true
// needs x, y, h, w anchors
completeNameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
completeNameLabel.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 4).isActive = true
completeNameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
completeNameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
usernameLabel.leftAnchor.constraint(equalTo: userImgView.rightAnchor, constant: 8).isActive = true
usernameLabel.topAnchor.constraint(equalTo: completeNameLabel.bottomAnchor, constant: 4).isActive = true
usernameLabel.heightAnchor.constraint(equalTo: userDataContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
usernameLabel.widthAnchor.constraint(equalTo: userDataContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, w, anchors
moreOptionsButton.rightAnchor.constraint(equalTo: userDataContainerView.rightAnchor, constant: -16).isActive = true
moreOptionsButton.topAnchor.constraint(equalTo: userDataContainerView.topAnchor, constant: 16).isActive = true
moreOptionsButton.heightAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 1/4, constant: -4).isActive = true
moreOptionsButton.widthAnchor.constraint(equalTo: userImgView.heightAnchor, multiplier: 2/3).isActive = true
// needs x, y, h, w anchors
textViewSeparatorView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewSeparatorView.bottomAnchor.constraint(equalTo: userDataContainerView.bottomAnchor).isActive = true
textViewSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
textViewSeparatorView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
textViewsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
textViewsContainerView.topAnchor.constraint(equalTo: userDataContainerView.bottomAnchor, constant: 12).isActive = true
textViewsContainerView.bottomAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
textViewsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
postTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
postTextView.topAnchor.constraint(equalTo: textViewsContainerView.topAnchor, constant: 4).isActive = true
postTextView.bottomAnchor.constraint(equalTo: resourceTextView.topAnchor, constant: -8).isActive = true
postTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
resourceTextView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
resourceTextView.bottomAnchor.constraint(equalTo: textViewsContainerView.bottomAnchor, constant: -4).isActive = true
resourceTextView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/8).isActive = true
resourceTextView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -32).isActive = true
// needs x, y, h, w anchors
actionsContainerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
actionsContainerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
actionsContainerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1/4).isActive = true
actionsContainerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
// needs x, y, h, w anchors
timestampLabel.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 8).isActive = true
timestampLabel.topAnchor.constraint(equalTo: likeButton.bottomAnchor, constant: 2).isActive = true
timestampLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/3, constant: -8).isActive = true
timestampLabel.widthAnchor.constraint(equalTo: actionsContainerView.widthAnchor, multiplier: 1/2).isActive = true
// needs x, y, h, w anchors
likeButton.leftAnchor.constraint(equalTo: actionsContainerView.leftAnchor, constant: 12).isActive = true
likeButton.topAnchor.constraint(equalTo: actionsContainerView.topAnchor, constant: 16).isActive = true
likeButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likeButton.widthAnchor.constraint(equalTo: likeButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
likesLabel.leftAnchor.constraint(equalTo: likeButton.rightAnchor, constant: 12).isActive = true
likesLabel.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
likesLabel.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
likesLabel.widthAnchor.constraint(equalTo: likesLabel.heightAnchor).isActive = true
// needs x, y, h, w anchors
commentsButton.leftAnchor.constraint(equalTo: likesLabel.rightAnchor, constant: -8).isActive = true
commentsButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
commentsButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
commentsButton.widthAnchor.constraint(equalTo: commentsButton.heightAnchor).isActive = true
// needs x, y, h, w anchors
bookmarkButton.leftAnchor.constraint(equalTo: commentsButton.rightAnchor, constant: 12).isActive = true
bookmarkButton.centerYAnchor.constraint(equalTo: likeButton.centerYAnchor).isActive = true
bookmarkButton.heightAnchor.constraint(equalTo: actionsContainerView.heightAnchor, multiplier: 1/2, constant: -8).isActive = true
bookmarkButton.widthAnchor.constraint(equalTo: bookmarkButton.heightAnchor).isActive = true
}
func configCell(post: Post) {
userImgView.loadImageUsingCacheWithUrlString(urlString: post.userImg!)
completeNameLabel.text = post.userCompleteName
usernameLabel.text = "@\(post.username!)"
if let seconds = post.timestamp?.doubleValue {
let timestampDate = Date(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
self.timestampLabel.text = dateFormatter.string(from: timestampDate)
}
postTextView.text = post.postText
resourceTextView.text = post.postResource
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}