MVC나 MVVM에서 모델에 데이터를 담을 때 api를 이용해서 json 데이터나 xml데이터를 파싱해서 넣어줘야할 필요가 있을 때가 있다.
어떻게 모델에 데이터를 집어넣을 수 있는지 알아보자.
일단 모델의 변수명!!!!
처음에 왜 파싱이 안되고 nil로 떨어지나 했더니 모델을 정의할 때 스트럭처 네임을 내 마음대로 지으면 안된다.
(정확히는 스트럭처명은 상관없으나 맵핑되어야할 데이터들의 컬럼명은 json 같아야함!!)
{
"status": "ok",
"totalResults": 20,
"articles": [
{
"source": {
"id": null,
"name": "CBS Sports"
},
"author": "Brent Brookhouse",
"title": "UFC 260 results, highlights: Francis Ngannou brutally knocks out Stipe Miocic to claim heavyweight title - CBSSports.com",
"description": "Ngannou pummeled the most accomplished heavyweight in UFC history with ease in the rematch on Saturday",
"url": "https://www.cbssports.com/mma/news/ufc-260-results-highlights-francis-ngannou-brutally-knocks-out-stipe-miocic-to-claim-heavyweight-title/live/",
"urlToImage": "https://sportshub.cbsistatic.com/i/r/2021/03/28/43f71821-fbd4-4c01-9238-304bc54faa9f/thumbnail/1200x675/1c0ccbf4798c9f82c0211a4ae3f63204/ngannou-knockout-miocic.jpg",
"publishedAt": "2021-03-28T04:26:00Z",
"content": "Francis Ngannou couldn't get the job done in his first shot at Stipe Miocic and the UFC heavyweight championship at UFC 220. In the main event of UFC 260, Ngannou left no doubt that he had become the… [+3775 chars]"
},
{
"source": {
"id": "cnn",
"name": "CNN"
},
"author": "Radina Gigova and Reuters, CNN",
"title": "'Words are not enough:' UN official urges world to act after at least 114 killed in Myanmar in one day - CNN ",
"description": "Human rights officials are calling on the international community to do more to stop the bloodshed in Myanmar after more than 100 civilians were reportedly killed by Myanmar military junta that overthrew the country's elected government.",
"url": "https://www.cnn.com/2021/03/28/asia/myanmar-protests-violence-intl-hnk/index.html",
"urlToImage": "https://cdn.cnn.com/cnnnext/dam/assets/210327224222-07-myanmar-unrest-0327-super-tease.jpg",
"publishedAt": "2021-03-28T04:09:00Z",
"content": "(CNN)Human rights officials are calling on the international community to do more to stop the bloodshed in Myanmar after more than 100 civilians were reportedly killed by Myanmar military junta that … [+7630 chars]"
},
해당 유알엘
https://newsapi.org/v2/top-headlines?country=us&apiKey=e9b514c39c5f456db8ed4ecb693b0040
제이슨 데이터를 보면 (get)
으로 articles의 컬럼안에 배열로 딕셔너리가 들어있다.
그럼 만약에 articles 타이틀을 가져오려면 모델 구성을 어떻게 해야할까요?
struct ArticleList: Decodable {
let articles: [Article]
}
struct Article: Decodable {
let title: String?
let description: String?
}
그럼 여기서는 변경 할 수 있는 값은 스트럭쳐명만 바꿀 수 있고 변수들은 나중에 파싱할 때 자동으로 가져오기 위해서 json과 같도록해야한다!
그럼 이제 해당 호출 할 메서드
func getArticles(url: URL, completion: @escaping ([Article]?) -> ()) {
URLSession.shared.dataTask(with: url) {
(data, response, error) in
if let error = error {
print(error.localizedDescription)
completion(nil) // if any error occurs, article can be nil
}else if let data = data {
let dataModel = try? JSONDecoder().decode(ArticleList.self, from: data)
print(data)
if let dataModel = dataModel {
print(dataModel)
completion(dataModel.articles)
}
}
}.resume()
}
jsonDecoder를 이용해서 디코드하면서 동시에 해당 모델로 파싱해서 데이터를 넣어준다!!
(해당 부분을 잘 이용해서 나중에 실제 프로젝트에서 잘 이용해보자.)
컴플션 핸들러로 데이터가 받아오면 해당 메서드를 실행 시킬 수 있도록 해주고
실제로 데이터를 호출해보면
let url =
URL(string: "https://newsapi.org/v2/top-headlines?country=us&apiKey=e9b514c39c5f456db8ed4ecb693b0040")!
getArticles(url: url, completion: { dataModel in
if let dataModel = dataModel {
print(dataModel)
}
})
안쪽에 데이터 모델을 만들어둔
private var modelArr: ArticleList!
모델에 넣어둔 뒤 사용해주면 될 것 같다!!
현재는 파싱되는 데이터만 받아보기 위해서 이렇게 모델과 뷰만 나눴는데 아래 블로그를 써주신 분이 아키텍쳐도 잘 나눠주셔서 배울 수 있었다.
https://42kchoi.tistory.com/292
끝!
'개발 > 개발' 카테고리의 다른 글
[Swift] - Access Control 접근제어자 (open, public, internal, fileprivate, private) (0) | 2022.01.21 |
---|---|
[iOS] - Testable한 코드를 작성하기 (0) | 2021.12.19 |
[iOS] Push Notification Error - InActive State (0) | 2021.11.10 |
Swift - 프로토콜 맛보기 (0) | 2021.11.02 |
RxSwift - Tap과 Action 으로 이벤트 처리 (0) | 2021.10.24 |