포스트 이후로 enum을 활용해서 더 쉽게 코드를 짤 수 있었던 case 복기용 포스트들
이전에 코드를 작성했다면 아마 동일 UI의 ViewController를 하나 더 만들었던가, 아니면 다른 UI의 다른 목적의 ViewController로 재사용 상황을 회피하려 했을 것이다.
하지만 enum으로 case를 구분하면 동일 ViewController에 다른 화면 구성과 data를 전달할 수 있다.
enum DataType {
case whole
case search
var titleString: String {
switch self {
case .whole: return "전체"
case .search: return "검색"
}
}
}
class ViewController: UIViewController {
//Default: whole type으로 전체 데이터 보여주기
var type: DataType = .whole
@IBOutlet weak var tableView: UITableView!
//data: 전체 data와 검색 결과 저장하는 배열 2가지
let wholeData: [ExampleData] = [//...여러 data...]
var searchData: [ExampleData] = []
override func viewDidLoad() {
super.viewDidLoad()
configDataType()
}
func configDataType() {
title = type.rawValue
switch type {
case .whole:
navigationItem.rightBarButtonItem = UIBarButtonItem()
case .search:
navigationItem.titleView = UISearchBar()
}
}
func configTableView() {
tableView.register(nib, identifier: ExampleCell.identifier)
tableView.delegate = self
tableView.datasource = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch type {
case .whole:
return wholeData.count
case .search:
return searchData.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ExampleCell.identifier, for: indexPath) as! ExampleCell
switch type {
case .whole:
cell.exampleData = wholeData[indexPath.row]
case .search:
cell.exampleData = searchData[indexPath.row]
}
return cell
}
}
//검색 type일 경우, searchBar 구현 관련 delegate 설정해야 함
extension ViewController: UISearchBarDelegate {
//...관련 설정...
}
전체 데이터를 보여줄 목적인지, 검색 결과를 보여줄 목적인지에 따라, SearchBar instance를 설정하고 tableView에서 보여줄 데이터도 설정할 수 있다.
이는 동일한 ViewController에서 정보 추가를 위한 present인지, 기존 정보 수정을 위한 push 화면 전환인지도 구분할 수 있다.
협업시에 이는 더 중요해지는데, 예를 들어 push의 경우가 수정인지 추가인지 action/presentation과 맥락 의미 파악이 어려운 경우에 enum에서 정해진 값을 보고 쉽게 큰 그림을 그릴 수 있다.
서버에서 API를 제공할 때 주어지는 JSON 데이터의 key property는 제공처마다 다 다르다.
이름만 하더라도 name, movieNm, title, 등등...
String Literal로 활용해도 무방하지만 타이핑 에러, 코드 수정에서 오는 에러 등등 휴먼 에러 가능성이 너무 높아 이를 enum으로 관리하는 것이 안전하다.
기본 type 이외의 Codable로 설정한 custom data structure 내부에 enum을 활용하는데, 이 때 CodingKey를 활용한다.
CodingKey
A type that can be used as a key for encoding and decoding.
struct ExampleData {
var name: String
var age: Int
var height: Double
enum CodingKeys: String, CodingKey {
case name = "usrNm"
case age = "usrAge"
case height = "usrHt"
}
}
이 경우, response의 결과로 오는 json의 ["usrNm"], ["usrAge"], ["usrHt"]
를 직접 사용하지 않고 활용하고 싶은 property로 활용 가능하다.
참고
Encode and Decode Custom Types
enum APIkey {
static let googleKey = "thisIsAnExampleKeyStringValue"
static let kakaoKey = "thisIsAnExampleKakaoAuthKeyStringValue"
//...계속해서 나열...
}
networking에서 인증키의 경우, 키가 노출되는 등의 중요 보안 노출 상황이 아니라면 잘 변화하지 않는다. (물론 token처럼 일정 기간을 두고 만료되는 키들도 존재한다.)
또한 인증키들은 따로 instance를 생성하지 않을 것이므로 class나 struct 대신 enum type의 type property로 설정한다.
class나 struct의 type property로 활용해도 되지만 협업 과정, 혹은 차후 작업에서 instance를 생성할 경우, 내부 로직이 꼬일 수 있는 문제 발생의 가능성이 존재한다.