-
SwiftUI - refreshableSwiftUI 2022. 12. 8. 10:16
안녕하세요. 그린입니다🍏
이번 포스팅에서는 SwiftUI의 List에서 사용 가능한 refreshable이라는 새로 고침 기능에 대해 알아보겠습니다🙌
우선 해당 기능은 iOS 15 부터 사용이 가능해요!
참고로 WWDC2021에서 소개되었습니다.
비교적 어떻게 보면 최신 메서드이기에 현업에서 13, 14부터 지원을 한다면 사용할 순 없습니다.
그렇지만 앞으로 미니멈 타겟은 점차 올려갈것이고 배워두면 좋기에 이참에 한번 트라이 해봅니다🙌
여러분 모두 테이블뷰 혹은 컬렉션뷰로 된 즉, 리스트로 데이터가 뿌려진 뷰의 경우 최상단에서 아래로 드래깅 시 새로 고침이 되면서 데이터를 최신으로 갱신하는 그런 기능을 가진 앱을 아주 많이 보셨고 익숙하실거라 생각합니다.
모두에게 사실은 친숙한 기능이긴한데 SwiftUI에서 API로 제공하진 않았습니다.
그런데 15에서부터 아주 손쉽게 사용 가능하도록 제공이 되었죠😀
그럼 거두절미하고 바로 어떤 메서드인지 어떻게 사용하는지 보시죠!
refreshable?
SwiftUI에서 List의 뷰를 새로 고침 해줍니다.
설명 끄읕~~👏👏👏
한마디로 정의가 끝났습니다.
해당 메서드를 뷰 모디파이어로 붙이면 아래 드래깅하여 새로 고침을 할 수 있도록 제공해준다는거죠.
func refreshable(action: @escaping () async -> Void) -> some View
선언은 이렇습니다.
해당 뷰 모디파이어를 통해 async한 탈출 클로저를 실행시킵니다.
주로 최신의 데이터를 다시 fetch하는 작업이 이뤄지는게 맞을것 같아요.
사용자가 새로 고침을 요청할 때 발생하는 SwiftUI가 실행하는 비동기 처리기죠.
실행 코드 앞 await 키워드를 사용해 비동기 호출을 해주도록 합니다.
위와 같은 메서드를 사용하면 리스트에서 아래 드래깅을 통해 새로 고침을 해주지만 이를 커스텀한 뷰에 적용할 수 있습니다.
즉, 버튼을 눌러 새로 고침을 한다던지 등의 조금 더 커스텀한 구성이 RefreshAction 인스턴스 설정으로 가능하죠.
이건 또 아래에서 알아보겠습니다🙋🏻
그럼 우선 refreshable 메서드를 예시를 통해 사용해보겠습니다!
refreshable 사용하기
import SwiftUI struct ContentView: View { @State var colors: [Color] = [] var body: some View { VStack(spacing: 10) { Text("Colors") .font(.largeTitle) .padding(.top, 50) List(colors, id: \.self) { color in RoundedRectangle(cornerRadius: 10) .frame(width: 300, height: 50) .foregroundColor(color) } .onAppear { colors = initColors() } .refreshable { await colors.append(contentsOf: addColors()) } Spacer() } } private func initColors() -> [Color] { return [.yellow, .green, .indigo, .orange, .purple] } private func addColors() async -> [Color] { return [.red, .blue, .gray] } }
저는 별도 통신을 해주지 않고 야매로 데이터를 넣었습니다!
그렇기에 await, async를 사실 사용하지 않아도 무방하긴 해요ㅎㅎ
우선 List에 다양한 색상의 둥근 사각형을 초기에 5개 만들어주고 이후 refresh 될 때 3개를 추가해주는 로직입니다.
그럼 어떻게 나오는지 봐볼까요?
위와 같이 아래로 드래깅 시 새로 고침의 인디케이터가 돌고 정의한 색상이 추가되어 뷰가 업데이트 되는것을 확인할 수 있습니다.
아주 사용이 쉽습니다ㅎㅎ
추후에 실 데이터 통신의 역할을 addColors 메서드 대신 갈아끼워 데이터를 갱신해오는 로직을 가져가면 됩니다🙌
그럼 이어서 아까 짚고 넘어가자던 RefreshAction에 대해 알아보겠습니다!
RefreshAction?
위에서 간단히 언급했듯이 새로 고침을 시작할 수 있도록 해주는 작업입니다.
struct RefreshAction
구조체 타입이며, 기본적으로 refresh 환경 값에 해당 인스턴스가 포함되어 있어 기본 뷰의 Environment가 새로 고침을 제공해주죠.
디폴트하게 이 Environment의 값은 nil이지만 refreshable 메서드를 이용하였을때 지정한 처리를 하는 새로 고침 작업을 해줄 수 있습니다.
이제 RefreshAction을 이용해 커스텀한 뷰를 만들어 새로 고침을 해줄 수 있습니다.
refresh Environment 변수를 이용하면 됩니다🙌
아래 예시를 들어보겠습니다. (공식문서 참고한 예시!)
struct RefreshableView: View { @Environment(\.refresh) private var refresh var body: some View { Button("Refresh") { Task { await refresh?() } } .disabled(refresh == nil) } }
refresh를 callAsFunction 이용해 직접 정의하고 호출하는 메서드로 사용할 수 있습니다.
여기서 callAsFunction은 새로 고침 작업을 시작하는 메서드입니다.
호출이 비동기적이므로 Task와 await를 이용합니다.
설명이 조금 복잡할 수 있는데 사용은 어렵지 않으니 바로 사용법을 보시죠🕺🏻
커스텀하게 새로 고침 기능 사용하기
import SwiftUI struct ContentView: View { @State var colors: [Color] = [] var body: some View { VStack(spacing: 10) { Text("Colors") .font(.largeTitle) .padding(.top, 50) List(colors, id: \.self) { color in RoundedRectangle(cornerRadius: 10) .frame(width: 300, height: 50) .foregroundColor(color) } .onAppear { colors = initColors() } CustomRefresher() .refreshable { await colors.append(contentsOf: addColors()) } Spacer() } } private func initColors() -> [Color] { return [.yellow, .green, .indigo, .orange, .purple] } private func addColors() async -> [Color] { return [.red, .blue, .gray] } } struct CustomRefresher: View { @Environment(\.refresh) private var refresh var body: some View { Group { if let refresh = refresh { Button( action: { Task { await refresh() } }, label: { Text("Refresh Button") } ) } } } }
CustomRefresher라는 뷰를 만들어줍니다.
refresh Environment 변수를 가지죠!
버튼의 action 동작으로 비동기 작업을 위해 Task에 refresh의 callAsFunction을 호출해주도록 합니다.
이 커스텀한 뷰를 원하는곳에 배치하고 위에서 알아본 refreshable 메서드를 통해 구현해주면 끝🙌
그럼 요렇게 버튼을 눌렀을때 데이터가 추가되고 뷰가 업데이트 됩니다👍
마무리
이렇게 오늘도 SwiftUI의 적당한 괜찮은 기능을 알아봤습니다!
해당 위 예시 코드들은 아래 제 깃헙에도 있으니 참고하실분들은 참고하셔도 좋겠습니다😊
https://github.com/GREENOVER/playground/tree/main/refreshable
[참고자료]
https://developer.apple.com/documentation/swiftui/view/refreshable(action:)
https://developer.apple.com/documentation/swiftui/refreshaction
'SwiftUI' 카테고리의 다른 글
SwiftUI - View를 구조체로 생성하는 이유 (7) 2022.12.26 SwiftUI - View (3) 2022.12.24 SwiftUI - antialiased & interpolation (0) 2022.12.06 SwiftUI - renderingMode (0) 2022.12.02 전역적인 Window 객체를 이용해 LoadingView 띄우기 (0) 2022.11.29