DownloadWithEscaping/下载数据并且转义返回数据, DownloadWithCombine/下载数据并且组合数据 的使用

news2024/11/15 19:45:21

1. DownloadWithEscaping 下载数据并且转义返回数据

  1.1 实现

struct PostDataModel:Identifiable, Codable {
    let userId: Int
    let id: Int
    let title: String
    let body: String
}

/// ViewModel
class DownloadWithEscapingViewModel: ObservableObject{
    @Published var posts: [PostDataModel] = []
    
    init() {
        getPosts()
    }
    
    // post 请求
    func getPosts(){
        // https://jsonplaceholder.typicode.com/posts
        // https://jsonplaceholder.typicode.com/posts/1
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else{ return }
        
        downloadData(formURL: url) { returnedData in
            if let data = returnedData{
                // 解码模型
                guard let newPosts = try? JSONDecoder().decode([PostDataModel].self, from: data) else { return }
                
                DispatchQueue.main.async { [weak self] in
                    // 添加到数组中
                    //self?.posts.append(newPost)
                    self?.posts = newPosts
                }
            }else{
                print("No data returned.")
            }
        }
    }
    
    
    /// 封装请求接口 formURL:  外部名称   @escaping: 转义闭包
    func downloadData(formURL url: URL, completionHandler: @escaping (_ data: Data?) -> ()){
        URLSession.shared.dataTask(with: url) { data, response, error in
            // 检查有没有数据
            //guard let data = data else{
            //    print("No data.")
            //    return
            //}
            
            // 检查有没有错误
            //guard error == nil else{
            //    print("Error: \(String(describing: error))")
            //    return
            //}
            
            // 判断返回 httpurl 响应
            //guard let response = response as? HTTPURLResponse else{
            //    print("Invalid response.")
            //    return
            //}
            
            // 判断返回状态码
            //guard response.statusCode >= 200 && response.statusCode < 300 else{
            //    print("Status code should be 2xx, but is \(response.statusCode)")
            //    return
            //}
            
            // 打印接收数据
            //print("Successfully downloaded data!")
            //print(data)
            //let jsonData = String(data: data, encoding: .utf8)
            //print(jsonData ?? "")
            
            guard let data = data,
                  error == nil,
                  let response = response as? HTTPURLResponse,
                  response.statusCode >= 200 && response.statusCode < 300 else{
                print("Error downloading data.")
                completionHandler(nil)
                return
            }
            // 返回数据
            completionHandler(data)
        }.resume()
    }
}

/// 下载并且转义
struct DownloadWithEscapingBootcamp: View {
    @StateObject var vm = DownloadWithEscapingViewModel()
    
    var body: some View {
        List {
            ForEach(vm.posts) { post in
                VStack(alignment: .leading) {
                    Text(post.title)
                        .font(.headline)
                    Text(post.body)
                        .foregroundColor(.gray)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
        }
    }
}

  1.2 效果图:

2. DownloadWithCombine 下载数据并且组合使用数据

  2.1 实现

import Combine

struct PostModel:Identifiable, Codable {
    let userId: Int
    let id: Int
    let title: String
    let body: String
}

// ViewModel
class DownloadWithCombineViewModel: ObservableObject{
    @Published var posts:[PostModel] = []
    // 是否取消请求
    var cancellables = Set<AnyCancellable>()
    
    init() {
        getPosts()
    }
    
    // 获取数据
    func getPosts(){
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else{ return }
        
        // Combine discussion:
        /*
        // 1. 注册信息,按月订阅一个包裹,订阅后然后发送给公司
        // 2. 公司将制做包裹,因此工厂继续制作他们的包裹
        // 3. 制作完包裹,然后运送包裹,您可能会在门前收到包裹
        // 4. 您将检查箱子,确保箱子没有损坏
        // 5. 打开并确保商品无误
        // 6. 最终可以使用
        // 7. 订阅的包裹,可以随时取消
        
        // 1. 创建发布者
        // 2. 后台线程上订阅发布者
        // 3. 主线程上接收
        // 4. tryMap 检查数据是否完好
        // 5. 解码 (解码数据到模型(PostModel))
        // 6. sink,进行同步,并将 item 放入项目
        // 7. store (随时取消订阅)
         */
        URLSession.shared.dataTaskPublisher(for: url)
            //.subscribe(on: DispatchQueue.global(qos: .background))
            .receive(on: DispatchQueue.main)
            .tryMap(handleOutput)
            .decode(type: [PostModel].self, decoder: JSONDecoder())
             // 不想处理错误信息,简单写法
            .replaceError(with: []) // 替代错误
            .sink(receiveValue: { [weak self]returnedPosts in
                self?.posts = returnedPosts
            })
            /*.sink { completion in
                // 打印信息 -> 包含 URLError
                //print("Completion: \(completion)")
                switch completion {
                case .finished:
                    print("Finished")
                case .failure(let error):
                    print("There was an error: \(error)")
                }
            } receiveValue: {[weak self] returnedPosts in
                self?.posts = returnedPosts
            }*/
            .store(in: &cancellables)
    }
    
    // 抽取函数
    func handleOutput(output: URLSession.DataTaskPublisher.Output) throws -> Data{
        guard let response = output.response as? HTTPURLResponse,
              response.statusCode >= 200 && response.statusCode < 300 else{
            throw URLError(.badServerResponse)
        }
        return output.data
    }
}

// 组合操作
struct DownloadWithCombine: View {
    @StateObject var viewModel = DownloadWithCombineViewModel()
    
    var body: some View {
        List {
            ForEach(viewModel.posts) { post in
                VStack(alignment: .leading) {
                    Text(post.title)
                        .font(.headline)
                    Text(post.body)
                        .foregroundColor(.gray)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
        }
    }
}

  2.2 效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1048029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode-中等题】654.最大二叉树

文章目录 题目方法一&#xff1a;递归 题目 方法一&#xff1a;递归 class Solution {int[] num null; public TreeNode constructMaximumBinaryTree(int[] nums) {num nums;return myTree(0,num.length-1);}public TreeNode myTree( int begin , int end){if(begin > end…

什么是RESTful API?它的设计原则是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是RESTful API&#xff1f;RESTful API的设计原则示例 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感…

【数据结构】直接插入排序 希尔排序(一)

目录 一&#xff0c;排序的概念 二&#xff0c;直接插入排序 1&#xff0c;基本思想 2&#xff0c;基本思路 3&#xff0c;思路实现 三&#xff0c;希尔排序 1&#xff0c;希尔排序的特性总结&#xff1a; 2&#xff0c;思路实现&#xff1a; 一&#xff0c;排序的概念…

基于SpringBoot+Vue 的游戏分享网站

1 简介 基于Java SpringBoot 的游戏分享网站&#xff0c;本系统主要包括管理员和用户两个角色组成&#xff1b;主要包括首页、个人中心、用户管理、游戏类型管理、游戏文章管理、交流论坛、系统管理等功能的管理系统。 文章首发地址 2 技术栈 开发语言&#xff1a;Java 框架…

EV代码签名证书的作用有哪些?如何获取呢?

我们都知道&#xff0c;黑客们往往会通过篡改软件代码来进行各种恶意行为&#xff0c;例如加入病毒、木马、恶意代码等&#xff0c;为了确保软件代码的完整性和可信任性&#xff0c;代码签名证书诞生了。代码签名证书又分为普通代码签名证书和EV代码签名证书&#xff0c;我们在…

P1003 [NOIP2011 提高组] 铺地毯(Arknights!)

[NOIP2011 提高组] 铺地毯 题目描述 为了准备一个独特的颁奖典礼&#xff0c;组织者在会场的一片矩形区域&#xff08;可看做是平面直角坐标系的第一象限&#xff09;铺上一些矩形地毯。一共有 n n n 张地毯&#xff0c;编号从 1 1 1 到 n n n。现在将这些地毯按照编号从小…

「私信分析」上线,帮助企业进行私信管理,提升营销线索转化

企业在新媒体矩阵建设过程中会出现各种各样的业务难题&#xff0c;为了更好地服务客户&#xff0c;矩阵通将秉持“为客户带来实际业务价值”的原则不断地优化产品功能。 矩阵通是新榜旗下的新媒体数字化内容资产管理SaaS&#xff0c;可以帮助企业解决跨平台账号运营难题&#x…

django_auth_ldap登录权限

用户登录权限分为三种&#xff0c;通过is_active,is_staff,is_superuser标识。可以对组赋予对应的权限。 设定active组、staff组和superuser组分别对应三种权限。在不同组权限下的登录情况如下&#xff1a; 当用户不属于任何一组&#xff1a; 登录失败&#xff0c;提示如图&a…

k8s如何快速部署tomcat

环境 三台云服务器 步骤 部署tomcat kubectl create deployment tomcat6 --imagetomcat:6.0.53-jre8kubectl get pods -o wide 可以获取到 tomcat 信息暴露端口 kubectl expose deployment tomcat6 --port80 --target-port8080 --typeNodePort查看service端口 kubectl ge…

[ESP32 IDF+Vscode]OLED多级菜单显示(摇杆控制)

ADC介绍 ESP32集成了两个 12位SAR(逐次逼近寄存器)adc &#xff0c;共支持18个测量通道。 1、两个 ADC 通道简介&#xff1a; ADC1&#xff1a; 支持 8 个通道&#xff0c;包括&#xff1a;GPIO32 - GPIO39&#xff08;并非按顺序&#xff09; ADC2&#xff1a; 支持 10 …

DataBinding双向绑定简介

一、简介 在Vue中使用的是MVVM架构。通过ViewModel可以实现M层和V层数据的双向绑定。Model层的数据发生变化后&#xff0c;会自动更新View层UI。UI层数据发生变化&#xff08;用户输入&#xff09;&#xff0c;可以驱动Model层的数据发生变化&#xff0c;借助于Vue框架中的View…

数学建模国赛/美赛常见赛题类型及建模方案(纯干货)(2)

目录 一&#xff0c;评价类问题 1&#xff0c;建模步骤如下图所示&#xff1a; 2&#xff0c;主客观评价问题的区别 3&#xff0c;如何选择合适的评价方法 二&#xff0c;预测类赛题 1&#xff0c;预测类赛题的基本解题步骤 2&#xff0c;预测类问题的区别 3&#xff0c;…

深兰科技荣获“2023年中国人工智能行业十大创新力企业奖”

近日&#xff0c;以“i时代智创未来”为主题的“CIAI 2023第八届中国国际人工智能大会“在上海普陀区隆重召开。 大会期间&#xff0c;举行了”2023年中国人工智能行业创新力企业评选“的颁奖典礼&#xff0c;深兰科技(上海)有限公司成功荣获“2023年中国人工智能行业十大创新力…

HTTP初识,fiddler的使用,URL各部分介绍,QueryString

目录 一、什么是HTTP 二、抓包工具 三、请求的首行 URL 四、URL的各部分详细介绍 一、什么是HTTP 现在网页上&#xff0c;我们常见的是https,但是在二十年前是以http为主&#xff0c;这个协议也叫超文本传输协议&#xff0c;文本->字符串&#xff0c;“超文本”->图片…

Nginx代理victoriametrics集群配置

1,首先安装nginx yum install -y nginx 2,生成密钥文件 安装htpasswd工具 yum install -y httpd-tools 生成密钥文件,prometheus为用户名 htpasswd -c /etc/nginx/conf.d/passwd prometheus 3,修改nginx配置文件nginx.conf,增加如下内容 upstream vmselect {server 10.…

PyTorch - Dataset 迭代数据接口 __getitem__ 异常处理

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/133378772 在模型训练的过程中&#xff0c;加载数据部分&#xff0c;极其容易出现异常&#xff0c;以及不可控的因素&#xff0c;需要通过异常捕获…

RabbitMQ(15672) 消息中间件 NOTE

目录 1、初识 RabbitMQ 消息队列 1.1 MQ 四大核心概念 1.2 消息的发送&#xff08;无交换机态&#xff09; 1.3 关于消息自动重新入队 1.3.1 消息的常见应答方法&#xff08;R&#xff09; 1.4 关于 RabbitMQ 的持久化、不公平分发以及预取值 2、RabbitMQ 消息的发布确认…

Timer/计时器发布者与订阅者, Subscribar/文本框订阅模式 的使用

1. Timer 计时器的操作 1.1 实现 /// 计时器 发布者与订阅者 struct TimerBootcamp: View {// 计时器 发布者 timer1/timer3/timer5 1.0 , timer2 2.0 , timer4 0.5let timer Timer.publish(every: 1, on: .main, in: .common).autoconnect()// ---1---// 计算性属性 当前…

线性代数(七) 矩阵分析

前言 从性线变换我们得出&#xff0c;矩阵和函数是密不可分的。如何用函数的思维来分析矩阵。 矩阵的序列 通过这个定义我们就定义了矩阵序列的收敛性。 研究矩阵序列收敛性的常用方法&#xff0c;是用《常见向量范数和矩阵范数》来研究矩阵序列的极限。 长度是范数的一个特…

C语言实现---通讯录

通讯录 前言1.初始化通讯录2.SHOW展示通讯录3.ADD添加联系人的函数4.DEL删除联系人的函数5.SEARCH查找联系人的函数6.MODIFY修改联系人的函数7.销毁通讯录8.整体代码展示1.头文件"contact.h"2.源文件"contact.c"3.测试文件"test.c" 前言 那么好…