macOS

[iOS, macOS] Alamofire Framework(3)

Daesiker 2021. 3. 11. 16:16
반응형

이전 포스트를 안보신 분들은 보시고 오는 것을 추천드립니다.

[iOS, macOS] Alamofire Framework(1)

[iOS, macOS] Alamofire Framework(2)

Controller

마지막으로 사용자에게 기능을 제공하는 Controller만 남았는데 여기서 Alamofire을 사용하여 API와 통신을 하여 데이터를 최신화한 뒤 View에 제공해 준다.

 

MainTableViewController

Import Alamofire

import Alamofire

Alamofire 프레임워크를 사용하기 위해 코드 제일 앞에 Alamofire을 import 해준다.

 

변수 생성

var films: [Film] = []
  var items: [Displayable] = []
  var selectedItem: Displayable?

앞서 만든 Model들을 변수로 선언해준다. Alamofire을 통해 API와 연결해서 데이터를 담는 공간들이다.

 

Alamofire Extension

// MARK: - Alamofire
extension MainTableViewController {
  func fetchFilms() {
    //AF 통신
    AF.request("https://swapi.dev/api/films").validate().responseDecodable(of: Films.self) { (response) in
      guard let films = response.value else { return }
      self.films = films.all
      self.items = films.all
      self.tableView.reloadData()
    }
  }
  
  func searchStarships(for name: String) {
    let url = "https://swapi.dev/api/starships"
    let parameters: [String: String] = ["search": name]
    AF.request(url, parameters: parameters).validate()
      .responseDecodable(of: Starships.self) { response in
        guard let starships = response.value else { return }
        self.items = starships.all
        self.tableView.reloadData()
    }
  }
}

 

— fetchFilms()

fetchFilms()는 mainView가 실행되면 바로 실행되는 함수로 AF통신을 통해 해당 API에 있는 "/films" 데이터를 가져온다.

AF.request(string) : 통신할 url주소를 string으로 입력한다.

validate() : 해당 url과 정상적으로 통신을 했는지 유효값을 검사해주는 함수이다.

responseDecodable(of: Type, completionHandler: Void) : 정상적으로 요청이 완료되어서 돌아오는 데이터를 디코딩해주는 함수이다. of 파라미터에 디코딩 타입을 넣고 completionHandler에 디코딩한 데이터를 어떻게 사용할 것인지 정의한다. 여기서는 Decodable 구조체인 Films를 이용하여 디코딩을 한뒤 앞서 선언한 데이터에 옮겨주고 tableView를 최신화 된 데이터에 맞게 재정의를 하였다.

 

 

— searchStarships(for name: String)

SearchBar에 검색한 키워드를 name이란 String 데이터를 파라미터로 받아서 해당 값에 대한 데이터를 Alamofire를 통해 요청하는 함수이다. fetchFilms()랑 거의 다 비슷한 내용인데 다른 점은 request 부분에서 parameters라는 파라미터가 추가된 것이다. 앞서 받아온 name을 String Dictionary 자료구조로 바꾼 뒤 request() 함수에 parameters에 추가하면 해당 name이 들어간 starship의 데이터만 가져오게 된다. 한가지 유의할 점은 API마다 파라미터가 다 다르기 때문에 모든 API가 ["search" : value] 딕셔너리를 사용하지 않는 것이다.

 

DetailViewController

DetailViewController는 MainTableViewController에서 선택한 Film이나 Starship 데이터에 대한 세부정보를 보여주는 View이다.

 

Alamofire Extension

// MARK: - Alamofire
extension DetailViewController {
  private func fetch<T: Decodable & Displayable>(_ list: [String], of: T.Type) {
    var items: [T] = []
    let fetchGroup = DispatchGroup()
    
    list.forEach { (url) in
      fetchGroup.enter()
      AF.request(url).validate().responseDecodable(of: T.self) { (response) in
        if let value = response.value {
          items.append(value)
        }
        fetchGroup.leave()
      }
    }
    
    fetchGroup.notify(queue: .main) {
      self.listData = items
      self.listTableView.reloadData()
    }
  }
  
  func fetchList() {
    guard let data = data else { return }
    
    switch data {
    case is Film:
      fetch(data.listItems, of: Starship.self)
    case is Starship:
      fetch(data.listItems, of: Film.self)
    default:
      print("Unknown type: ", String(describing: type(of: data)))
    }
  }
}

 

fetchList()

data가 어떤 구조체인지 확인하고 보내야된 데이터의 타입과 데이터를 fetch() 함수에 보내준다.

DetailView의 구조를 보면 data에 대한 세부내용이 나오고 tableView에 data가 Film이면 관련된 Starship 데이터가 나오고 Starship이면 관련된 Film데이터를 표시한다. 그래서 switch문을 보면 반대로 되어있는 것을 알 수 있다.

data.listItems에는 해당 데이터를 볼 수 있는 url이 String 배열로 보여준다.

 

fetch<T: Decodable & Displayable>(_ list: [String], of: T.Type)

파라미터로 받은 데이터를 통해 새로운 T라는 Decodable과 Displayable 형태의 자료구조를 만든 뒤 새로운 데이터를 담아서 tableView의 데이터를 최신화 해주는 함수이다. 여기서는 Alamofire에서 여러개의 url에 대한 데이터를 요청하기 때문에 DispatchGroup을 이용해서 모든 url에 대한 데이터를 다 받은 후에 테이블 정보가 최신화 되도록 만들었다.

 

forEach 반복문을 통해 통신을 하게 되는데 서버 통신을 하기전에 enter()함수를 통해 DispatchGroup에 들어가서 데이터를 집어넣고 leave()함수를 통해 다시 빠져나온다. 이 동작을 수행하면서 items의 데이터를 계속 추가하는 것이다.

 

반복문이 종료되면 notify()함수를 통해 tableView를 업데이트한다. notify는 그룹의 모든 테스크가 작업을 마쳤을 때 사용하는 함수이다. queue 파라미터를 main으로 선언하여 DispatchGroup안에서 작업한 것을 메인 스레드에 보낸뒤에 테이블을 최신화하면 한번의 최신화로 모든 데이터를 받을 수 있다.

 

반응형

'macOS' 카테고리의 다른 글

[Swift] Protocol(1)  (0) 2021.03.16
[Swift] UserDefaults  (0) 2021.03.15
[iOS, macOS] Alamofire Framework(2)  (0) 2021.03.10
[iOS, macOS] Alamofire Framework(1)  (2) 2021.03.09
[iOS, macOS] QuickLook 프레임워크(2)  (0) 2021.03.07