개요
MVVM 디자인 패턴을 이용하여 원피스 현상금 랭킹앱을 디자인.
현상금이 높은 순서대로 보여주어야 한다.
View구성은 TableView를 이용하였다.
실행 동영상
MVVM 디자인 패턴
View = UI + ViewController
Model = 데이터
ViewModel = Model은 ViewModel를 거쳐서 접근 가능하여야 한다. 알고리즘적인 부분 수행
StoryBoard : UI
- TableView : Cell
View에서 TableView를 구성한 다음에 Table View Cell 까지 디자인한다.
기존 Cell : xcode에서 자체적으로 지원하는 cell의 기본 디자인. 간단한 체크 표시 등등 가능.
Custom Cell : 직접 디자인하여 cell을 구성하는 방법. 주로 이 방법으로 구성한다.
이번 프로젝트 역시 커스텀셸로 디자인 하였다.
- Segue
테이블을 누르면, 현상금이 자세히 보여야 하기 때문에, 총 viewController Scene이 2개가 필요.
자연스럽에 밑에서 위로 올라오는 형태로 보이기 위하여 segue(세그웨이)를 이용하였다. (커스텀 이용x)
ViewController
UI에 적용해주는 것들 구현
⭐️ TableView를 위한 프로토콜 : 테이블 뷰 셸 몇개? , 테이블 뷰 어떻게 보여줘? , 테이블 뷰 클릭하면 어떡해? 등등 여러가지 질문이 있지만, 기본적으로 '테이블 뷰 셸 몇개? , 테이블 뷰 어떻게 보여줘?'이 두가지는 꼭 답을 해주어야한다. => UITableViewDataSource 상속
우리는 클릭했을 때도 할 일( => UITableViewDelegate 상속)이 있으므로 3가지 모두 답하기로 한다
TableView를 구성한 viewController Scene과 연결된 BountyViewController는 프로토콜에 대한 답을 해주기 위하여 UITableViewDataSource, UITableViewDelegate를 상속 받는다.
TableView프로토콜 확인 => melod-it.gitbook.io/sagwa/app-frameworks/uikit/views_and_controls/table-views#essentials
- TableView 서비스를 이용하기 위하여 기본적인 프로토콜 2가지
//UITableViewDataSource 질문에 대한 답 .
//셸이 몇개?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.numOfBountyInfoList
}
//셸을 어떻게 표현할 거니?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//부드럽게 박스 까는법.
//withIdentifier하면 id를 쓰라는말.
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as? ListCell else{
return UITableViewCell()
}
//뷰에 넣어주는 부분들
let bountyInfo = viewModel.bountyInfo(at: indexPath.row)
cell.update(info: bountyInfo)
return cell
}
- 버튼 클릭했을 때, segue를 실행 하기 위한 프로토콜
//UITableViewDelegate 질문에 대한 답
//클릭 했을 때, 어떻게 할꺼야?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//뒷부분에 sender는 showDetail로 넘어가기 전에 넘겨주어야할 것을 prepare 로 넘겨준다.
//showDetail은 segue에 id임.
performSegue(withIdentifier: "showDetail", sender: indexPath.row)
}
이 코드에서는 performSeque라는 함수(이미 구현되어있는 메소드)를 이용하는데 sender 부분을 nil로 설정하면, 전달할 것이 없는것이고,
전달할 것이있다면 sender에 넣어서 perpare에서 구성하면된다.
전달할 것이 있기 때문에 , perpare 함수(이미 구현되어있는 메소드)를 오버라이딩하여 DetailViewController Scene에 넣어준다.
//Segue를 호출할 떄, 밑에 perfromSegue함수 호출로 segue가 실행되기 직전에 준비하여 실행되는 함수.
//따라서 굳이 호출해주지 않아도 되며, 이미 있는 함수이기 때문에 오버라이딩하여 사용한 것.
//DetailViewController한테 데이터를 줄 것임
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail"{ //어떤 세그웨이?
// 목적지세그웨이를 DetailViewController 로 캐스팅하여 vc에 넣기
let vc = segue.destination as? DetailViewController
//이부분에서 if문을 사용하는 이유는 밑에서 index를 이용하여 대입을 하고있기 때문이다
//윗줄도 vc는 옵셔널 타입형이지만 if를 쓰지 않은 이유는 대입하고 있지 않기 때문이다
//if를 써도 되고 guard를 써도되며, !를 써도되는등 4가지 박스까기 방법이 있었다.
if let index = sender as? Int{ //밑에 performSegue 함수로부터 sender를 받아왔음. 그것을 Int변환
let bountyInfo = viewModel.bountyInfo(at: index)
vc?.viewModel.update(model: bountyInfo)
}
}
}
Model
이번 프로젝트에서 데이터는 매우 간단하다. 8개의 이미지, 이름, 현상금 3가지이면 되고 묶어서 접근 가능하여야 한다.
struct BountyInfo{
let name: String
let bounty:Int
var image: UIImage? {
return UIImage(named: "\(name).jpg")
}
init(name: String, bounty: Int){
self.name = name
self.bounty = bounty
}
}
ViewModel
controller나 view가 model에 접근 할 수 있도록 해주며, 알고리즘적인 부분을 담당한다.
viewmodel에서 model에 접근하는 초기 프로퍼티는 private이라고 가정하고 computed property나, 함수를 만들면 된다. ( viewmodel.model로 (. <-으로 )접근해서 싹다 꾸미면 되는데 왜 굳이 method나 computed property를 만드나 의아했었음 )
private이란 가정을 하면 이해감. - private으로 바꿔도 문제 없음 확인
Computed property 랑 Method 관련은 밑에 글 참고
var sortedList: [BountyInfo] {
let sortedList = bountyInfoList.sorted{ prev, next in //클로져로 구현
return prev.bounty > next.bounty
}
return sortedList
}
위 method는 viewmodel안에 computed property로 구현되어, sorted 함수 안의 인자로서 들어갈 함수는 클로져로 바로 구현된 것이다.
veiwModel는 알고리즘 부분을 담당하고 UI적인것은 담당하지 않는다. (UIkit을 import할 필요 없음. Foundation import 필요)
랭킹을 보여주려면 정렬이 필요한데, 정렬부분은 viewModel에서 이루어짐을 알 수 있다.
'🌙 iOS 스터디 > Xcode' 카테고리의 다른 글
[xcode] Inpo.plist 파일 - 애플리케이션 정보 (0) | 2021.01.24 |
---|---|
[xcode] HeaderView있는 CollectionView 애플 뮤직 앱 (0) | 2021.01.20 |
[xcode] CollectionView로 Animation기능을 추가한 원피스 현상금 앱 (0) | 2021.01.20 |
[Xcode] MVC 모델로 만든 계산기 앱 (Standford 대학 IOS강의) (0) | 2021.01.01 |
[Xcode] 손전등 앱 (Flash App) (0) | 2020.12.31 |