관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 로딩화면 구현 방법, UIActivityIndicatorView 본문

iOS 응용 (swift)

[iOS - swift] 로딩화면 구현 방법, UIActivityIndicatorView

jake-kim 2022. 5. 29. 19:18

아이템을 로딩할 동안 로딩 뷰가 표출

cf) UIWindow에 로딩화면을 추가하여, 일부가 아닌 화면 전체에 interaction을 막는 LoadingView 구현 방법은 이전 포스팅 글 참고

UIActivityIndicatorView 

  • 아이폰의 기본 로딩 UI가 있는 뷰
UIActivityIndicatorView(style: .medium)
  • 메소드를 통해 로딩상태와 로딩상태가 아닌 UI로 쉽게 변경이 가능
activityIndicatorView.startAnimating()
activityIndicatorView.stopAnimating()
  • style에는 대표적으로 medium과 large가 존재

style: medium
style: large

로딩 뷰 구현

  • 아이템을 로드할땐 로딩 뷰가 보이도록하고 로드가 완료되었을땐 로딩 뷰가 안보이도록 설정

  • 사용하는쪽에서는 단순히 isLoading프로퍼티만 바꾸면 알아서 UI가 바뀌도록 구현
// 사용하는쪽

private let loadingView: LoadingView = {
  let view = LoadingView()
  view.translatesAutoresizingMaskIntoConstraints = false
  return view
}()

// in viewDidLoad()
self.loadingView.isLoading = true
self.getSomeData { [weak self] in
  self?.loadingView.isLoading = false
}
  • LoadingView 클래스 생성
import UIKit

final class LoadingView: UIView {

}
  • LoadingView 안에 UI 추가
    • backgroundView: 로딩하는동안 뒤 UI들을 가려야하므로 빈 UIView 선언
    • activityIndicatorView: 로딩 UI
private let backgroundView: UIView = {
  let view = UIView()
  view.backgroundColor = .white
  view.translatesAutoresizingMaskIntoConstraints = false
  return view
}()
private let activityIndicatorView: UIActivityIndicatorView = {
  let view = UIActivityIndicatorView(style: .large)
  view.translatesAutoresizingMaskIntoConstraints = false
  return view
}()
  • 외부에서 사용할 isLoading 프로퍼티 정의
    • didSet으로 loading상태이면 로딩 뷰가 보이도록하고 loading상태가 아니면 해당 뷰를 사라지게끔 처리
var isLoading = false {
  didSet {
    self.isHidden = !self.isLoading
    self.isLoading ? self.activityIndicatorView.startAnimating() : self.activityIndicatorView.stopAnimating()
  }
}
  • 레이아웃 정의
override init(frame: CGRect) {
  super.init(frame: frame)
  
  self.addSubview(self.backgroundView)
  self.addSubview(self.activityIndicatorView)
  
  NSLayoutConstraint.activate([
    self.backgroundView.leftAnchor.constraint(equalTo: self.leftAnchor),
    self.backgroundView.rightAnchor.constraint(equalTo: self.rightAnchor),
    self.backgroundView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
    self.backgroundView.topAnchor.constraint(equalTo: self.topAnchor),
  ])
  NSLayoutConstraint.activate([
    self.activityIndicatorView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
    self.activityIndicatorView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
  ])
}

사용하는는 쪽

  • 로딩되는 동안 가릴 화면을 덮어야 하므로 가릴 화면인 tableView와 동일하게 레이아웃 구성
  • addSubview할때는 가릴 화면 위에 addSubview
// VC2.swift

self.view.addSubview(self.tableView)
self.view.addSubview(self.loadingView)

NSLayoutConstraint.activate([
  self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
  self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
  self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
  self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
])
NSLayoutConstraint.activate([
  self.loadingView.leftAnchor.constraint(equalTo: self.tableView.leftAnchor),
  self.loadingView.rightAnchor.constraint(equalTo: self.tableView.rightAnchor),
  self.loadingView.bottomAnchor.constraint(equalTo: self.tableView.bottomAnchor),
  self.loadingView.topAnchor.constraint(equalTo: self.tableView.topAnchor),
])
  • 테스트 용도로 사용할 getSomeData 메소드 정의
private func getSomeData(completion: @escaping () -> ()) {
  DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    completion()
  }
}
  • 로딩이 필요한 작업 전에 isLoading상태를 true로, 로딩이 끝난 후에는 isLoading을 false로 변경
self.loadingView.isLoading = true
self.getSomeData { [weak self] in
  self?.loadingView.isLoading = false
}

* 전체코드: https://github.com/JK0369/ExActivityIndicatorView

Comments