이번 과제는 포켓몬 이미지를 활용한 연락처를 만드는 것이다.
이번엔 MVC패턴을 활용해 프로젝트를 진행하기로 결정했기에 View, ViewController, Model을 나누어 구현을 하였다.
Lv.1 | Lv.2,3 | Lv.4 |
---|---|---|
추가
버튼을 눌렀을 시 PhoneBookViewController로 이동할 수 있게 구현 rightButton.action = #selector(tappedAddButton)
@objc func tappedAddButton() {
navigationController?.pushViewController(phoneBookViewController, animated: true)
}
navigationItem.title = "친구 목록" // 가운데에 들어가는 타이틀
navigationItem.rightBarButtonItem = rightButton // 오른쪽에 들어갈 Item을 앞서 생성한 Button(rightButton)을 넣어주면 된다.
func fetchData<T: Decodable>(url: URL, completion: @escaping (Result<T, AFError>) -> Void) {
AF.request(url).responseDecodable(of: T.self) { response in
completion(response.result)
}
}
// pokemon api 요청 함수
func fetchPokemonApi(completion: @escaping (UIImage?) -> Void) {
let urlAdress = "https://pokeapi.co/api/v2/pokemon/"
let randomNum = String(Int.random(in: 1...1000))
// 요청할 url주소를 생성
guard let url = URL(string: urlAdress + randomNum) else {
completion(nil)
return
}
// 바로 위에서 생성한 url주소를 가지고 결과값을 받아오는 메서드
fetchData(url: url) { [weak self] (result: Result<PokemonData, AFError>) in
guard let self = self else { return }
switch result {
case .success(let result) :
guard let imageUrl = URL(string: result.sprites.frontDefault) else { return }
// 이미지가 저장된 url을 이용해 UIImage로 변환해서 completion(콜백함수)로 Image의 값을 넘겨준다.
AF.request(imageUrl).responseData { response in
if let data = response.data, let image = UIImage(data: data) {
DispatchQueue.main.async {
completion(image)
}
}
}
case .failure(let error) :
print("데이터 로드에 실패 \(error)")
completion(nil)
}
}
// 싱글톤으로 생성
static let shared = CoreDataManger()
초기에는 Attribute를 name: String, phoneNumber: String, profilesImage: String
으로 생성을 했었다. 그 후 create를 통해 테스트를 거치며, 잘 작동하는걸 확인했다.
하지만 image를 url로 저장하려고 했던 초기 계획이 아닌거 같아 profilesImage의 속성을 Binary Data
로 변경을 했다. 그때까지는 아무런 이상이 없어보였지만 빌드를 하고나서 장문의 에러메세지를 받게 되었다.
아래의 에러들은 결론적으론 기존의 저장된 데이터의 형식과 현재 빌드하는 데이터의 형식이 맞지 않아서 즉, Core Data의 모델의 변경으로 빌드를 할 수 없다는 말이였다.
이 상황에서 해결방법은 1. 데이터를 초기화, 2. 자동 마이그레이션 활성화, 3. 수동으로 마이그레이션 와 같은 선택지가 주어졌다. 저의 경우에는 개발단계이기도 하고 앞서 저장한 데이터는 테스트를 위한 데이터였기에 데이터를 초기화하는 결정을 내렸다. 가장 빠르고 개발환경에서 할 수 있는 방법이다.
아래의 사진은 AppDelegate에서 보았던 persistentContainer 변수이다. 이 코드를 통해 기존에 저장되어 있던 데이터를 지우고 새롭게 변경된 값으로 저장을 할 수 있게 되었다.
// NSSortDescriptor을 이용해 오름차순으로 정렬
let fetchRequest = PhoneBook.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] // true : 오름차순, false : 내림차순
TableView Cell을 선택했을 시 저장되어있는 데이터를 띄워주는데 이름, 전화번호, 이미지까지 잘 받아서 보여주는데 앱 상단의 NavigationBar에 있는 title부분이 바뀌지 않는 이슈가 있었다.
navigationBarSetup함수
에서 navigationItem.title을 미리 "연락처 추가"로 저장해 놓은 바람에 configureUI함수
에서의 navigationItem.title 값을 변화를 주어도 바뀌지 않았다. 여기서 viewDidLoad에 configureUI
다음에 navigationBarSetup
을 호출하게 정의해 놓아서 덮어씌워진거였다. 그래서 navigationBarSetup함수
에서 정의해놓은 title값을 제거한 후 제대로 작동이 되었다.
이번에 MVC패턴을 사용하고자 View와 ViewController의 역할을 분리하는 과정에서 많은 시행착오가 있었고 delegate와 클로저를 활용한 콜백함수를 구현하는 등 여러 방법으로 구현해보려고 노력했다. 물론 네트워킹과 데이터를 저장하고 다루는 부분에서 시간을 많이 소요해서 앞으로 수정할 것도 다시 공부해야할 것도 많이 남아있는 프로젝트였다.
추가 버튼 파랑색 아닌 거 너무 신걍 쓰이는데 수정해주세요 개발자님