iOS Study 1주차 정리

농담고미고미·2025년 3월 20일
0

프론트엔드

목록 보기
8/12
post-thumbnail

많은 걸 배워따 배운건 그때그때 정리해야함!!
일단 파일 구조부터

Xcode에 폰트 추가하는 법: Extension으로 구현한다. enum으로 case들을 선언한다. 해당 폰트를 리턴한다. 그리고 info에 들어가서 폰트들을 추가해줘야 한다. 확장자까지 작성해야함! pretend() 를 보면 타입과 사이즈를 입력 받은 값들로 넣어준다. .custom 모디파이어를 사용한다는 것도 챙겨가자.

import Foundation
import SwiftUI

extension Font {
    enum Pretend {
        case extraBold
        case bold
        case semiBold
        case medium
        case regular
        case light
        
        var value: String {
            switch self {
            case .extraBold:
                return "Pretendard-ExtraBold"
            case .bold:
                return "Pretendard-Bold"
            case .semiBold:
                return "Pretendard-SemiBold"
            case .medium:
                return "Pretendard-Medium"
            case .regular:
                return "Pretendard-Regular"
            case .light:
                return "Pretendard-Light"
            }
        }
    }
    
    static func pretend(type: Pretend, size: CGFloat) -> Font {
        return .custom(type.value, size: size)
    }
    
    static var PretendardExtraBold24: Font {
        return .pretend(type: .extraBold, size: 24)
    }
    
    static var PretendardMedium16: Font {
        return .pretend(type: .medium, size: 16)
    }
    
    static var PretendardRegular12: Font {
        return .pretend(type: .regular, size: 12)
    }
    
    static var PretendardRegular13: Font {
        return .pretend(type: .regular, size: 13)
    }
}

호호 이러면 나중에 폰트 써먹기 편하다. 만약 나는 PretendardRegular13에서 사이즈는 미리 지정하기 싫다! 그때그때 필요한 사이즈를 내가 입력하고 싶다! 면

static func PretendardMedium(size: CGFloat) -> Font {
	return .pretend(type: .medium, size: size)
}

Text("Hello, SwiftUI!")
    .font(.PretendardMedium(size: 16))

와 같이 사용하면 된다. 나는 귀찮아서 컬러도 extension으로 만들어놨당.

이번주는 Model이랑 ViewModel은 작업을 안했고, View를 같이 보자. 역시 View 짜는게 중독적이다.... 크크

쉬운 SplashView 부터

struct SplashView: View {
    var body: some View {
        ZStack {
            Color(.mainGreen)
            
            VStack {
                Image("Starbucks")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 168, height: 168)
            }
        }
        .ignoresSafeArea()
    }
}

딱히 코드라 할게 없음... 배경을 꽉 채우고 싶으면 ZStack을 써야한다. 그리고 .ignoreSafeArea를 해야 꽉 찬다. Image는 resizeable(), scaledToFit(), frame()이 항상 같이 다닌다. 아니면 이미지를 내가 원하는 사이즈로 이쁘게 조절이 안됨.

LoginView()를 보자 두둥. padding이랑 spacing() 갖고 놀기 딱 조았음 항상 헷갈렸는데 이번에 padding, spacing, alignment를 제대로 이해했다.

큰 구조는 제일 큰 VStack 안에 3개의 VStack을 넣었다. 위 사진처럼 첫번째 VStack이 왼쪽에 위치하도록 할려면 제일 큰 VStack(alignment: .leading)를 해야 한다. 제일 큰 VStack의 alignment를 지우면 아래와 같이 첫번째 VStack이 중간에 위치하게 된다. (스유는 기본 정렬이 .center로 되어 있다.)

VStack(alignment: .leading) {
	중간생략
}
.padding(.horizontal, 19)

Spacer()

제일 큰 VStack 여백은 위와 같이 했다. padding(.horizontal, 19)를 해야지 내부 3개의 VStack들에 수평으로 여백이 들어간다. 이때는 Spacer를 쓰면 내가 원하는대로 여백이 안 들어간다.

그럼 내부 VStack들을 하나씩 만들어보자.

/// 🔹 스타벅스 로고 및 텍스트
            VStack(alignment: .leading) {
                Image("Starbucks")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 97, height: 95)
                
                Spacer().frame(height: 28)

                Text("안녕하세요.\n스타벅스입니다.")
                    .font(.PretendardExtraBold24)
                    .foregroundStyle(Color.black)
                    .kerning(1.2)
                    .multilineTextAlignment(.leading)
                    .lineLimit(nil)
                    .fixedSize(horizontal: false, vertical: true) // 높이 고정, 가로는 자동 조정
                
                Spacer().frame(height: 19)


                Text("회원 서비스 이용을 위해 로그인 해주세요")
                    .font(.PretendardMedium16)
                    .foregroundStyle(Color.customGray1)
                    .kerning(-0.8)
            }

이때 VStack에도 alignment: .leading을 해야한다. 이미지와 안녕하세요 사이에 여백은 padding보다 spacer를 사용하는게 좋다. 왜냐하면 padding을 하면 padding까지 포함해서 하나의 요소로 보지만, spacer는 포함되지 않는 개별의 존재로 인식하기 때문이다.

그리고 자간도 맞춰주자. .kerning()으로 자간을 맞출 수 있다. 개행문자로 줄바꿈을 해도 좋지만, 만에 하나 문장이 길어질 때를 대비하여 나는 .multilineTextAlignment()로 넣었다. multilineTextAlignment()와 .lineLimit()은 자주 붙어다니기 때문에 같이 넣어주면 좋다. 왜냐하면 몇줄까지 생략하지 않고 내용을 전부 보여줄건지 결정하는 모디파이어기 때문이다.

.fixedSize(horizontal: false, vertical: true) 도 혹시 기종이 바뀌거나, 앞으로 여백 수치를 수정할 수 있기 때문에 안정적으로 하기 위해 넣었다. 만약 여백 수치가 많이 바뀌면 "안녕하세요 스타벅스입니다"가 "안녕하세요...."로 잘릴 수 있다. 그런 일이 없도록 fixedSize로 수평 사이즈를 수정했다. 그러면 여백 수치 변동이 커도 글자가 잘릴 일을 예방할 수 있다.

그리고 foregroundStyle를 이용해야한다. 원래 foregroundColor()를 썼었는데 차후 foregroundStyle()로 대체될 예정이라고 Apple에서 말했다. 유지보수는 중요하니깐...

위 사진을 보면 1,2,3번째 VStack 사이의 여백이 수치가 정해진게 아니라 "auto"로 되어있다. 그러면 Spacer().frame(수치)가 아닌 Spacer()를 해줘야한다. 그래야 스유에서 알아서 계산해서 여백을 넣는다.

/// 🔹 아이디 & 비밀번호 입력
            VStack(alignment: .leading) {
                Text("아이디")
                    .font(.PretendardRegular13)
                    .foregroundStyle(Color.customBlack)
                    .kerning(-0.65)

                Divider()
                    .offset(y: -5)

                Spacer().frame(height: 47)
                
                Text("비밀번호")
                    .font(.PretendardRegular13)
                    .foregroundStyle(Color.customBlack)
                    .kerning(-0.65)

                Divider()
                    .offset(y: -5)
                
                Spacer().frame(height: 47)

                Button(action: {
                    print("로그인 버튼 클릭")
                }) {
                    Text("로그인하기")
                        .foregroundStyle(.white)
                        .frame(maxWidth: .infinity, minHeight: 46)
                        .background(Color.mainGreen)
                        .cornerRadius(20)
                }
            }

Divider()로 연한 밑줄을 나타냈다. 그런데 자세히 보면 텍스트와 밑줄 사이 미세한 공백이 있다. y축으로 위로 5만큼 올려주면 된다. .offset()으로 나타냈다.

버튼이 중요한데, .frame(maxWidth: .infinity, minHeight: 46) 이건 좋지 못한 방법이다. 왜냐하면 maxWidth: .infinity가 추후에 대체될 예정이기 때문이다. 그럼 어떻게 해야할까...

2가지 방법이 있다. 1번째는 아래의 코드와 같이 HStack 안에 Spacer() 2개를 넣고, frame으로 높이를 지정하는 방법이다.

{
    HStack {
        Spacer() // 좌측 공간 확장
        Text("로그인하기")
            .foregroundStyle(.white)
        Spacer() // 우측 공간 확장
    }
    .frame(height: 46) // 높이만 지정

2번째는 GeometryReader를 이용하는 방법이다. GeometryReader는 부모 뷰의 크기를 읽고 그에 맞게 레이아웃을 조정할 수 있도록 도와주는 역할을 한다.

Button(action: {
                    print("로그인 버튼 클릭")
                }) {
                    GeometryReader { geometry in
                        Text("로그인하기")
                            .foregroundStyle(.white)
                            .frame(width: geometry.size.width, height: 46) // 부모 뷰의 크기만큼 확장
                            .background(Color.mainGreen)
                            .cornerRadius(20)
                    }
                }
                .frame(height: 46) // 높이 고정

웃긴게 마지막 .frame(height: 46) // 높이 고정 을 하지 않으면 높이가 변한다. 위에서 frame으로 높이를 정해줬지만, 다시 한번 .frame을 해줘야하는 것이다. 지우면 아래의 사진처럼 된다.

어이없어... 지멋대로임... 여튼 개인적으로 HStack()으로 버튼의 가로를 정하는 걸 더 선호한다.

세번째 VStacke도 잘 보면 양옆에 같은 크기의 여백이 들어가있다. 따라서 HStack과 Spacer 2개를 이용하면 된다. 이미지 크기도 맞춰주기. 이미지는 pdf를 사용하는게 더 좋다. 당연히 png가 좋다고 생각했는데 pdf가 화질이 더 안 깨진다고 한다.

 /// 🔹 하단 회원가입 & 로그인 버튼
            HStack {
                Spacer()
                
                VStack(spacing: 16) {
                    Text("이메일로 회원가입하기")
                        .font(.PretendardRegular12)
                        .underline()
                        .foregroundStyle(Color.customGray2)
                    
                    Image("KakaoLogin")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 306, height: 45)
                    
                    Image("AppleLogin")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 306, height: 45)
                } // VStack end
                
                Spacer()
            } // HStack end

그리고 사소한 습관으로 각 Stack이 끝날 때마다 // VStack end와 같이 주석을 다는게 좋다. 여러 스택을 쓰다보면 {}지옥에 빠지게 된다... 마치 콜백지옥처럼 어디가 시작이고 어디가 끝인지 알 수 없어지는...

그럼 피그마의 화면과 내가 만든 화면과 얼마나 일치하는지 비교해보자. 아래가 피그마 위가 내가 만든 화면.


profile
농담곰을 좋아해요 말랑곰탱이

0개의 댓글