-
lottie-ios 프레임워크와 UIViewRepresentable 을 이용한 LoadingView 구현SwiftUI/MVVM 알아보기 2020. 8. 27. 20:44
로띠(lottie) 는 json 형식의 움직이는 이미지 포맷으로 aribnb에서 개발되었고 많은 웹이나 앱에서 사용되고 있다. UIKit과 SwiftUI에서는 직접 이를 지원하지 않으므로 lottie-ios 프레임워크를 Pod을 통해 설치하고 이를 통해서 LottieView를 구현할 수 있다.
SwiftUI는 지원하지 않는 UIKit의 WebView 나 MapView등 사용하기 위해 UIViewRepresentable 프로토콜을 정의하고 있고 이를 구현함으로 써 쉽게 이를 SwiftUI로 전환 할 수 있다. 여기서는 lottie-ios 프레임워크와 UIViewRepresentable 프로토콜 구현을 통해 LottieView를 구현하고 이를 통해 날씨 정보를 로딩 하는 중 이를 화면에 표시하는 LodingView를 구현하는 것으로 날씨 앱 구현을 마무리한다.
lottie-ios는 terminal 에서 아래와 같이 설치할 수 있다. 이미 Cocoa Pods 이 설치되어 있으면 첫번째 과정은 수행하지 않는다.
Cocoa Pods 설치
$ sudo gem install cocoapods $ pod setup —verbose
Cocoa Pods 에서 lottie-ios 설치
현재 Project 폴더로 이동한 후 현재 프로젝트에서 아래와 같이 수행 $ pod init $ open Podfile Podfile에 pod 'lottie-ios' 추가 Podfile 내용 # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target 'ClimaForSwiftUI' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for ClimaForSwiftUI pod 'lottie-ios' target 'ClimaForSwiftUITests' do inherit! :search_paths # Pods for testing end target 'ClimaForSwiftUIUITests' do # Pods for testing end end 수정 완료후 프레임워크 설치를 위해 아래와 같이 입력 $ pod install $ open . 이후 프로젝트파일(.xcodeproj) 파일이 아닌 워크스페이스(.wcworkspace) 파일을 클릭해 XCode를 재 실행한다.
LottieView 구현
LottieView는 lottie-ios 프레임워크의 AnimationView를 생성하고 이를 UIView의 하위뷰로 설정한 후 이를 반환하는 팩토리 함수와 해당
뷰를 업데이트하는 함수를 가지는 UIViewRepresentable 프로토콜을 구현해야 한다. 이를 구현한 LottieView는 아래와 같다.
LottieView.swift
import SwiftUI import Lottie struct LottieView: UIViewRepresentable { var filename: String //UIViewRepresentable 프로토콜의 UIView 팩토리 메서드 구현 func makeUIView(context: Context) -> UIView { let view = UIView(frame: .zero) //로디 애니메이션 뷰 생성 let animationView = AnimationView() //애니메이션 파일 설정 animationView.animation = Animation.named(filename) //에니메이션 스케일 설정 animationView.contentMode = .scaleAspectFit //애니메이션 시작 animationView.play() animationView.translatesAutoresizingMaskIntoConstraints = false //해당 에니메이션 뷰를 생성할 View의 하위뷰로 설정 view.addSubview(animationView) //상위뷰의 크기로 애니메이션 뷰의 크기 설정 NSLayoutConstraint.activate([ animationView.widthAnchor.constraint(equalTo: view.widthAnchor), animationView.heightAnchor.constraint(equalTo: view.heightAnchor) ]) return view } //UIViewRepresentable 프로토콜의 UIView 업데이트 메서드 구현 func updateUIView(_ uiView: UIView, context: Context) { } }
이제 LottieView를 통해 LodingView를 아래와 같이 구현한다.
LoadingView.swift
import SwiftUI struct LoadingView: View { var body: some View { VStack(alignment: .center) { Spacer() LottieView(filename: "data") Text("Loading...").font(.title) .foregroundColor(.gray) Spacer() }.frame(width: 200, height: 200) .background(Color(red: 0.965, green: 0.969, blue: 0.972)) .cornerRadius(20) .shadow(color: /*@START_MENU_TOKEN@*/.black/*@END_MENU_TOKEN@*/, radius: /*@START_MENU_TOKEN@*/10/*@END_MENU_TOKEN@*/, x: 20, y: 20) } } struct LoadingView_Previews: PreviewProvider { static var previews: some View { LoadingView() } }
이제 WeatherViewModel은 날씨 정보를 가져올 때 로딩 뷰를 화면에 보여주고 완료시 로딩뷰를 화면에서 없애고 날씨 정보가 보이도록 isLoading 플래그를 추가하고 private func load(resource:) 함수 시작과 종료시 플래그를 변경하도록 한다.
WeatherViewModel.swift
class WeatherViewModel : ObservableObject { ... @Published var isLoading : Bool = false } extension WeatherViewModel { ... private func load(resource: Resource<WeatherData>) { isLoading = true URLRequest.load(resource: resource) { (result) in switch result { case .success(let weatherData) : self.model = weatherData case .failure(let error) : print(error) } self.isLoading = false } } }
이제 해당 뷰 모델을 관찰하고 있는 뷰는 isLoading 의 변경을 통지 받을 수 있고 이를 통해서 true일 때 로딩화면을 표시하고 false일 때 로딩화면을 제거할 수 있게 된다.
ContentView.swift
struct ContentView: View { ... var body: some View { ZStack { ... if viewModel.isLoading { LoadingView() } } } }
지금 까지 SwitUI를 이용해 날씨 앱을 구현한 전체 프로젝트는 아래에 추가한다.
'SwiftUI > MVVM 알아보기' 카테고리의 다른 글
SwiftUI 에서 CoreLocation 사용 (0) 2020.08.27 SwiftUI MVVM 모델 (0) 2020.08.27 iOS 의 MVC 모델 (0) 2020.08.26