Devlog
article thumbnail
Published 2021. 8. 23. 06:28
[SwiftUI fundamental Tutorial] List 강의/etc

위 글은 유튜브 정대리님의 SwiftUI fundamental Tutorial 강좌를 보고 작성한 정리글로

자세한 내용은 유튜브를 통해 확인하시길 권장합니다. 

 

 

 

SwiftUI의 List는 UIKit에서 사용한 TableView, CollectionView와 같다고 보면 됨

 

 

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            Text("MY LIST")

        }
        
    }
}

List를 쓰면 목차 형식으로 나타남

 

 

 

 

 

 

List 안에 요소를 여러개 넣으면

import SwiftUI

struct MyList: View{
    
    var body: some View{
        

        List{
            Text("MY LIST")
            Text("MY LIST")
            Text("MY LIST")
            Text("MY LIST")
            Text("MY LIST")
            Text("MY LIST")
        }
        
    }
}

이런 형태로 출력

 

 

 

반복문(ForEach)을 사용하여 List를 처리하기

(ForEach 사용시 반드시 id를 부여해야 함)

 

 

첫번째 방법

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            ForEach(1...10, id: \.self){
                Text("MY LIST \($0)")
            }
        }
        
    }
}

두번째 방법

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            ForEach(1...10, id: \.self){
                itemIndex in Text("MY LIST \(itemIndex)")
            }
        }
        
    }
}

itemIndex 변수를 만들어서 Text에 넣기

 

첫번쨰, 두번쨰 결과는 동일함

 

 

 

 

앞 전 Layout 시간에서 만든 커스텀 카드를 List에 넣어 보기

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            ForEach(1...10, id: \.self){
                itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                			 start: "13:00", end: "15:00", bgColor: Color.green)
            }
        }
        
    }
}

 

 

 

 

 

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                          start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in 
                    MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                              start: "13:00", end: "15:00", bgColor: Color.blue)
                }
            }
        }
        
    }
}

List안에 Section을 만들어서 구분할 수 있음

 

Section 사용 구조

List{

    Section(header: Text("Section 명")){

        리스트 내용...

    }

}

 

 

 

 

 

 

 

List 자체에 속성 부여 가능

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in //Text("MY LIST \(itemIndex)")
                    MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in //Text("MY LIST \(itemIndex)")
                    MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", start: "13:00", end: "15:00", bgColor: Color.blue)
                }
            }
        }
        .listStyle(GroupedListStyle())
        
    }
}

.listStyle(GroupedListStyle())

 

 

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                          start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.blue)
                }
            }
        }
        .listStyle(PlainListStyle()) //default listStyle
        
    }
}

.listStyle(PlainListStyle()) 

 

 

 

 

listRowInsets(EdgeInsets.init()): List 요소들 간의 간격 조절 가능

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            .listRowInsets(EdgeInsets.init())
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                          start: "13:00", end: "15:00", bgColor: Color.blue)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 30, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
      
        
    }
}

 

init()값이 비워져 있으면 간격이 0으로 붙어져서 나옴

 

 

import SwiftUI

struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                          start: "13:00", end: "15:00", bgColor: Color.blue)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 30, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
      
        
    }
}

 

List 목록 선 지우기

import SwiftUI

struct MyList: View{
    
    init(){
        if #available(iOS 14.0, *){

        }else{
            UITableView.appearance().tableFooterView = UIView()
        }
        UITableView.appearance().separatorStyle = .none

    }
    var body: some View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.blue).hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 30, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
       
        
    }
}

코드 그대로 쳤는데 강의 이후로 이루어진 업데이트 때문인지 이렇게 해서는 List 목록 선이 안 없어짐

 

 

 

댓글에 다른 구독자 분이 남겨주신 List 목록 선 지우는 방법

import SwiftUI

struct HideRowSeparatorModifier: ViewModifier {
    static let defaultListRowHeight: CGFloat = 44
    
    var insets: EdgeInsets
    var background: Color
    init(insets: EdgeInsets, background: Color){
        self.insets = insets
        
        var alpha: CGFloat = 0
        
        UIColor(background).getWhite(nil, alpha: &alpha)
        assert(alpha == 1, "")
        self.background = background
    }
    
    func body(content: Content) -> some View {
        content
            .padding(insets)
            .frame(
                minWidth: 0, maxWidth: .infinity, minHeight: Self.defaultListRowHeight,   alignment: .leading
            )
            .listRowInsets(EdgeInsets())
            .background(background)
    }
}
extension EdgeInsets{
    static let defaultListRowInsets = Self(top: 10, leading: 10, bottom: 10, trailing: 10)
}
extension View {
    func hideRowSeparator(insets: EdgeInsets = .defaultListRowInsets, background: Color = .white)
    -> some View {
        modifier(HideRowSeparatorModifier(insets: insets, background: background))
    }
}


struct MyList: View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in  MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                            start: "13:00", end: "15:00", bgColor: Color.blue).hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
        
        
    }
}

 

 

 

List 목록 배경 색상 설정

import SwiftUI

struct HideRowSeparatorModifier: ViewModifier {
    static let defaultListRowHeight: CGFloat = 44
    
    var insets: EdgeInsets
    var background: Color
    init(insets: EdgeInsets, background: Color){
        self.insets = insets
        
        var alpha: CGFloat = 0
        
        UIColor(background).getWhite(nil, alpha: &alpha)
        assert(alpha == 1, "")
        self.background = background
    }
    
    func body(content: Content) -> some View {
        content
            .padding(insets)
            .frame(
                minWidth: 0, maxWidth: .infinity, minHeight: Self.defaultListRowHeight,   alignment: .leading
            )
            .listRowInsets(EdgeInsets())
            .background(background)
    }
}
extension EdgeInsets{
    static let defaultListRowInsets = Self(top: 10, leading: 10, bottom: 10, trailing: 10)
}
extension View {
    func hideRowSeparator(insets: EdgeInsets = .defaultListRowInsets, background: Color = .white)
    -> some View {
        modifier(HideRowSeparatorModifier(insets: insets, background: background))
    }
}


struct MyList: View{
        
        List{
            
            Section(header: Text("TODAY")){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(header: Text("TOMORROW")){
                ForEach(1...3, id: \.self){
                    itemIndex in  MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                            start: "13:00", end: "15:00", bgColor: Color.blue)
                                            .hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10),
                                            background(Color.yellow))
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
        
        
    }
}

 

 

 

 

Section에 footer 추가, Text() 속성 부여

import SwiftUI

struct HideRowSeparatorModifier: ViewModifier {
    static let defaultListRowHeight: CGFloat = 44
    
    var insets: EdgeInsets
    var background: Color
    init(insets: EdgeInsets, background: Color){
        self.insets = insets
        
        var alpha: CGFloat = 0
        
        UIColor(background).getWhite(nil, alpha: &alpha)
        assert(alpha == 1, "")
        self.background = background
    }
    
    func body(content: Content) -> some View {
        content
            .padding(insets)
            .frame(
                minWidth: 0, maxWidth: .infinity, minHeight: Self.defaultListRowHeight,   alignment: .leading
            )
            .listRowInsets(EdgeInsets())
            .background(background)
    }
}
extension EdgeInsets{
    static let defaultListRowInsets = Self(top: 10, leading: 10, bottom: 10, trailing: 10)
}
extension View {
    func hideRowSeparator(insets: EdgeInsets = .defaultListRowInsets, background: Color = .white)
    -> some View {
        modifier(HideRowSeparatorModifier(insets: insets, background: background))
    }
}


struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(
                header:
                    Text("TODAY")
                    .font(.headline)
                    .foregroundColor(.black)
                ,footer:
                    Text("HAVE A NICE DAY 👍")
                ){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                                           .hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(
                header:
                    Text("TOMORROW")
                    .font(.headline)
                    .foregroundColor(.black)
                ,footer:
                    Text("👍👍👍")
            ){
                ForEach(1...20, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.blue)
                                           .hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10),
                                           background: Color.yellow)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
       
        
    }
}

 

 

 

 

ContentView와 MyList 연동 (Navigation 적용하기)

import SwiftUI

struct ContentView: View {
    var body: some View {
        
        NavigationView{
            
            ZStack(alignment: .bottomTrailing){
                
                VStack(alignment: .leading, spacing: 0){
                    
                    HStack{
                        
                        NavigationLink(destination: MyList()){
                            Image(systemName: "line.horizontal.3")
                                .font(.largeTitle)
                                .foregroundColor(.black)
                            
                        }
                        
                        Spacer()
                        
                        Image(systemName: "person.crop.circle.fill")
                            .font(.largeTitle)
                        
                    }.padding(.top, 20)
                    .padding(.horizontal, 20)
                    
                    Text("TODO LIST")
                        .font(.system(size: 40))
                        .fontWeight(.black)
                        .padding(.horizontal, 20)
                        .padding(.top,20)
                    ScrollView{
                                VStack{
                                        MyCard()
                                    MyProject(icon: "tray.fill", title: "책상 정리하기", start: "13:00", end: "14:00", bgColor: Color.blue)
                                    MyProject(icon: "book.fill", title: "책 읽기", start: "14:00", end: "16:00", bgColor: Color.green)
                                    MyProject(icon: "case.fill", title: "기숙사 짐 싸기", start: "16:00", end: "18:00", bgColor: Color.red)
                                    MyBasic()
                                        
                                        
                                }.padding()
                        }
                }
                Circle()
                    .foregroundColor(Color.yellow)
                    .frame(width:60, height: 60)
                    .overlay(Image(systemName: "plus")
                                .font(.system(size:30))
                                .foregroundColor(.white))
                    .padding(10)
                    
                    .shadow(radius: 20)
            }//ZStack
            
        }//NavigationView

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

- ContentView의 요소들을 NavigationView에 넣기

- 햄버거 바가 들어있는 HStack에 NavigationLink 적용 

 

 

 

 

List 상단의 빈 공간은 navigationBarTitle 공간을 의미

 

List 상단의 navigationBarTitle 수정하기

import SwiftUI

struct HideRowSeparatorModifier: ViewModifier {
    static let defaultListRowHeight: CGFloat = 44
    
    var insets: EdgeInsets
    var background: Color
    init(insets: EdgeInsets, background: Color){
        self.insets = insets
        
        var alpha: CGFloat = 0
        
        UIColor(background).getWhite(nil, alpha: &alpha)
        assert(alpha == 1, "")
        self.background = background
    }
    
    func body(content: Content) -> some View {
        content
            .padding(insets)
            .frame(
                minWidth: 0, maxWidth: .infinity, minHeight: Self.defaultListRowHeight,   alignment: .leading
            )
            .listRowInsets(EdgeInsets())
            .background(background)
    }
}
extension EdgeInsets{
    static let defaultListRowInsets = Self(top: 10, leading: 10, bottom: 10, trailing: 10)
}
extension View {
    func hideRowSeparator(insets: EdgeInsets = .defaultListRowInsets, background: Color = .white)
    -> some View {
        modifier(HideRowSeparatorModifier(insets: insets, background: background))
    }
}


struct MyList: View{
    
    var body: some View{
        
        List{
            
            Section(
                header:
                    Text("TODAY")
                    .font(.headline)
                    .foregroundColor(.black)
                ,footer:
                    Text("HAVE A NICE DAY 👍")
                ){
                ForEach(1...3, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.green)
                                           .hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
            
            Section(
                header:
                    Text("TOMORROW")
                    .font(.headline)
                    .foregroundColor(.black)
                ,footer:
                    Text("👍👍👍")
            ){
                ForEach(1...20, id: \.self){
                    itemIndex in MyProject(icon: "book.fill", title: "책 읽기 \(itemIndex)", 
                                           start: "13:00", end: "15:00", bgColor: Color.blue)
                                           .hideRowSeparator(insets: EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10),
                                           background: Color.yellow)
                }
            }
            .listRowInsets(EdgeInsets.init(top: 10, leading: 10, bottom: 10, trailing: 10))
        }
        .listStyle(GroupedListStyle())
        .navigationBarTitle("MY LIST")
        
    }
}

 

 

 

 

메인 페이지(ContentView) 상단의 빈 공간은 NavigationView를 Stack에 쌓아서 생김

 

 

ContentView의 빈 공간 없애기

import SwiftUI

struct ContentView: View {

    @State
    var isNavigationBarHidden : Bool = false

    var body: some View {
        
        NavigationView{
            
            ZStack(alignment: .bottomTrailing){
                
                VStack(alignment: .leading, spacing: 0){
                    
                    HStack{
                        
                        NavigationLink(destination: MyList()){
                            Image(systemName: "line.horizontal.3")
                                .font(.largeTitle)
                                .foregroundColor(.black)
                            
                        }
                        
                        Spacer()
                        
                        Image(systemName: "person.crop.circle.fill")
                            .font(.largeTitle)
                        
                    }.padding(.top, 20)
                    .padding(.horizontal, 20)
                    
                    Text("TODO LIST")
                        .font(.system(size: 40))
                        .fontWeight(.black)
                        .padding(.horizontal, 20)
                        .padding(.top,20)
                    ScrollView{
                                VStack{
                                        MyCard()
                                    MyProject(icon: "tray.fill", title: "책상 정리하기", start: "13:00", end: "14:00", bgColor: Color.blue)
                                    MyProject(icon: "book.fill", title: "책 읽기", start: "14:00", end: "16:00", bgColor: Color.green)
                                    MyProject(icon: "case.fill", title: "기숙사 짐 싸기", start: "16:00", end: "18:00", bgColor: Color.red)
                                    MyBasic()
                                        
                                        
                                }.padding()
                        }
                }
                Circle()
                    .foregroundColor(Color.yellow)
                    .frame(width:60, height: 60)
                    .overlay(Image(systemName: "plus")
                                .font(.system(size:30))
                                .foregroundColor(.white))
                    .padding(10)
                    
                    .shadow(radius: 20)
            }//ZStack
            
            .navigationTitle("Main")
            .navigationBarHidden(self.isNavigationBarHidden)
            .onAppear{
                self.isNavigationBarHidden = true
            }
            
        }//NavigationView

    }
}

@State는 값을 감지함

 

@State 

var isNavigationBarHidden : Bool = false

 

isNavigationBarHidden을 default로 false 값 부여

 

NavigationView 안에 

.navigationTitle("Main")

    .navigationBarHidden(self.isNavigationBarHidden)

    .onAppear{

        self.isNavigationBarHidden = true

    }

설정을 해주면 self.isNavigationBarHidden이 true가 되면서 뷰를 다시 그림 

 

 

 

            

            

 

profile

Devlog

@덩이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그