221125 TIL [SwiftUI의 List와 ForEach(forEach아님!) with Identifiable]

Doogie·2022년 11월 25일
0

List

  • 사용법은 다르지만 UIKit의 TableView와 같은 역할을 함
  • 사용법 매우 간단!
        List {
            Text("안녕")
            Text("그래 안녕")
            Text("잘가")
            Text("그래 잘가")
        }

끝.
dataSource 어쩌고... 채택 어쩌고... 할 필요 없다 그냥 끝임 이 코드가 ㄷㄷ

        List {
            Image("stmarylake")
            Image("chilkoottrail")
            Image("silversalmoncreek")
        }

Text를 image로 바꾸면?

바로 추감됨...(물론 size같은건 직접 일일이 지정해 줄 수도 있고 cell을 만들듯 view객체를 하나 만들어서 사용할 수도 있다)

ForEach

  • SwiftUI의 ForEach는 기존 알고있는 고차함수 forEach와 다름
  • collection을 순회하면서 해당 요소를 View로 반환하기 위해 사용하는듯 하다
    • 공식문서에 의하면 "(id등을 통해) 식별된 데이터의 collection에서 요청하게 되면 뷰를 계산하는 어쩌구 저쩌구..."

사용방법

  • 기본적으로 뷰로 계산될 collection이 data로, 요소들의 식별자가 id로, 어떤 식의 view로 반환할지에 대한 로직이 content로(클로저 형태로) 작성하면 된다
  • id의 경우 collection의 요소들이 Identifiable을 채택한 객체라면 생략 가능

1. Identifiable을 채택하지 않은 요소들의 collection의 경우

    private let messages = ["안녕", "Hello", "안녕하세요", "Hi", "안녕하시와요", "안녕하실꽈"]

위 string배열을 List에 Text로 표시하고자한다면 ForEach를 통해 간단하게 나타낼 수 있다

struct TESTFILE: View {
    private let messages = ["안녕", "Hello", "안녕하세요", "Hi", "안녕하시와요", "안녕하실꽈"]
    
    var body: some View {
        List {
            ForEach(messages, id: \.self) { message in
                Text(message)
            }
        }
    }
}

2. Identifiable을 채택한 요소들의 collection의 경우

struct Message: Identifiable {
    let id = UUID()
    let message: String
    
    private let messages = [Message(message: "안녕"),
                            Message(message: "Hello"),
                            Message(message: "안녕하세요"),
                            Message(message: "Hi"),
                            Message(message: "안녕하시와요"),
                            Message(message: "안녕하실꽈")]
}

위와같이 Message라는 Identifiable을 채택한 객체를 만들어 객체가 생성될 때 마다 UUID생성을 해주는 id프로퍼티를 만들고 메시지는 message프로퍼티를 만들어 할당해주도록 했고 그렇게 만들어진 collection을 messages이다

        List {
            ForEach(messages) { message in
                Text(message.message)
            }
        }

그럼 ForEach구현시에 id를 생략할 수 있다

추가로 List소개에서 다뤘던 이미지들도 imageName만 배열로 만들어 ForEach를 이용하면 한 번에 사이즈를 조절 해 줄 수 있다

        List {
            ForEach(["stmarylake", "chilkoottrail", "silversalmoncreek"], id: \.self) { imageName in
                Image(imageName)
                    .resizable()
                    .scaledToFill()
                    .frame(height: 100)
            }
        }

근데 저 이미지 사이즈 조절하는 수식어 위치에 따라 결과가 다르게 나오는데

    var body: some View {
        List {
            ForEach(["stmarylake", "chilkoottrail", "silversalmoncreek"], id: \.self) { imageName in
                Image(imageName)
                    .resizable()
                    .frame(height: 100) //요기랑
                    .scaledToFill() //요기랑 위치 바꿔봄
            }
        }


frame과 scaledToFill의 위치를 바꾸면 이렇게 나온다

근데 잘 모르겠다 둘다 빌드해봐서 뷰 하이라키 보면 실제로 heightrk 100인건 두 번째인다 흠냐...

profile
끊임없이 문을 여는 개발자

0개의 댓글