
이전에 프로젝트에서 Model 부분을 설계하면서, 이처럼 설계했는데 Alamofire를 사용해서 데이터를 받아오려면 구조를 수정해야 하는 것을 알게 되어서 아래와 같이 수정해줬다.
struct Profile: Decodable {
let login: String
let id: Int
let avatarUrl: String
let name: String?
let region: String?
let followers: Int?
let following: Int?
enum CodingKeys: String, CodingKey {
case login
case id
case avatarUrl = "avatar_url"
case name
case region
case followers
case following
}
public func getLogin() -> String{
return login
}
public func getId() -> Int {
return id
}
public func getName() -> String {
if let name = name {
return name
}
return "-"
}
public func getRegion() -> String {
if let region = region {
return region
}
return "-"
}
public func getFollowers() -> String {
if let followers = followers {
return String(followers)
}
return "-"
}
public func getFollowing() -> String {
if let following = following {
return String(following)
}
return "-"
}
}
수정된 데이터 구조를 통해 GitHub의 프로필 부분을 받아오기 위해서, fetchGitHubUser() 함수를 따로 작성해 줬다.
func fetchGitHubUser(username: String) {
let url = "https://api.github.com/users/\(username)"
AF.request(url).validate().responseDecodable(of: Profile.self) { response in
if let value = response.value {
print("GitHub User: \(value)")
self.idLabel.text! += value.getLogin()
self.nameLabel.text! += value.getName()
self.regionLabel.text! += value.getRegion()
self.followersLabel.text! += value.getFollowers()
self.followingLabel.text! += value.getFollowing()
}else {
print("Error: ")
}
}
}
우선 받아올 url 주소를 변수에 저장하고, Alamofire를 사용하기 위해서 AF.request(url).validate().responseDecodable(of: Profile.self)를 작성한다. Profile이 Decodable 프로토콜을 상속 받지 않으면 에러가 날 수 있다.
response를 받아오는 방식은 result와 value 방식이 있는데, response.result 는 Result타입이 반환되고, response.value 는 디코딩된 모델이 반환되기 때문에 value 방식을 사용했다.
value 방식으로 받아왔기 때문에 바로 Profile 안의 메소드를 호출해서 값을 받아왔다.
struct Repository: Decodable {
let id: Int
let node_id: String?
let name: String
let description: String?
let language: String?
enum CodingKeys: CodingKey {
case id
case node_id
case name
case description
case language
}
public func getName() -> String {
return name
}
public func getLanguage() -> String {
if let language = language {
return language
}
return "-"
}
}
우선 Profile을 설계했던 방식으로 Repository도 구조를 설계하고 데이터를 받아 올 수 있도록 메소드도 추가해줬다.
// GitHub API로부터 repository 정보를 가져오는 함수
func fetchRepositories(for user: String) {
let url = "https://api.github.com/users/\(user)/repos"
AF.request(url).responseDecodable(of: [Repository].self) { response in
if let value = response.value {
print(value)
self.dataRepository = value
self.uitableView.reloadData()
}else {
print("Error: ")
}
}
}
Profile을 받아오는 방식과 전체적으로 비슷하지만 다른 부분이라고 하면, Repository는 배열로 받아와야하기 때문에 [Repository]로 작성해주고 데이터를 받아온 후에 셀에 출력이 되어야하기 때문에 reloadData()를 해줬다.
Alamofire를 사용했을 때, 처음 다루는 부분이 많아서 어려웠지만, Kingfisher는 생각보다 사용방법이 단순해서 놀랐다.
아래의 코드처럼 작성하면 원하는 Image파일을 받아올 수 있다.
imageView.contentMode = .scaleAspectFit // 이미지 비율 유지
if let url = URL(string: "https://github.com/\(username).png") {
imageView.kf.setImage(with: url)
}
이번에 과제를 하면서 진짜 두 가지 부분에서 너무 고생과 삽질을 많이하게 된것 같다.
첫번째로는 CollectionView를 처음 사용해보기도 했고, 코드베이스로 UI부분을 작성한 것도 처음이라 Layout을 원하는 방식으로 보여지게 끔 만드는데 12시간정도를 할애한것 같다.
두번째로는 Alamofire 부분에서도 꽤 많은 시간을 할애했는데, 그 원인이 되는게 비동기 방식으로 처리 되기때문에 앱이 먼저 실행이 되고 데이터를 받아오는 문제 때문에 해결하는 부분에서 오래걸리고, 데이터를 받아오는 방식도 처음사용하다 보니깐 삽질을 많이 하게됐다.
