Using Mock Data
Published by @SoNiceInfo at 6/24/2020
Overview
By using the json mock data, you can verify your UI without having to develop an API.
We'll follow the MVVM pattern, and once we've implemented the API, we'll be able to transition seamlessly.
We'll take SwiftUI Tutorial Building Lists and Navigation as a reference.
I recommend to see Using API Data after this lesson.
Guide
We're going to make an app that displays a list of TV programs.
The creation process is as follows
The structure of the folder looks like the one on the right.
- Creating a Model (
ProgramModel.swift
) - Creating Mock Data (
ProgramData.json
) - Create a Helper to Load the Mock Data (
DataLoad.swift
) - Creating a ViewModel and View (
ProgramView.swift
)
Creating a Model (ProgramModel.swift
)
Model defines the struct of the data.
structs can be nested.
A TV program has id, name, summary and image (medium size).
//
// ProgramModel.swift
//
import SwiftUI
struct Img: Hashable, Codable {
var large: String?
var medium: String?
var small: String?
}
struct Program: Hashable, Codable {
let id: Int
let name: String
let summary: String
let image: Img
}
Creating Mock Data (ProgramData.json
)
Prepare mock data.
Mock data is prepared in json format.
[
{"id": 0, "name": "あるぱか散歩", "summary": "あるぱかさんといっしょに街歩きをしましょう", "image": { "medium": "animal_arupaka"}},
{"id": 1, "name": "ブタトーク", "summary": "MCぶったさんの独壇場", "image": { "medium": "animal_buta"}},
{"id": 2, "name": "とっとこはむはみー", "summary": "はむはみーが大冒険", "image": { "medium": "animal_hamster"}},
{"id": 3, "name": "ひよっと", "summary": "ひよっとちゃんがいろんなことに挑戦するよ", "image": { "medium": "animal_hiyoko"}},
{"id": 4, "name": "わんさんといっしょ", "summary": "わんさんといっしょに歌ったり踊ったりしよう", "image": { "medium": "animal_inu"}}
]
Register the json file to Bundle Resources section of Build Phases in Targets.
Create a Helper to Load the Mock Data (DataLoad.swift
)
Create a helper to load the mock data into the shape of the model.
We'll take SwiftUI Tutorial Building Lists and Navigation as a reference.
I think this can be used generally other than this Program.
//
// DataLoad.swift
//
import SwiftUI
func dataLoad<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Creating a ViewModel and View (ProgramView.swift
)
Call the data using the helper in ProgramViewModel
.
Understanding Property Wrappers also show you how to use ObservableObject
. Finally, call ProgramView.swift
from ContentView.Swift
.
//
// ProgramView.swift
//
import SwiftUI
class ProgramViewModel: ObservableObject {
@Published var data: [Program] = []
init() {
self.data = dataLoad("programData.json")
}
}
struct ProgramView: View {
@ObservedObject var programVM = ProgramViewModel()
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 10) {
// Process the Program in sequence
ForEach(programVM.data, id: \.id) { (program) in
ZStack(alignment: .bottom) {
Image(program.image.medium)
.resizable()
.scaledToFill()
.frame(width: UIScreen.main.bounds.width, height: 300)
.background(LinearGradient(gradient: Gradient(colors: [.yellow, .red, .purple]), startPoint: .bottomLeading, endPoint: .topTrailing))
.clipShape(RoundedRectangle(cornerRadius: 20))
VStack {
Text(program.name)
.font(.largeTitle)
.foregroundColor(.white)
Text(program.summary)
.foregroundColor(.white)
}
}
}
}
}
}
}
struct ProgramView_Previews: PreviewProvider {
static var previews: some View {
ProgramView()
}
}
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
var body: some View {
ProgramView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}