IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> SwiftUI优秀文章经典案例制作简易的新闻列表Demo -> 正文阅读

[移动开发]SwiftUI优秀文章经典案例制作简易的新闻列表Demo

SwiftUI制作简易的新闻列表Demo

import SwiftUI

struct HomeView: View {
   @StateObject var  newsViewModelVM = NewsViewModel()
   var body: some View {
       ZStack{
           Group{
               switch newsViewModelVM.state{
               case .loading:
                   ProgressView()
               case .failed(let error):
                   ErrorView(error: error) {
                       newsViewModelVM.getArticels()
                   }
               case .success(let articels):
                   NavigationView{
                       List(articels){ item in
                           PostCellView(article: item)
                       }
                       .listStyle(.plain)
                       .navigationTitle(Text("News"))
                   }
               }
           }
           .onAppear {
               newsViewModelVM.getArticels()
           }
           
           Text("Desgin By Lujun 2022.2.8")
               .font(.system(size: 30).bold())
               .foregroundColor(.orange)
               .shadow(color: .black, radius: 5, x: 5, y: 5)
               .offset(y: 300)
       }
    }
}
struct NewsModel: Codable {
    let articles: [Article]
}
// MARK: - Article
struct Article: Codable,Identifiable {
    var id = UUID()
    let author: String?
    let url: String?
    let source, title, articleDescription: String?
    let image: String?
    let date: Date?

    enum CodingKeys: String, CodingKey {
        case author, url, source, title
        case articleDescription = "description"
        case image, date
    }
}

错误自定义

enum APIError: Error {
    case decodingError
    case errorCode(Int)
    case unknow
}
extension APIError: LocalizedError{
    var errorDescription: String?{
        switch self {
        case .decodingError:
            return "failurs"
        case .errorCode(let code):
            return "\(code) -somethinds error"
        case .unknow:
            return "the error in unknown"
        }
    }
}

请求数据流核心

import SwiftUI
import Combine

enum ResultState{
    case loading
    case success(content: [Article])
    case failed(error: APIError)
}

let baseURL = "http://localhost:8081/"
class NewsViewModel: ObservableObject {
    @Published  var state: ResultState = .loading
    private  var aticels = [Article]()
    private  var cancelables = Set<AnyCancellable>()
    func getArticels(){
        let cancellable = request(from: "http://localhost:8081/news.json")
            .sink { res in
                switch res{
                case .finished:
                    self.state = .success(content: self.aticels)
                case .failure(let error):
                    self.state = .failed(error: error)
                    
                }
            } receiveValue: { response in
                self.aticels = response.articles
            }
        self.cancelables.insert(cancellable)
        
    }
    func request(from apiUrl: String) -> AnyPublisher<NewsModel,APIError>{
        URLSession.shared
            .dataTaskPublisher(for: URL(string: apiUrl)!)
            .receive(on: DispatchQueue.main)
            .mapError{_ in APIError.unknow}
            .flatMap{data,response -> AnyPublisher<NewsModel,APIError> in
                guard let response = response as? HTTPURLResponse else {
                    return Fail(error: APIError.unknow).eraseToAnyPublisher()
                }
                if (200...299).contains(response.statusCode) {
                    let jsonDeconder = JSONDecoder()
                    jsonDeconder.dateDecodingStrategy = .iso8601
                    return Just(data)
                        .decode(type: NewsModel.self, decoder: jsonDeconder)
                        .mapError{_ in APIError.decodingError}
                        .eraseToAnyPublisher()
                }else{
                    return Fail(error: APIError.errorCode(response.statusCode)).eraseToAnyPublisher()
                }
            }
           .eraseToAnyPublisher()
    }
    
}

postCell核心

import SDWebImageSwiftUI
struct PostCellView: View {
    let article: Article
    var body: some View {
        HStack{
            if let imgUrl = article.image,
               let url = URL(string: String(format: "%@%@", baseURL,imgUrl)) {
                WebImage(url: url)
                    .placeholder(content: {
                        Color.gray
                    })
                    .resizable()
                    .scaledToFill()
                    .frame(width: 100, height: 100)
                    .cornerRadius(10)
             }else{
                Image(systemName: "photo.fill")
                    .foregroundColor(.white)
                    .background(Color.gray)
                    .frame(width: 100, height: 100)
                    .cornerRadius(10)
            }
            
            VStack(alignment: .leading, spacing: 4){
                Text(article.title ?? "")
                    .foregroundColor(.black)
                    .font(.system(size: 18, weight: .semibold))
                Text(article.source ?? "N/A")
                    .foregroundColor(.gray)
                    .font(.footnote)
             }
         }
        .padding(.vertical
        ,10)
    }
}

自定义错误View核心

struct ErrorView: View {
    typealias ErrorViewActionHander = () -> Void
    let hander : ErrorViewActionHander
    internal init(error: Error,
                  hander: @escaping ErrorView.ErrorViewActionHander
    ){
        self.error = error
        self.hander = hander
    }
    
    let error: Error
    var body: some View {
        VStack{
            Image(systemName: "exclamationmark.icloud.fill")
                .foregroundColor(.gray)
                .font(.system(size: 50, weight: .heavy))
            Text("some error")
                .font(.system(size: 30))
                .fontWeight(.bold)
            Text(error.localizedDescription)
                .padding(4)
            Button {
                hander()
            } label: {
                Text("retry")
            }
            .foregroundColor(.white)
            .padding(.vertical,17)
            .padding(.horizontal,30)
            .background(Color.blue)
            .font(.system(size: 15, weight: .heavy))
            .cornerRadius(10)

        }
    }
}

数据api来源 https://api.lil.software/news,需要未批嗯

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-09 20:49:02  更:2022-02-09 20:49:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 14:24:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码