ios 21일차

bin·2026년 1월 27일

회고

오늘은 필수 구현 과제6에 대해 작성을 하고 구현을 하며 고려했던 사항, 겪었던 문제점들을 기록하고자 한다.

과제에 관한 기록

구현 6

  • 시리즈 순서 중 원하는 권수의 책 정보를 볼 수 있도록 구성하라.

ViewController.swift 수정

기존에는 기본적으로 버튼 하나만을 생성했었다. 그러나 시리즈 버튼의 개수를 data.json의 attributes의 개수에 맞게 동적으로 표시하고자 했으며, 이 버튼들을 하나로 담아두는 stackView를 사용했다

  • 기존
seriesButton.setTitle("1", for: .normal)
seriesButton.setTitleColor(.white , for: .normal)
seriesButton.titleLabel?.font = .systemFont(ofSize: 16)
seriesButton.backgroundColor = .systemBlue
seriesButton.layer.cornerRadius = 8

[titleText, seriesButton, scrollView].forEach { view.addSubview($0) }

seriesButton.snp.makeConstraints {
			$0.centerX.equalToSuperview()
            $0.top.equalTo(titleText.snp.bottom).offset(16)
            $0.width.equalTo(seriesButton.snp.height) // height에 width 고정 -> 가로, 세로 비율 유지
}
  • 수정
seriesStackView.axis = .horizontal
seriesStackView.spacing = 6
seriesStackView.distribution = .fillEqually
seriesStackView.alignment = .center

[titleText, seriesStackView, scrollView].forEach { view.addSubview($0) }

seriesStackView.snp.makeConstraints {
            $0.centerX.equalToSuperview()
            $0.top.equalTo(titleText.snp.bottom).offset(16)
}

-stackView 내부 버튼 생성, 속성 정의, 동작

// 버튼 관련 메소드 관리
extension ViewController {

    // 기존 : 버튼 1개 생성 -> 배열로 받아와서 개수만큼 버튼 생성
    private func setSeriesButton(with books: [Book]) {

        // 기본 버튼 생성, 속성 정의
        for idx in books.indices {
            let button = SeriesButton()
            button.setTitle("\(idx + 1)", for: .normal)
            button.setTitleColor(.systemBlue, for: .normal)
            button.titleLabel?.font = .systemFont(ofSize: 16)
            button.backgroundColor = .systemGray5
            button.tag = idx
            button.addTarget(self, action: #selector(seriesButtonTapped(_:)), for: .touchDown)

            button.snp.makeConstraints {
                $0.width.equalTo(button.snp.height)
            }
            seriesStackView.addArrangedSubview(button)
            seriesButtons.append(button)
        }
    }

    // 버튼을 눌렀을 때, 동작하는 메서드 정의
    @objc
    private func seriesButtonTapped(_ sender: SeriesButton) {
        let idx = sender.tag
        let book = books[idx]

        infoUpdate(with: book)
        self.scrollView.setContentOffset(.zero, animated: false) // 스크롤 위치 초기화
        selectedSeriesButton(idx)

    }

    // 버튼 눌렸을 때 상태 변화 메서드 정의
    private func selectedSeriesButton(_ selectedSeriesIdx: Int) {
        for (idx, btn) in seriesButtons.enumerated() {
            btn.backgroundColor = (idx == selectedSeriesIdx) ? .systemBlue : .systemGray5

            let titleColor: UIColor = (idx == selectedSeriesIdx) ? .white : .systemBlue
            btn.setTitleColor(titleColor, for: .normal)
        }
    }
}

생각

문제의 요구사항에 맞게(이후 확인한 조금 놓친 부분들이 있지만), 구현을 완료했다. 지금까지의 구현을 하며 문제를 겪었던 부분들과 이해를 요했던 것들을 정리하자.

1. data.json 파싱을 위한 DataInfo.swift(Model) 생성

  • 구상안

    데이터는 data[attributes[ @@@@@@@@@]]로 존재한다.
    그러므로 객체를 3개로 생성해야 함
    data를 담는 BookResponse
    attributes를 담는 BookData
    title, author, pages, releaseDate, summary, dedication, chapters[]를 담는 Book
    조건 : releaseDate는 data.json에서 release_date로 존재함.
    그러므로 enum을 사용하여 releaseDate = “release_date” 로 데이터 넣어주기
    또한 Book 구조체 내부의 chapters는 배열로 넘어오기에 Chapter 구조체 생성 내부는 title
    불러온 데이터 사용
    BookInfoStackView.swift -> title, author, releaseDate, pages
    BookSummaryStackView.swift -> summary,dedication
    BookChapterStackView.swift -> forEach를 사용하여 chapter.title를 StackView에 넣기

  • 의문점 : 꼭 이렇게 계층형으로 객체를 생성하여 데이터를 받아야하는가?

2. 시리즈 버튼 생성

ViewController.swift에서 seriesButton을 배열로 생성
setSeriesButton 메소드 생성
Book 배열을 books로 받아와서 books.indices 만큼 반복을 진행하여 버튼 생성 -> StackView에 넣기
생성 시에 button.tag를 사용하여 각각에 인덱스 값을 입력하여 생성
버튼 눌렀을 때 동작 : seriesButtonTapped 메소드를 생성하여 sender(button의 tag를 인덱스로 받아서 책의 정보를 전환, 스크롤 위치 초기화, selectedSeriesButton 메소드를 정의하고 사용하여 색상 변화

  • 고려사항 : ViewController.swift 내부에서 필요한 요소인가 ?

3. delegate 사용

BookSummaryStackView.swift에서 접기/더보기 기능을 구현하였으며, 이 정보는 UserDefaults에 저장되어야 한다. 현재의 코드에서는 클로져를 사용하여 구현하였으나, delegate를 사용하여 구현할 수 있는데, 어떻게 적용할 것인가?

  • 구상안

    BookSummaryStackView에 protocol 생성( Delegate)
    onTapExtraButton(isFolded: Bool) 메소드 생성
    클래스 본체에 weak var deleagte: BookSummaryStackViewDelegate? 선언 : 보고 받을 대상 변수 생성
    ViewController의 configUI에 bookSummaryStackView.delegate = self 선언 : 보고 받을 대상 지정
    protocol 메서드 onTapExtraButton 내부 동작 명세 (기존 코드 사용 -> book.title은 사용할 수 없음 : 버튼이 눌리는 시점에 보고를 받음 고로 titleTex.text를 저장, 삭제)

4. titleImage 동적 랜더링

기본 구현에서 깜빡했던 titleImage를 동적으로 랜더링하는 코드를 어떻게 구성할 것인가? titleImage에 대한 정보는 data.json에서 제공하지 않음.

  • 구상안

    버튼을 눌렀을 때 동작하는 메소드인 seriesButtonTapped에서 sender(SeriesButton)의 tag를 idx로 저장하고 있으므로, infoUpdate를 호출할 때 book과 함께 idx를 넘겨주도록 구현. 또한, 화면에 표시되는 titleImage는 UIImage(named: "harrypotter(idx +1)")로 선언하여 asset에 있는 이미지에 연결

5. releaseDate 형식 변경

기본적으로 넘어오는 release_date(String 타입, yyyy-MM-dd 형태)를 MMMM(July) d, yyyy 형태로 변경해야 함.

  • 구상안

    받아온 String 타입의 releaseDate를 Date 타입으로 변경 후 yyyy-MM-dd 형식을 MMMM d, yyyy 형식으로 변경함(Date 타입) 또한, Locale(identifier: "en_US")를 사용하여 July 형태로 표시 이후 String타입으로 다시 변환하여 return

  • 고려사항 : String -> Date -> String 형식 변환이 많은데, 불필요하지 않나 ?

6.ViewController.swift 분리

해당 내용은 내일 정리할 것이다.

0개의 댓글