Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
// Created by 최정인 on 11/19/25.
//

import Combine
import SnapKit
import UIKit

final class ReportCompleteViewController: UIViewController {
final class ReportCompleteViewController: BaseViewController<ReportDetailViewModel> {
private enum Layout {
static let horizontalMargin: CGFloat = 20
static let completeImageViewTopSpacing: CGFloat = 78
Expand Down Expand Up @@ -65,15 +66,27 @@ final class ReportCompleteViewController: UIViewController {
private let descriptionLabel = UILabel()
private let photoStackView = UIStackView()
private let confirmButton = PrimaryButton(buttonState: .default, buttonTitle: "확인")
private let reportId: Int
private var cancellables: Set<AnyCancellable> = []

init(viewModel: ReportDetailViewModel, reportId: Int) {
self.reportId = reportId

super.init(viewModel: viewModel)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()
configureAttribute()
configureLayout()
fetchReport()
viewModel.action(input: .fetchReportDetail(reportId: reportId))
}
Comment on lines 83 to 88
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

configureAttribute/configureLayout가 두 번 호출될 가능성이 있습니다.

BaseViewControllerviewDidLoad()에서 이미 configureAttribute(), configureLayout(), bind()를 호출하는 패턴이라면, Line 84–85에서 직접 다시 호출하면서 서브뷰 중복 추가·제약 중복 설정이 발생할 수 있습니다. 실제로 레이아웃 쪽은 두 번 도는 순간 Auto Layout 경고나 예기치 않은 뷰 계층 구조가 생길 수 있습니다.

이 컨트롤러도 ReportDetailViewController와 동일하게 super.viewDidLoad() 이후에는 액션만 호출하도록 정리하는 편이 안전해 보입니다.

 override func viewDidLoad() {
     super.viewDidLoad()
-    configureAttribute()
-    configureLayout()
     viewModel.action(input: .fetchReportDetail(reportId: reportId))
 }
🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Report/View/ReportCompleteViewController.swift
around lines 82–87, remove the duplicate calls to configureAttribute() and
configureLayout() in viewDidLoad() because BaseViewController already invokes
those (and bind()), which can cause duplicate subview additions and constraint
warnings; keep super.viewDidLoad() and only call the report fetch action
(viewModel.action(input: .fetchReportDetail(reportId: reportId))), or
alternatively guard against double-initialization if BaseViewController behavior
changes.


private func configureAttribute() {
override func configureAttribute() {
view.backgroundColor = .white
scrollView.showsVerticalScrollIndicator = false

Expand Down Expand Up @@ -105,7 +118,7 @@ final class ReportCompleteViewController: UIViewController {
photoStackView.spacing = Layout.photoStackViewSpacing
}

private func configureLayout() {
override func configureLayout() {
let safeArea = view.safeAreaLayoutGuide

view.addSubview(scrollView)
Expand Down Expand Up @@ -171,8 +184,30 @@ final class ReportCompleteViewController: UIViewController {
}
}

private func bind() {
fetchReport()
override func bind() {
viewModel.output.reportDetailPublisher
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] reportDetail in
guard let reportDetail else { return }

self?.titleLabel.text = reportDetail.title
self?.categoryLabel.text = reportDetail.category.name
self?.locationLabel.text = reportDetail.location
let descriptionText = reportDetail.description
self?.descriptionLabel.attributedText = BitnagilFont(style: .body1, weight: .medium)
.attributedString(text: descriptionText, alignment: .right)

for photoURL in reportDetail.photoUrls {
guard
let photoView = self?.makePhotoView(),
let url = URL(string: photoURL)
else { continue }

photoView.kf.setImage(with: url)
self?.photoStackView.addArrangedSubview(photoView)
}
})
.store(in: &cancellables)
}

private func makeContentView(contentType: ReportCompleteContent) -> UIView {
Expand Down Expand Up @@ -223,25 +258,8 @@ final class ReportCompleteViewController: UIViewController {
return contentContainerView
}

// TODO: 추후 ViewModel로 옮기기
private func fetchReport() {
titleLabel.text = "가로등이 깜박거려요."
categoryLabel.text = "교통시설"
locationLabel.text = "서울특별시 강남구 삼성동"
let descriptionText = "150자 내용 채우기"
descriptionLabel.attributedText = BitnagilFont(style: .body1, weight: .medium)
.attributedString(text: descriptionText, alignment: .right)

let photoView1 = makePhotoView()
let photoView2 = makePhotoView()
let photoView3 = makePhotoView()
[photoView1, photoView2, photoView3].forEach {
photoStackView.addArrangedSubview($0)
}
}

private func makePhotoView() -> UIView {
let photoView = UIView()
private func makePhotoView() -> UIImageView {
let photoView = UIImageView()
photoView.backgroundColor = BitnagilColor.gray30
photoView.layer.masksToBounds = true
photoView.layer.cornerRadius = 6
Expand Down
Loading