구현 화면

구현 순서
- 트윗 액션에 따른 버튼 생성
- 델리게이트 패턴을 사용하여 각 버튼의 액션 별 전달데이터 설정
TweetTableViewCell.swift
- 트윗 버튼 생성
- 델리게이트 패턴 사용 목적으로 프로토콜 선언
- 데리게이트 패턴을 사용하기 위한 대리자 선언
- 각 버튼을 누르면 동작하는 델리게이트 함수 설정
import UIKit
// 데이터 전달 목적으로 델리게이트 패턴 사용 - 프로토콜 선언 - 1
protocol TweetTableViewCellDelegate: AnyObject {
func tweetTableViewCellDidTapReply()
func tweetTableViewCellDidTapRetweet()
func tweetTableViewCellDidTapLike()
func tweetTableViewCellDidTapShare()
}
class TweetTableViewCell: UITableViewCell {
static let identifier = "TweetTableViewCell"
private let actionSpacing: CGFloat = 60
// 대리자 선언 - 2
weak var delegate: TweetTableViewCellDelegate?
private let avatarImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 25
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
imageView.image = UIImage(systemName: "person")
imageView.backgroundColor = .green
return imageView
}()
private let displayNameLabel: UILabel = {
let label = UILabel()
label.text = "Explorer"
label.font = .systemFont(ofSize: 18, weight: .bold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let userNameLabel: UILabel = {
let label = UILabel()
label.text = "@Explorer"
label.textColor = .secondaryLabel
label.font = .systemFont(ofSize: 12, weight: .regular)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let tweetTextContentLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was bo"
label.numberOfLines = 0
return label
}()
private let replyButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "bubble.left"), for: .normal)
button.tintColor = .gray
return button
}()
private let retweetButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "arrow.2.squarepath"), for: .normal)
button.tintColor = .gray
return button
}()
private let likeButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "heart"), for: .normal)
button.tintColor = .gray
return button
}()
private let shareButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "square.and.arrow.up"), for: .normal)
button.tintColor = .gray
return button
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(avatarImageView)
contentView.addSubview(displayNameLabel)
contentView.addSubview(userNameLabel)
contentView.addSubview(tweetTextContentLabel)
contentView.addSubview(replyButton)
contentView.addSubview(retweetButton)
contentView.addSubview(likeButton)
contentView.addSubview(shareButton)
configureConstraints()
configureButtons()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configureConstraints() {
let avatarImageViewConstraints = [
avatarImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
avatarImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 14),
avatarImageView.heightAnchor.constraint(equalToConstant: 50),
avatarImageView.widthAnchor.constraint(equalToConstant: 50)
]
let displayNameLabelConstraints = [
displayNameLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 20),
displayNameLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20)
]
let userNameLabelConstraints = [
userNameLabel.leadingAnchor.constraint(equalTo: displayNameLabel.trailingAnchor, constant: 10),
userNameLabel.centerYAnchor.constraint(equalTo: displayNameLabel.centerYAnchor)
]
let tweetTextContentLabelConstraints = [
tweetTextContentLabel.leadingAnchor.constraint(equalTo: displayNameLabel.leadingAnchor),
tweetTextContentLabel.topAnchor.constraint(equalTo: displayNameLabel.bottomAnchor, constant: 10),
tweetTextContentLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15),
//tweetTextContentLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10)
]
let replyButtonConstraints = [
replyButton.leadingAnchor.constraint(equalTo: tweetTextContentLabel.leadingAnchor),
replyButton.topAnchor.constraint(equalTo: tweetTextContentLabel.bottomAnchor, constant: 10),
replyButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10)
]
let retweetButtonConstraints = [
retweetButton.leadingAnchor.constraint(equalTo: replyButton.trailingAnchor, constant: actionSpacing),
retweetButton.centerYAnchor.constraint(equalTo: replyButton.centerYAnchor)
]
let likeButtonConstraints = [
likeButton.leadingAnchor.constraint(equalTo: retweetButton.trailingAnchor, constant: actionSpacing),
likeButton.centerYAnchor.constraint(equalTo: replyButton.centerYAnchor)
]
let shareButtonConstraints = [
shareButton.leadingAnchor.constraint(equalTo: likeButton.trailingAnchor, constant: actionSpacing),
shareButton.centerYAnchor.constraint(equalTo: replyButton.centerYAnchor)
]
NSLayoutConstraint.activate(avatarImageViewConstraints)
NSLayoutConstraint.activate(displayNameLabelConstraints)
NSLayoutConstraint.activate(userNameLabelConstraints)
NSLayoutConstraint.activate(tweetTextContentLabelConstraints)
NSLayoutConstraint.activate(replyButtonConstraints)
NSLayoutConstraint.activate(retweetButtonConstraints)
NSLayoutConstraint.activate(likeButtonConstraints)
NSLayoutConstraint.activate(shareButtonConstraints)
}
// 버튼을 눌렀을 때 동작하는 함수 - 3.
@objc private func didTapReply() {
delegate?.tweetTableViewCellDidTapReply()
}
@objc private func didTapRetweet() {
delegate?.tweetTableViewCellDidTapRetweet()
}
@objc private func didTapLike() {
delegate?.tweetTableViewCellDidTapLike()
}
@objc private func didTapShare() {
delegate?.tweetTableViewCellDidTapShare()
}
private func configureButtons() {
replyButton.addTarget(self, action: #selector(didTapReply), for: .touchUpInside)
retweetButton.addTarget(self, action: #selector(didTapRetweet), for: .touchUpInside)
likeButton.addTarget(self, action: #selector(didTapLike), for: .touchUpInside)
shareButton.addTarget(self, action: #selector(didTapShare), for: .touchUpInside)
}
}
HomeViewController.swift
- TweetTableViewCellDelegate 프로토콜 준수
- 포로토콜 내의 함수 쿠체화
- cell의 delegate를 HomeViewController로 선언
import UIKit
class HomeViewController: UIViewController {
private let timelineTableView: UITableView = {
let tableView = UITableView()
tableView.register(TweetTableViewCell.self, forCellReuseIdentifier: TweetTableViewCell.identifier)
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(timelineTableView)
timelineTableView.delegate = self
timelineTableView.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
timelineTableView.frame = view.bounds
}
}
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: TweetTableViewCell.identifier, for: indexPath) as? TweetTableViewCell else { return UITableViewCell()
}
// 델리게이트 패턴에 대한 대리자를 HomeViewController 설정
cell.delegate = self
return cell
}
}
extension HomeViewController: TweetTableViewCellDelegate {
func tweetTableViewCellDidTapReply() {
print("tweetTableViewCellDidTapReply() - called")
}
func tweetTableViewCellDidTapRetweet() {
print("tweetTableViewCellDidTapRetweet() - called")
}
func tweetTableViewCellDidTapLike() {
print("tweetTableViewCellDidTapLike() - called")
}
func tweetTableViewCellDidTapShare() {
print("tweetTableViewCellDidTapShare() - called")
}
}
TIL
- 어떤 문제가 있었는지?
- TweetTableViewCell 에서 받은 입력을 HomeViewController를 통해 받아보려고 함
- 어떻게 해결했는지
- 델리게이트 패턴을 통해 TweeTableViewCell에서 받은 입력을 처리하기 위한 대리자 역할을 HomeViewController 로 선언함
⭐️ 델리게이트 패턴 설명 ⭐️

- 위의 이미지에서 사각형 내에 버튼을 누르면 기능이 실행되게 한다.
- 먼저 프로토콜을 생성한다. 이때 프로토콜 내에는 어떤 기능에 대한 이름 정도만 생성한다.
- 예를 들면 레시피 정도? 라고 생각하면 된다.

- TweeTableViewCellDelegate 프로토콜을 준수하는 delegate 라는 변수 선언한다.
- 이때 delegate는 TweetTableViewCell 이라는 음식의 주문서 양식을 생성한다고 생각한다.

- TweetTableViewCell 내의 버튼에 맞는 함수를 설정한다.
- 각 버튼을 누르면 해당 요리 주문서 양식에 맞게 주문을 넣는다고 보면 된다.

- HomeViewController은 TweetTableViewCellDelegate 프로토콜을 준수하고, 각 함수를 구체화한다.
- HomeViewController라는 요리사는 TweetTableViewCellDelegate라는 한식 카테고리 내에 각 요리에 대한 레시피를 작성한다고 생각하면 된다.

⭐️⭐️⭐️ TweetTableViewCell 에서 작성한 주문서를 HomeViewController 라는 요리사가 받았다는 걸 보여줘야 한다. ⭐️⭐️⭐️

https://youtu.be/Kb1Tx5R0fXA?si=Y1_PdGogFrm8OgY6
'Clone App > Twitter' 카테고리의 다른 글
[Twitter Clone] Add Indicator button in profile view (0) | 2024.05.27 |
---|---|
[Twitter Clone] Continue implementing the profile view (0) | 2024.05.27 |
[Twitter Clone] Add logo, Design ProfileView (0) | 2024.05.26 |
[Twitter Clone] Add a custom cell (0) | 2024.05.24 |
[Twitter Clone] Setup the basic layout (0) | 2024.05.23 |