// ์ฌ์ฉ์์ ์ฆ๊ฒจ์ฐพ๊ธฐ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ํด๋์ค
class FavoriteManager {
static let shared = FavoriteManager()
private init() {}
var persistentContainer: NSPersistentContainer {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer
}
// MARK: - Core Data Saving support
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
print("User saved successfully")
} catch {
let nserror = error as NSError
print("Failed to save user: \(error.localizedDescription)")
}
}
}
}
- saveContext ๋ฉ์๋: ์ด ๋ฉ์๋๋ ํ์ฌ์ ๊ด๋ฆฌ ๊ฐ์ฒด ์ปจํ ์คํธ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋์ง ํ์ธํ๊ณ , ๋ณ๊ฒฝ ์ฌํญ์ด ์์ผ๋ฉด ์ด๋ฅผ ์ ์ฅํ๋ค.
- persistentContainer.viewContext: ํ์ฌ์ ๊ด๋ฆฌ ๊ฐ์ฒด ์ปจํ ์คํธ๋ฅผ ๋ํ๋ธ๋ค.
- context.hasChanges: ์ปจํ ์คํธ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋์ง ํ์ธํ๋ค.
- context.save(): ๋ณ๊ฒฝ ์ฌํญ์ ์๊ตฌ ์ ์ฅ์์ ์ ์ฅํ๋ค.
- ์๋ฌ ์ฒ๋ฆฌ: ์ ์ฅ ๊ณผ์ ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ์ด๋ฅผ catch ๋ธ๋ก์์ ์ฒ๋ฆฌํ๊ณ , ์๋ฌ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
func fetchMovieBackdropImage(movieId: Int, completion: @escaping (String?) -> Void) {
let urlString = "\(baseUrl)/movie/\(movieId)?api_key=\(apiKey)&language=ko-KR"
fetchMovieDetail(with: urlString) { movieDetail in
completion(movieDetail?.backdropPath)
}
}
// ๊ณตํตํ๋ fetchMovieDetail ๋ฉ์๋
private func fetchMovieDetail(with urlString: String, completion: @escaping (MovieDetail?) -> Void) {
guard let url = URL(string: urlString) else {
print("Invalid URL")
completion(nil)
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
completion(nil)
return
}
guard let data = data else {
print("No data returned")
completion(nil)
return
}
do {
let decoder = JSONDecoder()
let movieDetail = try decoder.decode(MovieDetail.self, from: data)
completion(movieDetail)
} catch let jsonError {
print("JSON error: \(jsonError.localizedDescription)")
print(String(data: data, encoding: .utf8) ?? "No readable data")
completion(nil)
}
}.resume()
}
๊ณตํต ๋ฉ์๋ fetchMovieDetail๋ ๋น๋๊ธฐ์ ์ผ๋ก ๋คํธ์ํฌ ํธ์ถ์ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํด๋ก์ ๋ก ๋ฐํํ๋ค.
์ด ๊ฒฐ๊ณผ๋ฅผ fetchMovieBackdropImage ๋ฉ์๋์์ ๋ฐ์์ ํ์ํ ๋ฐ์ดํฐ(backdropPath)๋ฅผ ์ถ์ถํ๊ณ ๋ค์ ํด๋ก์ ๋ก ์ ๋ฌํ๋ค.
fetchMovieBackdropImage ๋ฉ์๋์์๋ URL ์์ฑ๊ณผ ๋ฐ์ดํฐ ์ถ์ถ๋ง ๋ด๋นํ๊ณ ,
์ค์ ๋คํธ์ํฌ ์์ฒญ๊ณผ JSON ๋์ฝ๋ฉ์ ๊ณตํตํ๋ fetchMovieDetail ๋ฉ์๋๊ฐ ์ฒ๋ฆฌํ๊ฒ ๋๋ค.
์ด๋ ์ฝ๋์ ์ค๋ณต์ ์ค์ด๊ณ ์ ์ง ๋ณด์์ฑ์ ๋์ด๋ฉฐ, ๊ฐ ๋ฉ์๋์ ์ญํ ์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ ์ ์๋ค.
๋ ์ฝ๋์ ์ฐจ์ด์
1. ๋์ฝ๋ฉํ ๋ฐ์ดํฐ ํ์ :
์ฒซ ๋ฒ์งธ ์ฝ๋์์๋ MovieDetail ํ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉํ๋ค.
๋ ๋ฒ์งธ ์ฝ๋์์๋ MovieResponse ํ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉํ๋ค.
2. completion ํธ๋ค๋ฌ์ ์ธ์:
์ฒซ ๋ฒ์งธ ์ฝ๋์ completion ํธ๋ค๋ฌ๋ MovieDetail? ํ์ ์ ๊ฐ์ ๋ฐ๋๋ค.
๋ ๋ฒ์งธ ์ฝ๋์ completion ํธ๋ค๋ฌ๋ [Movie]? ํ์ ์ ๊ฐ์ ๋ฐ๋๋ค. MovieResponse๋ results๋ผ๋ ๋ฐฐ์ด ์์ฑ์ ๊ฐ์ง๊ณ ์๋ค.
3. ์๋ต ๋ฐ์ดํฐ ๊ตฌ์กฐ:
์ฒซ ๋ฒ์งธ ์ฝ๋๋ ์ํ์ ์ธ๋ถ ์ ๋ณด๋ฅผ ๋ด์ ๋จ์ผ ๊ฐ์ฒด MovieDetail์ ์ฒ๋ฆฌํ๋ค.
๋ ๋ฒ์งธ ์ฝ๋๋ ์ํ ๋ชฉ๋ก์ ๋ด์ MovieResponse ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ก [Movie] ๋ฐฐ์ด์ ๋ฐํํ๋ค.
์ด๋ค ์ํฉ์ ์ฌ์ฉํ ๊น?
์ฒซ ๋ฒ์งธ ์ฝ๋๋ ํน์ ์ํ์ ์ธ๋ถ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋ ์ฌ์ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ํ์ ์ ๋ชฉ, ์ค๊ฑฐ๋ฆฌ, ๊ฐ๋ , ์ถ์ฐ์ง ๋ฑ์ ์ ๋ณด๋ฅผ ํฌํจํ๋ MovieDetail ๊ฐ์ฒด๊ฐ ํ์ํ ๋ ์ฌ์ฉ๋๋ค.
๋ ๋ฒ์งธ ์ฝ๋๋ ์ฌ๋ฌ ์ํ์ ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ ธ์ฌ ๋ ์ฌ์ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ธ๊ธฐ ์ํ ๋ชฉ๋ก์ด๋ ํน์ ์ฅ๋ฅด์ ์ํ ๋ชฉ๋ก์ ๊ฐ์ ธ์์ผ ํ ๋ MovieResponse ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ [Movie] ๋ฐฐ์ด๋ก ๋ฐํํ๋ค.