Skip to content

Instantly share code, notes, and snippets.

@martincarlin87
Created June 3, 2020 08:49
Show Gist options
  • Save martincarlin87/0169fe0887a9ef84263b0e9bd4901396 to your computer and use it in GitHub Desktop.
Save martincarlin87/0169fe0887a9ef84263b0e9bd4901396 to your computer and use it in GitHub Desktop.
Swapi Character List Example
import Foundation
struct Character: Decodable, Hashable {
let name: String
let height: String
let mass: String
let hair_color: String
let skin_color: String
let eye_color: String
let birth_year: String
let gender: String
let homeworld: String
let films: [String]
let species: [String]
let vehicles : [String]
let starships: [String]
let created: String
let edited: String
let url: String
}
import Foundation
struct CharactersResponse: Decodable {
let count: Int
let next: String?
let previous: String?
let results: [Character]
}
mport SwiftUI
struct CharacterView: View {
var character: Character?
var body: some View {
VStack(alignment: .leading) {
Text(character?.name ?? "").font(.title)
HStack(alignment: .top) {
Text("Height: \(character?.height ?? "")").font(.subheadline)
Spacer()
Text("Birth Year: \(character?.birth_year ?? "")").font(.subheadline)
}
}
.padding()
}
}
struct CharacterView_Previews: PreviewProvider {
static var previews: some View {
CharacterView()
}
}
import SwiftUI
struct ContentView: View {
@State private var characters: [Character] = []
@State private var page = 1;
@State private var count = 0;
@State private var hideLoadMore = false
@State private var showAlert = false
var body: some View {
NavigationView {
VStack {
List {
Section(header: Text("Characters")) {
ForEach(characters, id: \.self) { character in
NavigationLink(destination: CharacterView(character: character)) {
Text(character.name)
}
}
}
}
.onAppear(perform: loadCharacters)
}
.navigationBarTitle("Swapi Api Client", displayMode: .inline)
.navigationBarItems(
trailing: Button(action: {
self.loadCharacters()
}) {
Text("Load More")
}
.opacity(self.hideLoadMore ? 0 : 1)
.alert(isPresented: $showAlert) {
Alert(title: Text("All characters loaded!"), message: Text("There are no more characters to show!"), dismissButton: .default(Text("Got it!")))
}
)
.listStyle(GroupedListStyle())
}
}
private func loadCharacters() {
// don't load any more if we are already at the limit
if (self.count > 0 && self.characters.count >= self.count) {
print("No more to load")
self.hideLoadMore = true
self.showAlert = true
return
}
let charactersURL = URL(string: "https://swapi.dev/api/people/?page=\(self.page)")!
let url = charactersURL
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let charactersResponse = try? JSONDecoder().decode(CharactersResponse.self, from: data) {
// keep track of how many results there are
self.count = charactersResponse.count
self.page = self.page + 1
DispatchQueue.main.async {
print(charactersResponse.results)
withAnimation {
self.characters.append(contentsOf: charactersResponse.results)
}
}
return
}
}
print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}.resume()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment