해커톤에서 느낀 SwiftUI VStack에 관해 알아야 할 점

0

서론

해커톤 참여 중 구현하려 했던 카드 요소이다.

먼저 VStack으로 위 이미지 부분과 아래 텍스트 + 버튼 부분을 나눈 후 이미지 부분은 ZStack으로 Image와 HStack을 사용하여 구현하려고 했다.

하지만 해당 요소의 구현이 거의 끝나갈 때 쯤 XCode에서 처음 보는 에러가 났다.

“Expression was too complex to be solved in reasonable time”

구글링을 좀 해보니 한마디로 코드가 너무 복잡하니 여러 부분으로 나누라는 말이었다.

해커톤이란 특수한 환경에서 처음 마주하는 상황이라 매우 당황했었고 부족한 시간 탓인지 도저히 어떻게 나눠야 할 지 생각이 나지 않았다. 또한 우리팀은 디자인 패턴을 도입하지 않고 뷰마다 한명이 담당하여 짜기로 했기 때문에 이제야 와서 프로젝트 폴더 구조를 바꿀 수도 없는 노릇이었다.

적지않은 시간을 투자하며 서브뷰로 빼보며 리팩토링을 해보았지만 결과적으로 해당 뷰 부분은 (약 100줄의 코드를 눈물을 머금고...) 이미지로 처리하게 되었다.

본론

위와 같은 에러를 만나면서 새로운 사실을 알게 되었다. VStack은 (HStack, ZStack 마찬가지) 칠드런으로 최대 10개의 View만 허용하며 대체제로는 Group이 있다는 것이다.

그렇다면 VStack을 Group으로 싹 대체하면 되는게 아닌가? 아니었다. 바꿨음에도 불구하고 에러는 없어지지 않았다.

결론

SwiftUI로 복잡한 View를 짜야한다면 처음부터 세밀하게 컴포넌트화 시켜 빌딩블록을 잘 만들어놔야 할 것 같다.
아니면 디자인 패턴을 사용하여 View와 BusinessLogic을 잘 분리하던가...!

Source Code


struct CardLists: View {
    @Binding var fundings: [Funding]
    var body: some View {
        ForEach(fundings, id: \.self) { funding in
            //        ForEach(0..<6){ idx in
            //add selected filtering
            VStack(alignment: .leading){
                //imagegraph view
                ZStack(alignment: .bottomLeading){
                    Image(funding.media).resizable()
                        .frame(width: .infinity, height: 178)
                        .cornerRadius(8)

                    HStack{
                        VStack{
                            Text(funding.milestones[0].what).foregroundColor(.white).font(.bargraphLarge)
                            Text(funding.milestones[0].who).foregroundColor(.white).font(.bargraphSmall)

                            Image(systemName: "checkmark")
                                .foregroundColor(funding.milestones[0].isDone ? .white : .blue)
                                .foregroundColor(.white)
                                .font(.bargraphLarge)
                                .padding(4)
                                .background(funding.milestones[0].isDone ? .blue : .cyan)
                                .background(.white)
                                .clipShape(Circle())


                        }
                        VStack{
                            Text(funding.milestones[1].what).foregroundColor(.white).font(.bargraphLarge)
                            Text(funding.milestones[1].who).foregroundColor(.white).font(.bargraphSmall)

                            Image(systemName: "checkmark")
                                .foregroundColor(funding.milestones[1].isDone ? .white : .blue)
                                .foregroundColor(.blue)
                                .font(.bargraphLarge)
                                .padding(4)
                                .background(funding.milestones[1].isDone ? .blue : .cyan)
                                .background(.cyan)
                                .clipShape(Circle())


                        }
                        VStack{
                            Text(funding.milestones[2].what).foregroundColor(.white).font(.bargraphLarge)
                            Text(funding.milestones[2].who).foregroundColor(.white).font(.bargraphSmall)
                        }


                    }

                }.background(.black.opacity(0.3))


                //card
                HStack {
                    VStack(alignment: .leading) {
                        Text(funding.title).font(.title3)

                        Text(funding.description).font(.custombody2)
                            .foregroundColor(.gray)
                    }
                    Spacer()
                    VStack{
                        Button {
                            //                                        funding.isFavorite.toggle()

                        } label: {
                            Image(systemName: funding.isFavorite ? "heart.fill" : "heart").foregroundColor(.teal)
                        }
                        Spacer()
                        NavigationLink {
                            FundingDetailView()


                        } label: {
                            Text("함께하기")
                                .font(.body)
                                .foregroundColor(.teal)
                                .padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
                                .overlay(
                                    RoundedRectangle(cornerRadius: 30)
                                        .stroke(Color.teal, lineWidth: 2)
                                )
                        }.padding(4)
                    }
                }
            }.padding(EdgeInsets(top: 10, leading: 0, bottom: 0, trailing: 0))
        }
    }
}



1개의 댓글

comment-user-thumbnail
2023년 4월 26일

정말 속상한 발견이네요...

답글 달기