SwiftUI中級之List顯示本地Json文件(2020年教程)
SwiftUI中級之List顯示本地Json文件(2020年教程)
看看數據
LandmarkData.json
[
{
"name": "Turtle Rock",
"category": "Featured",
"city": "Twentynine Palms",
"state": "California",
"id": 1001,
"park": "Joshua Tree National Park",
"coordinates": {
"longitude": -116.166868,
"latitude": 34.011286
},
"imageName": "turtlerock"
},
{
"name": "Silver Salmon Creek",
"category": "Lakes",
"city": "Port Alsworth",
"state": "Alaska",
"id": 1002,
"park": "Lake Clark National Park and Preserve",
"coordinates": {
"longitude": -152.665167,
"latitude": 59.980167
},
"imageName": "silversalmoncreek"
},
{
"name": "Chilkoot Trail",
"category": "Rivers",
"city": "Skagway",
"state": "Alaska",
"id": 1003,
"park": "Klondike Gold Rush National Historical Park",
"coordinates": {
"longitude": -135.334571,
"latitude": 59.560551
},
"imageName": "chilkoottrail"
},
{
"name": "St. Mary Lake",
"category": "Lakes",
"city": "Browning",
"state": "Montana",
"id": 1004,
"park": "Glacier National Park",
"coordinates": {
"longitude": -113.536248,
"latitude": 48.69423
},
"imageName": "stmarylake"
},
{
"name": "Twin Lake",
"category": "Lakes",
"city": "Twin Lakes",
"state": "Alaska",
"id": 1005,
"park": "Lake Clark National Park and Preserve",
"coordinates": {
"longitude": -153.849883,
"latitude": 60.641684
},
"imageName": "twinlake"
},
{
"name": "Lake McDonald",
"category": "Lakes",
"city": "West Glacier",
"state": "Montana",
"id": 1006,
"park": "Glacier National Park",
"coordinates": {
"longitude": -113.934831,
"latitude": 48.56002
},
"imageName": "lakemcdonald"
},
{
"name": "Charley Rivers",
"category": "Rivers",
"city": "Eaking",
"state": "Alaska",
"id": 1007,
"park": "Charley Rivers National Preserve",
"coordinates": {
"longitude": -143.122586,
"latitude": 65.350021
},
"imageName": "yukon_charleyrivers"
},
{
"name": "Icy Bay",
"category": "Lakes",
"city": "Icy Bay",
"state": "Alaska",
"id": 1008,
"park": "Wrangell-St. Elias National Park and Preserve",
"coordinates": {
"longitude": -141.518167,
"latitude": 60.089917
},
"imageName": "icybay"
},
{
"name": "Rainbow Lake",
"category": "Lakes",
"city": "Willow",
"state": "Alaska",
"id": 1009,
"park": "State Recreation Area",
"coordinates": {
"longitude": -150.086103,
"latitude": 61.694334
},
"imageName": "rainbowlake"
},
{
"name": "Hidden Lake",
"category": "Lakes",
"city": "Newhalem",
"state": "Washington",
"id": 1010,
"park": "North Cascades National Park",
"coordinates": {
"longitude": -121.17799,
"latitude": 48.495442
},
"imageName": "hiddenlake"
},
{
"name": "Chincoteague",
"category": "Rivers",
"city": "Chincoteague",
"state": "Virginia",
"id": 1011,
"park": "Chincoteague National Wildlife Refuge",
"coordinates": {
"longitude": -75.383212,
"latitude": 37.91531
},
"imageName": "chincoteague"
},
{
"name": "Lake Umbagog",
"category": "Lakes",
"city": "Errol",
"state": "New Hampshire",
"id": 1012,
"park": "Umbagog National Wildlife Refuge",
"coordinates": {
"longitude": -71.056816,
"latitude": 44.747408
},
"imageName": "umbagog"
}
]
讀取json并轉化為數組
- 定義一個struck存儲數據
import SwiftUI
import CoreLocation
struct Landmark: Hashable, Codable, Identifiable {
var id: Int
var name: String
fileprivate var imageName: String
fileprivate var coordinates: Coordinates
var state: String
var park: String
var category: Category
var locationCoordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: coordinates.latitude,
longitude: coordinates.longitude)
}
enum Category: String, CaseIterable, Codable, Hashable {
case featured = "Featured"
case lakes = "Lakes"
case rivers = "Rivers"
}
}
extension Landmark {
var image: Image {
ImageStore.shared.image(name: imageName)
}
}
struct Coordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
- 從json中提取數據
// data.swift
import UIKit
import SwiftUI
import CoreLocation
let landmarkData: [Landmark] = load("landmarkData.json")
func load<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)")
}
}
final class ImageStore {
typealias _ImageDictionary = [String: CGImage]
fileprivate var images: _ImageDictionary = [:]
fileprivate static var scale = 2
static var shared = ImageStore()
func image(name: String) -> Image {
let index = _guaranteeImage(name: name)
return Image(images.values[index], scale: CGFloat(ImageStore.scale), label: Text(name))
}
static func loadImage(name: String) -> CGImage {
guard
let url = Bundle.main.url(forResource: name, withExtension: "jpg"),
let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil),
let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
else {
fatalError("Couldn't load image \(name).jpg from main bundle.")
}
return image
}
fileprivate func _guaranteeImage(name: String) -> _ImageDictionary.Index {
if let index = images.index(forKey: name) { return index }
images[name] = ImageStore.loadImage(name: name)
return images.index(forKey: name)!
}
}
顯示數據
- 先定義一下row
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView(coordinate: landmark.locationCoordinate)
.edgesIgnoringSafeArea(.top)
.frame(height: 300)
CircleImage(image: landmark.image)
.offset(x: 0, y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
HStack(alignment: .top) {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
}
.padding()
Spacer()
}
.navigationBarTitle(Text(landmark.name), displayMode: .inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
- 定義一下詳細頁
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView(coordinate: landmark.locationCoordinate)
.edgesIgnoringSafeArea(.top)
.frame(height: 300)
CircleImage(image: landmark.image)
.offset(x: 0, y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
HStack(alignment: .top) {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
}
.padding()
Spacer()
}
.navigationBarTitle(Text(landmark.name), displayMode: .inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
- 拼接成主頁面
import SwiftUI
struct ListJsonFromFileView: View {
var body: some View {
NavigationView {
List(landmarkData) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}
struct ListJsonFromFileView_Previews: PreviewProvider {
static var previews: some View {
ListJsonFromFileView()
}
}
效果
更多SwiftUI教程和代碼關注專欄
- 請關注我的專欄 SwiftUI教程與源碼
智能推薦
SwiftUI 高級List分頁與無限滾動之基礎版(2020教程)
盡管我們可以訪問List中的具體item,但是我們不知道List滾動到了當前哪個位置,也不知道我們到List末尾的距離。這些數據都是我們進行分頁到基礎。 Pagination(分頁)對于每個人都有不同的含義,因此我們先給我分頁的目標做個明確定義: 在滾動過程中,List應提取并追加下一頁的數據。當用戶到達列表末尾且請求仍在進行中時,應顯示加載視圖。 基于上面的定義,讓我們實現一個解決方案來解決這些...
SwiftUI 入門之Image設置大小并居中(2020年教程)
SwiftUI 入門之Image設置大小并居中(2020年教程) 技術要點 如何獲取屏幕大小 如何設置照片大小適中 代碼 效果 Image設置大小并居中 更多SwiftUI教程和代碼關注專欄 請關注我的專欄 SwiftUI教程與源碼...
SwiftUI 基礎之05 list 和 searchbar (2020)
SwiftUI 基礎之05 list 和 searchbar (2020) 首要 searchbar 效果圖 image.png 參考資料 https://medium.com/better-programming/implement-searchbar-in-swiftui-556a204e1970...
SwiftUI 基礎之02 NavigationView和List(2020)
SwiftUI 基礎之NavigationView和List(2020) 效果 [email protected] 更多SwiftUI教程和代碼關注專欄 請關注我的專欄 SwiftUI教程與源碼...
猜你喜歡
SwiftUI List 如何顯示dictionary
本文價值與收獲 看完本文后,您將能夠作出下面的界面 看完本文您將掌握的技能 list基礎使用 顯示dictionary 代碼 技術交流 QQ:3365059189 SwiftUI技術交流QQ群:518696470...
SwiftUI 開發腳手架含Tab List Navigation (2020年版)
SwiftUI 開發腳手架含Tab List Navigation (2020年版) 代碼 SwiftUI 開發腳手架 更多SwiftUI教程和代碼關注專欄 請關注我的專欄 SwiftUI教程與源碼...
SwiftUI 復用舊項目代碼之UIViewcontroller(2020版教程)
SwiftUI 復用舊項目代碼之UIViewcontroller(2020版教程) SwiftUI 非常好用,開發界面高效快捷,但是具體到業務層面,復用歷史代碼是必須要研究到事情。 如何在SwiftUI中調用UIViewcontroller 1、 創建一個 Wrapper 例如我們有個Example1ViewController舊代碼,我們可以先通過UIViewControllerRepresen...
SwiftUI 動畫控制運行軌跡之Curve(2020教程)
歡迎訂閱專欄《SwiftUI 2020教程》 本文價值與收獲 看完本文后,您將能夠作出下面的動畫 四種內置曲線運動效果 四種內置曲線運動效果 看完本文您將掌握的技能 掌握4種內置動畫曲線使用 實現移動 實現顏色變換 欣賞遠古壁畫 QQ:3365059189 SwiftUI技術交流QQ群:518696470 動畫曲線是一種在整個動畫過程中表達速度的方式。在前面的示例中,您看到了“ eas...
SwiftUI Text高級用法3D旋轉rotation3DEffect(2020年教程)
SwiftUI Text高級用法3D旋轉rotation3DEffect(2020年教程) 代碼 效果 SwiftUI Text高級用法...