Week 1: Assignment

sun·2021년 9월 26일
1

@ Assignment

  • 수업 때 만들어봤던 Memorize 앱을 몇 가지 수정 사항 + 추가 사항을 곁들여 스크래치로부터 혼자 다시 만들어보는 게 과제였다 수정 사항, 추가 사항은 아래와 같다!

1.  상단에 Memorize! 제목 달기

  • 맞게 한건지는 모르겠는데 Navigation View{}VStack 전체를 감싸준 다음, navigationTitle("Memorize!") 로 제목을 달아줬다.
  • 가운데 정렬을 하고 싶어서 찾아봤는데 UIkit 을 활용해야 한다고 해서 일단 보류...

2.  3개의 테마 버튼 만들기

앱 하단에 서로 다른 3가지 테마의 버튼을 만들고, 매번 버튼을 누를 때마다 카드가 셔플되어 나타나도록 구현하기

  • 처음에는 사실 아이콘과 버튼명을 뺀 구조는 동일하기 때문에 별도의 ThemeButton 구조체를 만들었다. 그러나 버튼을 누름에 따라 emojis 배열을 적절하게 교체해주어야 함에도 불구하고 구조체의 경우 ContenView 내부에 선언하던 외부에 선언하던 @State var emojis 에 접근할 수 없었다.
  • 결국 이러한 문제점을 해결하기 위해 그냥 문제에서처럼 computed property 로 각 버튼을 따로 선언해서 해결했다. 아마도 좀 더 재활용이 가능한 방법이 있을 것 같은데 앞으로 배워나가겠지 싶다.
  • 카드 셔플 메서드 의 경우 구현이 어려울 것 같아 마지막까지 남겨뒀는데 과제 가이드에서 계속 셔플은 생각보다 매우 간단할 수도 있다고 계속 힌트를 줬다. 찾아보니 shuffled() 이라는 내장 함수가 있어서 이를 이용해서 각 버튼에서 emojis 를 해당 버튼의 테마와 일치하는 이모지 배열을 셔플한 것으로 교체해줬다.
    @State var emojis = [//array with emojis]
    
    ...
    
    var vehicleButton: some View {
        VStack {
            Button {
                emojis = vehicleEmojis.shuffled()  // 배열 교체
                emojiCount = Int.random(in: 4...emojis.count)
            } label: {
                VStack {
                    Image(systemName: "car.fill").font(.largeTitle)
                    Text("Vehicles").font(.footnote)
                }
            }
        }
    }

3.   테마 버튼을 누를 때마다 카드 개수가 랜덤으로 바뀌게 하기

  • 가이드에서 Int.random(in: ) 메서드를 활용하면 된다고 해서 원래는 없었던 @State var emojiCount: Int 를 선언했다
  • 각 버튼을 누르면 해당 버튼에서 새롭게 셔플되어 교체된 emojis 배열 의 길이가 최대 나타날 수 있는 카드 개수가 되고, 과제 가이드에서 항상 4개 이상의 카드가 나타나도록 하라고 되어있으므로 각 버튼 내에서 emojiCountInt.random(in: 4..,emojisCount) 으로 업데이트하게 했다.
    @State var emojiCount = // some Int
    
    ...
    
    var vehicleButton: some View {
        VStack {
            Button {
                emojis = vehicleEmojis.shuffled()
                emojiCount = Int.random(in: 4...emojis.count)  // 랜덤 숫자로 교체
            } label: {
                VStack {
                    Image(systemName: "car.fill").font(.largeTitle)
                    Text("Vehicles").font(.footnote)
                }
            }
        }
    }
  • 이렇게 하면 emojiCountForEach[emojis[0..<emojiCount] 에서 subscript range 로 활용되므로 4 ~ 최대 카드 개수 사이의 랜덤한 개수의 카드가 디스플레이 된다.
    ...

    ForEach(emojis[0..<emojiCount], id: \.self) {
        CardView(content: $0).aspectRatio(2/3, contentMode: .fit)
    }

4.   테마 버튼을 누를 때마다 카드 크기가 개수에 비례해 조절되게 하기

  • 가이드에서 func widthThatBestFits(cardCount: Int) -> CGFloat {} 형태로 구현하라고 했다
  • 카드 개수랑 minimum 값을 바꿔가면서 테스트해봤더니 아래 switch 문 과 결과가 같았다 즉, 카드 개수가 4개일 때는 minimun 이 110 ~ 167 사이일 때 스크롤하지 않으면서 카드 크기가 최대이고, 카드 개수가 5 ~ 9개 일때는 minimum 이 80 ~ 109 사이일 때 최적이었다. 그래서 사실 이렇게 구현하는 게 맞는지 모르겠는데 그냥 임의로 최대 24개인 경우까지 해서 사실상 하드코딩하다시피 구현했다
func widthThatBestFits(cardCount: Int) -> CGFloat {
    switch cardCount {
    case 4:
        return 110
    case 5...9:
        return 80
    case 10...16:
        return 63
    default:
        return 62
    }
}


let bestWidth = widthThatBestFits(cardCount: emojiCount) 
LazyVGrid(columns: [GridItem(.adaptive(minimum: bestWidth))])

☀️ 느낀점

  • 일단 combining views 를 적절히 활용할 수 있게 되었다.
  • 그리고 수업을 들으면서 항상 왜 어떤 변수/상수를 특정 scope 에서 정의하는지, 그보다 상위 scope 에서 정의하면 안되는지 궁금했는데, 스스로 실험해본 결과 너무나 당연하지만 해당 변수/상수가 사용되는 가장 상위의 scope 에서 선언하는 게 실행 속도는 물론 깔끔한 코드 작성을 위해 베스트인 것 같다.
profile
☀️

0개의 댓글

관련 채용 정보