ios开发: 从接口获取数据列表并显示

一,代码

1,接口返回的json

{
  "status": "success",
  "code": 200,
  "time": "2026-03-29 21:39:27",
  "msg": "",
  "data": {
    "list": [
      {
        "id": 1,
        "author": "李白",
        "title": "静夜思",
        "image": "https://imgs-qn.test.com/ware/sowhatimg/ware/orig/2/39/39653.png"
      },
      {
        "id": 2,
        "author": "孟浩然",
        "title": "宿建德江",
        "image": "https://imgs-qn.test.com/ware/sowhatimg/ware/orig/2/39/39651.png"
      },
      {
        "id": 3,
        "author": "杨万里",
        "title": "晓出净慈寺送林子方",
        "image": "https://imgs-qn.test.com/ware/slider/1938.png"
      },
      {
        "id": 4,
        "author": "李白",
        "title": "望庐山瀑布",
        "image": "https://imgs-qn.test.com/ware/slider/1938.png"
      },
      {
        "id": 5,
        "author": "author5",
        "title": "title5",
        "image": "https://imgs-qn.test.com/ware/goods/big/2/284/284909.jpg"
      },
      {
        "id": 6,
        "author": "author6",
        "title": "title6",
        "image": "https://imgs-qn.test.com/ware/goods/big/2/284/284909.jpg"
      }
    ]
  }
}

 

2, 列表页面

ContentView

//
//  ContentView.swift
//  helloworld2
//
//  Created by liuhongdi on 2026/3/28.
//

import SwiftUI
import Alamofire


struct ContentView: View {
    @State private var message = "加载中..."
    var urlString = "http://www.test.net/list.php";

        @State private var poems: [Poem] = [] // 存储解析后的数组
    
         var body: some View {

             NavigationStack {
                 VStack {
                     Text(message)

                     List(poems) { poem in
                         // value: poem 会将整个对象传递给路由系统
                         NavigationLink(value: poem) {
                             HStack(spacing: 15) {
                                 AsyncImage(url: URL(string: poem.image)) { image in
                                     image.resizable().aspectRatio(contentMode: .fit)
                                 } placeholder: {
                                     ProgressView()
                                 }
                                 .frame(width: 90, height: 90)
                                 .background(Color.purple)
                                 .cornerRadius(8)
                                 
                                 VStack(alignment: .leading, spacing: 5) {
                                     Text(poem.title).font(.headline)
                                     Text(poem.author).font(.subheadline).foregroundColor(.secondary)
                                 }
                             }
                         }
                         
                     }
                     .navigationTitle("古诗精选")
                     // 路由拦截器:当检测到目的地传递的值是 PoemItem 类型时,跳转到 DetailView
                     .navigationDestination(for: Poem.self) { poem in
                         DetailView(id: poem.id)
                     }
                 }
             }
             
             .task {
                 await fetchData()
             }
         }
         
         
         /// 获取数据
         func fetchData() async {

             let request = AF.request(urlString).serializingDecodable(ApiResponse<PoemListData>.self)
                let response = await request.response
                
                switch response.result {
                case .success(let apiResponse):
                    // 这里的 apiResponse.data 就是 PoemListData 类型
                    self.poems = apiResponse.data.list
                    print("请求成功,时间:\(apiResponse.time)")

                case .failure(let error):
                    print("解析错误: \(error)")
                }
         }
         
}

#Preview {
    ContentView()
}

3,详情页面

DetailView

import SwiftUI

struct DetailView: View {
    let id: Int // 接收传递过来的 id

    var body: some View {
        VStack(spacing: 20) {
            Text("诗词详情页")
                .font(.title)
            
            Text("当前查看的诗词 ID 是: \(id)")
                .padding()
                .background(Color.purple.opacity(0.1))
                .cornerRadius(10)
            
            Spacer()
        }
        .navigationTitle("详情")
        // SwiftUI 默认在导航跳转时提供“从右向左”的滑动动画
    }
}

4,model类

ApiResponse


import Foundation

// 使用泛型 T,并约束 T 必须符合 Decodable 协议
struct ApiResponse<T: Decodable>: Decodable {
    let status: String
    let code: Int
    let time: String
    let msg: String
    let data: T  // 这里可以是任何类型:List 结构体、单个对象、甚至是一个数组
}

// 针对你当前接口的具体数据结构
struct PoemListData: Decodable {
    let list: [Poem]
}

struct Poem: Decodable, Identifiable, Hashable {
    let id: Int
    let author: String
    let title: String
    let image: String
}

 

二,测试效果:

image

 

posted @ 2026-03-29 22:08  刘宏缔的架构森林  阅读(1)  评论(0)    收藏  举报