어제까지의 작업량은 분명 초반에 바로 데이터를 받아와 화면에 구현하지 못했고 각각의 세그먼트를 클릭했을 때만 데이터를 불러왔다.
우선 기술적인 부분에선 해결점들을 구성했다.
collectionview cell에 제약을 걸어주고 각각의 cell안에 있는 image와 label 간에 제약을 걸어준다. collectionview 내에서의 간격과 제약들을 코드로 추가적으로 구현한다.
//ViewController
let flowLayout = UICollectionViewFlowLayout()
searchCollectionView.collectionViewLayout = flowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellWidth = (collectionView.bounds.width - 10) / 2
let cellHeight = collectionView.bounds.height / 3
return CGSize(width: cellWidth, height: cellHeight)
}
//cell.swift
@IBOutlet weak var movieName: UILabel!
@IBOutlet weak var movieImage: UIImageView!
var movie: MovieData.Movie?
func setCell(_ _movie: MovieData.Movie) {
movie = _movie
self.movieName.text = _movie.title
self.movieName.sizeToFit()
self.movieImage.contentMode = .scaleToFill
// 아래 코드들 ...
이렇게 설정하면 위에 보이는 이미지와 같이 cell 간의 간격이 가로행은 2개로 세로행은 3개로 총 한 화면에 6개로 구성이 된다
가장 많이 고민했고, 가장 많이 헤멨던 부분이다. 우선 collectionview에 있는 cell들이 화면이 전환됨과 동시에 데이터들을 전송받아야한다.
//VC viewDidLoad()에 구현된 코드
MovieData.shared.getNowPlayingMovies(completion: { [weak self] in
self?.displayCollectionView = MovieData.shared.nowPlayingMovies
DispatchQueue.main.async {
self?.movieCollectionView.reloadData()
}
})
//Data Class에 구현된 코드
public func getNowPlayingMovies(completion: @escaping () -> Void) {
//파일 형식과 API키를 정의한 헤더부
let headers = [
"accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJmM2Q1ZTNlYWY2MGViNWY3Njg5YjhjMjIxNTYyMzlhNCIsInN1YiI6IjY1YTUwZDgwMWZiOTRmMDBjMDc0YTFhNyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.4pi9VmylhkY94DoJk6s4Ol7txHjXcyonKy3PeI9ZdS8"
]
//요청을 보낼 URL
let url = URL(string: "https://api.themoviedb.org/3/movie/now_playing?language=ko-KR&page=1")!
//URL에 요청
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
//HTTP 메서드 설정
request.httpMethod = "GET"
//요청에 헤더부 추가
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
//에러 처리
if let error = error {
print("Error fetching data: \(error)")
return
}
//데이터 옵셔널 바인딩
guard let data = data else {
print("No data received")
return
}
//데이터 처리
do {
let decoder = JSONDecoder()
let result = try decoder.decode(Result.self, from: data)
self.nowPlayingMovies = result.results
completion()
print ("현재상영작 데이터 세팅 완료")
} catch {
print("Error parsing JSON: \(error)")
}
})
dataTask.resume()
}
통신이나 비동기 처리를 하는 코드를 작성할 때, completion 클로저를 사용하고 @escaping
이라는 탈출 클로저를 사용한다. 또한 shared라는 싱글톤 패턴을 적용하여 클래스에 직접 접근해서 쓸수 있도록 만들어준다.