2022. 10. 21. 11:23ㆍSeSAC/수업정리
-. iOS 13에서 나온 CollectionView API(DiffableDataSource, Compositional Layout)를 기반으로 iOS14에서 Section Snapshot, List Configuration이 새로 나왔다. 이를 사용하여 테이블뷰처럼 생긴 컬렉션뷰를 만들 수 있다.
-. MVVM이란 M-V-VM 세 개 레이어로 나누어 코드를 작성하는 방식으로 뷰모델을 통해 UI와 비지니스 로직을 분리하는게 핵심이다. *M(Model): 데이터 담당, VM(View Model): 비지니스로직 담당, V(View): UI담당
#. MVVM흐름: 데이터 초기화를 뷰모델에서 처리하고, 그 데이터를 뷰컨트롤러가 받아서 작업을 실행한다.
1. 레이아웃 설정: UICollectionViewLayout타입 레이아웃을 반환하는 메서드 생성
2. 데이터소스 설정(재사용셀 + 셀컨텐츠): diffable 데이터소스 타입으로 셀재사용(CellForItemAt) + 셀컨텐츠 설정
3. 데이터소스 설정(재사용셀에 사용할 데이터) + 뷰모델에서 데이터 초기화 및 처리: 뷰모델초기화한 데이터를 받아 snapshot에 넣기
*뷰모델에서 초기화하는 동시에 Observable에서 데이터 변화 체크(value 초기화)->클로저로 데이터 전달하는 메서드 실행(bind, didSet에 따른 listener실행)->뷰컨트롤러에서 전달받은 클로저 데이터로 작업 실행
3. 데이터소스 설정(재사용셀에 사용할 데이터) + 뷰모델에서 데이터 초기화 및 처리: 뷰모델초기화한 데이터를 받아 snapshot에 넣기
func bindData() {
//numberTextField.text = "3000"처럼 뷰컨트롤러에서 직접 보여주는게 아니라 뷰모델에서 내용을 전달받아 보여줌
//viewModel.pageNumber.bind실행구조: pageNumber초기화 동시에 CObservable value초기화-> bind실행시 클로저로 value전달, listener에 클로저 저장->value변경 시 변경된 value를 받은 listener실행
viewModel.pageNumber.bind { value in
self.numberTextField.text = value
}
//뉴스 추가 제거를 뷰모델 처리: datasource초기화하기 전에 사용하면 found nil 발생하므로 configureDataSource()에서 datasource초기화 먼저 해줘야함
viewModel.sample.bind { item in
var snapshot = NSDiffableDataSourceSnapshot<Int, News.NewsItem>()
snapshot.appendSections([0])
snapshot.appendItems(item) //News구조체가 가진 items 반환값은 itemsInternal()이고, itemsInternal()는 NewsItem타입의 배열이다. 즉, 배열을 스냅샷에 넣어주는 것과 같음.
self.dataSource.apply(snapshot, animatingDifferences: false)
}
}
#. MVVM+Diffable흐름: 네트워크 통신으로 받은 데이터 초기화를 뷰모델에서 처리하고, 그 데이터를 뷰컨트롤러가 받아서 작업을 실행한다.
1. 레이아웃 설정: UICollectionViewLayout타입 레이아웃을 반환하는 메서드 생성
2. 데이터소스 설정(재사용셀 + 셀컨텐츠): diffable 데이터소스 타입으로 셀재사용(CellForItemAt) + 셀컨텐츠 설정
3. 데이터 처리: 네트워크 통신으로 받은 String타입 이미지url을 이미지화(백그라운드 스레드(String->Url->Data), 메인 스레드(Data->Image)로 나누어서 작업)
4. 데이터소스 설정(재사용셀에 사용할 데이터) + 뷰모델에서 데이터 초기화 및 처리: 서치바텍스트 내용을 네트워크 통신요청->클로저로 받은 네트워트통신 내용을 photoList에 초기화->CObservable에서 값변경 인식하면서 snapshot에 데이터 추가하는 bind실행
*사용할 데이터를 정리한 Codable파일, 타입에 맞는 데이터를 받을 수 있는 네트워크 통신 메서드 미리 준비 필요!
*뷰모델에서 초기화하는 동시에 Observable에서 데이터 변화 체크(value 초기화)->클로저로 데이터 전달하는 메서드 실행(bind, didSet에 따른 listener실행)->뷰컨트롤러에서 전달받은 클로저 데이터로 작업 실행
3. 데이터 처리: 네트워크 통신으로 받은 String타입 이미지url을 이미지화(백그라운드 스레드(String->Url->Data), 메인 스레드(Data->Image)로 나누어서 작업)
//MARK: - 3. 데이터 처리: 네트워크 통신으로 받은 String타입 이미지url을 이미지화(백그라운드 스레드(String->Url->Data), 메인 스레드(Data->Image)로 나누어서 작업)
//String->Url->Data->Image: String으로 받은 이미지url을 이미지화 하는 과정
DispatchQueue.global().async { //네트워크통신은 백그라운드스레드에서 작업: 네트워크통신처리하는 동안 다른 작업 가능
let url = URL(string: itemIdentifier.urls.thumb)! //String->Url
let data = try? Data(contentsOf: url) //Url->Data
DispatchQueue.main.async { //UI업데이트는 메인스레드에서 작업
content.image = UIImage(data: data!) //Data->Image: 킹피셔는 UIImageView타입만 처리하기 때문에 킹피셔 사용 하지 않고 이미지화
cell.contentConfiguration = content //네크워크 비동기통신 하지 않도록 메인async에 선언해줘야 순서대로 실행됨
}
}
4. 데이터소스 설정(재사용셀에 사용할 데이터) + 뷰모델에서 데이터 초기화 및 처리: 서치바텍스트 내용을 네트워크 통신요청->클로저로 받은 네트워트통신 내용을 photoList에 초기화->CObservable에서 값변경 인식하면서 snapshot에 데이터 추가하는 bind실행
//MARK: - 4. 네트워크 통신요청: 서치바텍스트 내용을 네트워크 통신요청->클로저로 받은 네트워트통신 내용을 photoList에 초기화->CObservable에서 값변경 인식하면서 snapshot에 데이터 추가하는 bind실행
viewModel.requestSearchPhoto(query: searchBar.text!)
//뷰모델
func requestSearchPhoto(query: String) {
APIService.searchPhoto(query: query) { photo, statucCode, error in
guard let photo = photo else { return }
self.photoList.value = photo
}
//API요청
static func searchPhoto(query: String, completion: @escaping (SearchPhoto?, Int?, Error?) -> Void) { //통신요청내용(SearchPhoto), 상태코드(Int), 에러케이스 클로저 전달
let url = "\(APIKey.searchURL)\(query)"
let header: HTTPHeaders = ["Authorization": APIKey.authorization]
AF.request(url, method: .get, headers: header).responseDecodable(of: SearchPhoto.self) { response in //responseDecodable에 decode 대상 추가
let statusCode = response.response?.statusCode
switch response.result {
case .success(let value): completion(value, statusCode ,nil) //성공했을때 클로저로 통신요청내용, 상태코드 전달
case .failure(let error): completion(nil, statusCode ,error) //실패했을때 클로저로 상태코드, 에러케이스 전달
}
}
}
'SeSAC > 수업정리' 카테고리의 다른 글
082_Rx(Input, Output)+MVVM (0) | 2022.11.01 |
---|---|
43_Login, Lotto Examples(Observable+MVVM) (0) | 2022.10.25 |
072_UICollectionLayoutListConfiguration(테이블뷰스타일 컬렉션뷰) (0) | 2022.10.18 |
032_for-in, foreach 알아보기 (0) | 2022.08.17 |
017_Property (0) | 2022.07.26 |