내일배움캠프 iOS

UIKit) TIL # 39 포켓몬 연락처 앱 과제 - URLSession 으로 수정해보기

yjuni22 2024. 12. 12. 21:26

과제 제출을 하고 추가적으로 

URLSession을 사용해보고 싶어서 공부해보았다.

 

 typealias NetworkCompletion = (Result<Poketmon, NetworkError>) -> Void
    
    // 네트워킹 요청하는 함수
    func fetchRandomPoketmonData(completion: @escaping NetworkCompletion) {
        let randomNum = Int.random(in: 1...1000)
        let urlString = "\(requestUrl)\(randomNum)"
        
        performRequest(with: urlString) { result in
            completion(result)
        }
    }
    
    // 실제 Request하는 함수 (비동기적 실행 ===> 클로저 방식으로 끝난 시점을 전달 받도록 설계)
    private func performRequest(with urlString: String, completion: @escaping NetworkCompletion) {
        print(#function)
        // URL구조체 만들기
        guard let url = URL(string: urlString) else { return }
        
        let session = URLSession(configuration: .default)
        
        // get 만 쓸 때 -> dataTask(with: url)
        let task = session.dataTask(with: url) { (data, response, error) in
            if error != nil {
                print(error!)
                completion(.failure(.networkingError))
                return
            }
            guard let safeData = data else {
                completion(.failure(.dataError))
                return
            }
            
            // 데이터 분석하기
            if let poketmon = self.parseJSON(safeData) {
                print("Parse 실행")
                completion(.success(poketmon))
            } else {
                print("Parse 실패")
                completion(.failure(.parseError))
            }
        }
        task.resume()
    }
    
    // 받아본 데이터 분석하는 함수 (동기적 실행)
    private func parseJSON(_ data: Data) -> Poketmon? {
        print(#function)
        // 성공
        do {
            // 우리가 만들어 놓은 구조체(클래스 등)로 변환하는 객체와 메서드
            // (JSON 데이터 ====> PoketmonData 클래스)
            return try JSONDecoder().decode(Poketmon.self, from: data)
            
            // 실패
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }

 

네트워크 매니저에 fetch 메서드와 request 메서드를 구현하였다.

 

그 후 뷰 파일 안에서 LoadImage 메서드를 추가하였다.

 

 // URL ===> 이미지를 셋팅하는 메서드
    // 이미지의 url을 먼저 받고 그 url로 이미지를 한번 더 요청함
    private func loadImage() {
        guard let urlString = self.imageUrl, let url = URL(string: urlString)  else { return }
        
        DispatchQueue.global().async {
            
            // url을 가지고 서버랑 통신하는 생성자, 동기적으로 되어있기 때문에 비동기처리를 따로 해줘야함
            guard let data = try? Data(contentsOf: url) else { return }
            
            DispatchQueue.main.async {
                self.randomImageView.image = UIImage(data: data)
            }
        }
    }

 

 

버튼에서 랜덤이미지를 받아오는 코드

 

 @objc func randomButtonTapped(_ sender: UIButton) {
        networkManager.fetchRandomPoketmonData { [weak self] result in
            guard let self else { return }
            
            DispatchQueue.main.async {
                switch result {
                case .success(let poketmon):
                    // 이미지 URL 설정
                    if let imageUrl = poketmon.sprites?.other?.home?.imageUrl {
                        self.phoneBookView.imageUrl = imageUrl
                    } else {
                        print("이미지 URL 없음")
                    }
                case .failure(let error):
                    print("포켓몬 데이터 로드 실패: \(error)")
                }
            }
        }
    }

 

이렇게 하면 URLSession 으로도 데이터를 받아올 수 있게 된다.

 

아직 더 공부가 필요한 부분이 많다.