Skip to content

7주차 과제#5

Open
sssthnnhee wants to merge 15 commits into
mainfrom
swiftUI
Open

7주차 과제#5
sssthnnhee wants to merge 15 commits into
mainfrom
swiftUI

Conversation

@sssthnnhee
Copy link
Copy Markdown
Collaborator

@sssthnnhee sssthnnhee commented May 29, 2026

🔗 7주차 과제

📄 작업 내용

기본과제

  • 탭바 간 이동 구현구현
  • 가로스크롤뷰 구현

심화과제

  • 스티키 헤더
  • 플로팅뷰
  • Welcome View를 구현해서, 메인 뷰로 넘어가는 네비게이션까지 함께 구현
구현 내용 WelcomeView (네비게이션) SubscribeView (가로스크롤)
GIF

💻 주요 코드 설명 및 Trouble Shooting 🚀

1. WelcomeView 에서 메인 뷰로 넘어가는 네비게이션

 @State private var isShowingMainView = false

Button {
                    isShowingMainView = true
                } label: {

                    Text("메인으로") 
                      // (중략)
                   }


  .navigationDestination(isPresented: $isShowingMainView)
 {
            NavigationBarView()
}

위와 같이 메인뷰(NavigationBarView)로 향하는 코드를 작성하였다.
@State 로 isShowingMainView 라는 값을 감시하고, 버튼을 눌르면 이 값이 true가 되어 NavigationBarView로 이동한다

해당 코드들은 전부 NavigationStack 내부에 있어야하므로

import SwiftUI

@main
struct Watcha_SwiftUIApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                WelcomeView(nickname: "승희")
            }
        }
    }
}

앱의 시작점에서 시작뷰를 네비게이션스택으로 감쌌다
여기에 써주는 게 더 마음에 들었다

근데 안 좋은것이라면 고치겠습니다 ! (네비게이션 이동을 사용하는 뷰에 적는 것이 좋다든가)

2. NavigationBarView 커스텀 탭바

최근에 enum과 case를 좀 많이 봐서 그걸 이용해 작성해볼까 하는 생각도 들었지만,
기존에 내가 작성했던 코드가 배열 기반이고, 이번 과제는 마이그레이션... 느낌이라고 생각해서 그대로 그 방식을 가져왔다

이전에도 탭바를 커스텀하여 사용했었는데, 그때는 UIKit가 제공하는 UITabBarController 를 상속받는 것으로 버튼의 상태를 관리했다.

그러나 SwiftUI에는 !!! 상태 관리를 해주는 @State가 떡하니 있으니!!!!! 얘가 바뀔때마다 화면을 새로 그려주니!!
딱히 뭘 상속받지 않고도 훨씬 쉽게 만들 수 있을 것 같았다.

   @State private var selectedIndex = 0

    private let selectedImages = ["nav1", "nav2", "nav3", "nav4", "nav5"]

// (중략)

 private var selectedView: some View {
        Group {
            if selectedIndex == 0 {
                SubscribeTabView()
            } else if selectedIndex == 1 {
                EmptyTabView(title: "개별 구매")
            } else if selectedIndex == 2 {
                EmptyTabView(title: "웹툰")
            } else if selectedIndex == 3 {
                EmptyTabView(title: "찾기")
            } else {
                EmptyTabView(title: "보관함")
            }
        }
    }

끝..
선택된 인덱스를 감시하고, 그에 따라 보여줄 뷰를 연결해줬다

저 Group 이라는 건 레이아웃에 영향을 주지않는 논리적 묶음 이라고 한다
처음에 Group 없이 작성하려고 햇는데 자꾸 에러가 나서 추가했다 ( 지피티가 각 분기를 서로 다른 타입의 뷰로 봐서? 생길수있는 에러라고 했다 )

그리고 이미지배열 (에셋 네이밍 여전히 nav라서 죄송합니다) 가져와서 탭바 모양 만들고 선택상태에 따라서 tint 처리 해주면 정말 끝

if index != selectedImages.count - 1 {
                        Spacer()

위 코드는 이미지 + Spacer()를 반복하는 코드에서 맨 마지막거엔 안 넣기 위한 코드인데
하드코딩 안하고 저렇게 해본것이 조금 뿌듯해서 적어봤습니다

3. SubscribeTabView 메인 뷰

가로스크롤뷰에 스크롤 시작점을 지정하는 코드를 넣었다
ScrollView를 ScrollViewReader 로 감싸주고 .onAppear 를 통해 어떤 id의 요소를 어떻게 보여주고 싶은지 지정하면 된다

ScrollViewReader { startPoint in

// 중략

 .onAppear {
                startPoint.scrollTo(1, anchor: .center)

메인 포스터 스크롤뷰와 가로 포스터 스크롤뷰가 2번째것이 가운데에 와있는것 같아서 설정해두었다.
지금은 몇 개 없어서 그냥 모델에 identifiable 을 채택하고 id를 그냥 Int로 줬는데
나중에 데이터가 많아지면 UUID로 아이디를 만들고 scrollTo에 PosterModel.mPosters[1].id 라고 주면 좋을 것 같다

위 가로스크롤뷰는 따로 SubscribeTabScrollView 파일에 분리해두었는데,
시간이 부족하여 헤더는 컴포넌트화 하지 못했다

그치만,
덕분에 더 크게 느낄 수 있었다...

swiftUI는 정말 코드를 1/2 수준으로 줄여서 작성할 수 있구나.. 정말 편하구나
중복된 코드를 적어도 그렇게 길어지지 않고... 생각하는대로 코드를 적어도 어느 정도 구현이 되고,
프리뷰를 통해 바로바로 화면을 확인할 수 있고... 만약 이번 과제가 UIKit였으면 절대 시간안에 못했을 것 같다

KakaoTalk_Photo_2026-05-06-01-32-08-removebg-preview

👀 To Reviewers

스유를 아랑하게 된 나는 모든 것을 받아들일 준비가 되었소

@sssthnnhee sssthnnhee self-assigned this May 29, 2026
Copy link
Copy Markdown

@hemssy hemssy left a comment

Choose a reason for hiding this comment

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

7주차 과제 고생하셨습니다!! ✨😚😚


import SwiftUI

struct mainStack : View{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기 구조체 이름이 소문자 시작인데 다른파일은 대문자시작이어서 여기도 대문자로 맞추면 좋을것같아요!!


ScrollViewReader { startPoint in

ScrollView(.horizontal) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

저도 이번에 과제하면서 알았는데
ScrollView(.horizontal, showsIndicators: false) {
이렇게 속성붙이면 가로스크롤할때 나오는 인디케이터가 숨겨져용


extension PosterModel {
static let mPosters: [PosterModel] = [
PosterModel(id: 0, posterImage: .t1),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기

struct PosterModel: Identifiable {
    let id = UUID()
    let posterImage: ImageResource
}

이렇게 uuid 쓰면 더 깔끔할것같아요~

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

동의합니다 !!


struct SubscribeTabView: View {

var body: some View {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기 body가 조금 긴것같은데

private var headerView: some View
private var newContentSection: some View
private var watgorythmSection: some View
private var upcomingSection: some View
private var partySection: some View

이렇게 나누면 더 깔끔해질것같아요!! 개인적인 생각입니닷

Copy link
Copy Markdown

@gleamminn gleamminn left a comment

Choose a reason for hiding this comment

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

마지막 과제 너무 고생 많았어용 !!! 코드 너무 좋네요 😍

.font(.head2)
.foregroundStyle(.WATCHA_WHITE)

Image("mandoo")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

애니메스터디 세계관 좋다


extension PosterModel {
static let mPosters: [PosterModel] = [
PosterModel(id: 0, posterImage: .t1),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

동의합니다 !!

import SwiftUI

struct PosterModel: Identifiable {
let id: Int
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

id를 사용한 이유가 궁금합니다 !

Comment on lines +29 to +30
.onAppear {
startPoint.scrollTo(1, anchor: .center)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

좋네요 !!! 왕초스때 설명해준 부분이군용

Comment on lines +101 to +109
VStack(alignment: .leading) { Text("오늘 22:02에 시작")
.font(.body1)
.foregroundStyle(.WATCHA_PINK)
.padding(.bottom,6)

Text("#왕가사는남자")
.font(.subhead3)
.foregroundStyle(.WATCHA_WHITE)}
Spacer()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

하드코딩 되어있는 부분 지워주는게 좋을 것 같아용


Spacer()

Image("Video")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.으로 접근 가능합니당

Comment on lines +61 to +75
HStack{

VStack(alignment: .leading) {

Text("방금 막 도착한 신상 컨텐츠")
.font(.head3)
.foregroundStyle(.WATCHA_WHITE)

Text("예능부터 드라마까지!")
.font(.subhead1)
.foregroundStyle(.GRAY_200)
}
Spacer()
}
.padding(.leading, 24)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

반복되는 헤더 부분 컴포넌트로 만드는게 좋을 것 같아요!

Comment on lines +85 to +87
#Preview {
NavigationBarView()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

프리뷰는 항상 지워주긔

var body: some Scene {
WindowGroup {
NavigationStack {
WelcomeView(nickname: "승희")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

닉네임까지 변수로 설정해둔 센스 !!

Comment on lines +16 to +18
private var displayName: String {
nickname ?? "익명의 사용자"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

너무 좋아요 !!!!!

Copy link
Copy Markdown

@dearosmar dearosmar left a comment

Choose a reason for hiding this comment

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

너무 고생하셨습니다!!!
스텍 구조 너무 좋은 것 같아요

selectedView
.padding(.bottom, 99)

customNavigationBar
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

여기서는 그냥 불러 주는 건가요?!

private var selectedView: some View {

Group {
if selectedIndex == 0 {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

엇 이렇게 인덱스 주는 거 좋은 것 같아요

.scaledToFit()
.frame(width: 100, height: 100)

Text(" . . 텅 ~")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

텅~~

struct posterStack : View {

var body: some View {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

요기 공백을 줄 거면 전체적으로 같이 주는 게 좋을 것 같습니당!

HStack {
Text("구독")
.font(.head1)
.foregroundStyle(.WATCHA_WHITE)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

보통 에셋 파일 컬러는 lowercamelcase로 주는 것 같습니다!

@State private var isShowingMainView = false

private var displayName: String {
nickname ?? "익명의 사용자"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

너무 멋져요

}
}

#Preview {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

프리뷰 지워 주면 좋을 것 같슴당


import SwiftUI

struct mainStack : View{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

stack들이 위치만 다르고 구조가 거의 비슷해서 파라미터로 받아 주는 것도 좋을 것 같아요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants