[iOS] 당겨서 새로고침 (Pull To Refresh)
Pull to Refresh ( 당겨서 새로고침 ) 테이블 뷰 를 아래 방향으로 드래그하여 화면을 갱신하는 기능!
당겨서 새로고침 3단계
1. 테이블 뷰를 아래로 당김 : 새로고침을 한다는 메시지가 나타나기 시작한다.
2, 계속해서 당김 : 새로고침 기능을 실행하기 위한 임계점에 도달한다.
3. 릴리즈 : 손을 놓는 순간 연결된 메소드가 실행되면서 새로고침이 이루어진다
iOS 에서는 UIRefreshControl 컨트롤을 제공.
코드를 천천히 보자. 주석으로 달아둔게 더 이해하기도 쉽고 아무튼 그렇게 어려운 개념은 아니다.
//
// EmployeeListVCTableViewController.swift
// Chapter06-HR
//
// Created by Hamlit Jason on 2021/04/01.
//
import UIKit
class EmployeeListVC: UITableViewController {
var bgCircle : UIView! // 임계점에 도달했을 때 나타날 배경 뷰, 노란 원 형태
var loadingImg: UIImageView! // 새로고침 컨트롤에 들어갈 이미지 뷰
var empList: [EmployeeVO]! // 데이터 소스를 저장할 멤버 변수
var empDAO = EmployeeDAO() // SQLite 처리를 담당할 DAO 클래스
override func viewDidLoad() {
super.viewDidLoad()
self.empList = self.empDAO.find()
self.initUI()
self.refreshControl = UIRefreshControl()
//self.refreshControl?.attributedTitle = NSAttributedString(string: "당겨서 새로고침")
self.refreshControl?.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
// 로딩 이미지 초기화 및 중앙 정렬 - 수직정렬은 하면 안돼 왜냐하면 당기면서 y값이 변경되는데 대응할 수 없게 되서
self.loadingImg = UIImageView(image: UIImage(named: "refresh"))
self.loadingImg.center.x = (self.refreshControl?.frame.width)! / 2
// tintColor 값을 제거하여 기본 로딩 이미지인 인디케이터 뷰를 숨기고 로딩 이미지 뷰를 서브 뷰로 등록한다
self.refreshControl?.tintColor = .clear
self.refreshControl?.addSubview(self.loadingImg)
// 배경 뷰 초기화 및 노란 원 형태를 위한 속성 설정
self.bgCircle = UIView()
self.bgCircle.backgroundColor = UIColor.yellow
self.bgCircle.center.x = (self.refreshControl?.frame.width)! / 2
// 배경 뷰를 refreshControl 객체에 추가하고, 로딩 이미지를 제일 위로 올림
self.refreshControl?.addSubview(self.bgCircle)
self.refreshControl?.bringSubviewToFront(self.loadingImg)
}
@objc func pullToRefresh(_ sender: Any) {
// 새로고침 시 갱신되어야 할 내용들
self.empList = self.empDAO.find()
self.tableView.reloadData()
self.refreshControl?.endRefreshing() // 당겨서 새로고침 기능 종료
// 노란색 원이 로딩 이미지를 중심으로 커지는 애니메이션
let distance = max(0.0, -(self.refreshControl?.frame.origin.y)!)
UIView.animate(withDuration: 0.5) {
self.bgCircle.frame.size.width = 80
self.bgCircle.frame.size.height = 80
self.bgCircle.center.x = (self.refreshControl?.frame.width)! / 2
self.bgCircle.center.y = distance / 2
self.bgCircle.layer.cornerRadius = (self.bgCircle?.frame.size.width)! / 2
}
}
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { // 스크롤 뷰의 드래그가 끝났을 때 호출되는 메소드
// 노란 원을 다시 초기화
self.bgCircle.frame.size.width = 0
self.bgCircle.frame.size.height = 0
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) { // 스크롤이 발생할 때마다 처리할 내용 - 세부 코드는 외워서 쓰기
let distance = max(0.0, -(self.refreshControl?.frame.origin.y)!) // 이 구문은 통째로 외워두는 것이 좋다. - refreshControl 객체의 y좌표 값을 이용하거 당긴 거리를 계산하는 공식
self.loadingImg.center.y = distance / 2 // center.y 좌표를 당긴 거리만큼 수정
let ts = CGAffineTransform(rotationAngle: CGFloat(distance / 20))
self.loadingImg.transform = ts
self.bgCircle.center.y = distance / 2 // 배경 뷰의 중심 좌표 설정
}
func initUI() { // UI를 초기화할 메소드 initUI를 정의한다.
// 네비게이션 타이틀용 레이블 속성 설정
let navTitle = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
navTitle.numberOfLines = 2
navTitle.textAlignment = .center
navTitle.font = UIFont.systemFont(ofSize: 14)
navTitle.text = "사원 목록\n" + "총\(self.empList.count) 명"
// 네비게이션 바 UI 설정
self.navigationItem.titleView = navTitle
// 에디팅 버튼 직접 구현해보기 !! 자동화에 의존하지 않고
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.empList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let rowData = self.empList[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "EMP_CELL")
// 사원명 + 재직 상태 출력
cell?.textLabel?.text = rowData.empName + "(\(rowData.stateCd.desc()))"
cell?.textLabel?.font = UIFont.systemFont(ofSize: 12)
cell?.detailTextLabel?.text = rowData.departTitle
cell?.detailTextLabel?.font = UIFont.systemFont(ofSize: 12)
// Configure the cell...
return cell!
}
@IBAction func add(_ sender: Any) {
let alert = UIAlertController(title: "사원 등록", message: "등록할 사원 정보를 입력해 주세요", preferredStyle: .alert)
alert.addTextField { (tf) in
tf.placeholder = "사원명"
}
// 알림창에서 커스텀 할 수 있는 부분에 넣기
let pickervc = DepartPickerVC()
alert.setValue(pickervc, forKey: "contentViewController")
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "OK", style: .default){ (_)in
// 알림창의 입력 필드에서 값을 읽어온다
var param = EmployeeVO()
param.departCd = pickervc.selectedDepartCd
param.empName = (alert.textFields?[0].text)!
// 가입일은 오늘로 한다
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
param.joinDate = df.string(from: Date())
// 재직 상태는 '재직중'으로 한다
param.stateCd = EmpStateType.ING
// 데베 처리
if self.empDAO.create(param: param) {
// 테이블 뷰 갱신한다
self.empList = self.empDAO.find()
self.tableView.reloadData()
// 내비게이션 타이틀을 갱신한다
if let navTitle = self.navigationItem.titleView as? UILabel {
navTitle.text = "사원목록 \n " + "총 \(self.empList.count)명"
}
}
})
self.present(alert,animated: false)
}
@IBAction func editing(_ sender: Any) {
/*
주의 : 스토리 보드에서 시스템 아이템은 커스텀으로 해야 편집이 가능하다!!
*/
if self.isEditing == false { // 편집모드가 아닐떄
self.setEditing(true, animated: true)
(sender as? UIBarButtonItem)?.title = "Done"
} else { // 현재 편집 모드일때
self.setEditing(false, animated: true)
(sender as? UIBarButtonItem)?.title = "Edit"
}
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { // 목록편집 형식을 결정하는 메소드 (삽입/삭제/none)
return UITableViewCell.EditingStyle.delete
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
// 위의 함수와 함께 사용되며, 목록 편집 버튼을 클릭했을 때 호출되는 메소드
let empCd = self.empList[indexPath.row].empCd
// 데베에서, 데이터 소스에서, 그리고 테이블 뷰에서 차례대로 삭제한다.
if empDAO.remove(empCd: empCd) {
self.empList.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
}
'deprecated > 꼼꼼한 재은씨 시리즈' 카테고리의 다른 글
CoreData 코드 리뷰 (0) | 2021.04.09 |
---|---|
이벤트 버블링과 리스폰더 체인 (0) | 2021.04.09 |
[iOS14] SQLite 적용 기본 리뷰 (0) | 2021.04.01 |
[ios14] SQLite3 - Xcode12 설정 및 에러대응과 코드업 (0) | 2021.04.01 |
UserDefaults 코드리뷰 (0) | 2021.03.29 |