本节内容
- Codable 解码以解析json
- swift 的异常处理方法
知识点
- Codable 可编码
A type that can convert itself into and out of an external representation.
一个可以将自己转换为和脱离外部表示的类型。
通常是创建一个实例对象,在实例对象中创建与json文件相对应名称和类型的实例变量(实例变量可以少于json文件中对应名称的个数)。然后,将json文件解码成对应的实例对象,然后就可以通过实例对象进行全局访问。
- try 异常处理
Swift2.0 后加入了新的关键字 try? , 如果不想处理异常那么可以用这个关键字,使用这个关键字返回一个可选值类型,如果有异常出现,返回nil.如果没有异常,则返回可选值。
- try 出现异常处理异常
- try? 不处理异常,返回一个可选值类型,出现异常返回nil
- try! 不让异常继续传播,一旦出现异常程序停止,类似NSAssert()
// 三种方法处理异常
// 方法1 推荐 try? 如果解析成功就有值,否则为 nil
let list1 = try?JSONDecoder().decode(PostList.self, from: data)
print(list1 ?? "None")
// 方法2 使用try 处理异常,能够接收到错误,并且输出。但是,语法结构复杂。
do {
let list2 = try JSONDecoder().decode(PostList.self, from: data)
print(list2);
} catch {
print(error);
}
// 方法3 不推荐 try! 如果解析成功就有值,否则崩溃
let list3 = try!JSONDecoder().decode(PostList.self, from: data)
print(list3)
- guard 守护
guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句。
guard expression else {
//语句
//必须包含一个控制语句:return,break,continue或throw。
}
// 这里,expression是一个布尔表达式(返回true或者false)。
// 如果对表达式求值false,guard则执行代码块内的语句。
// 如果对表达式求值true,guard则从执行中跳过代码块内的语句
guard语句和if语句有点类似,都是根据其关键字之后的表达式的布尔值决定下一步执行什么。但与if语句不同的是,guard语句只会有一个代码块,不像if语句可以if else多个代码块。
guard let list = try?JSONDecoder().decode(PostList.self, from: data) else{
fatalError("Can not parse post list json data")
}
实战代码
PostCell.swift
//
// PostSell.swift
// WeiboDemo
//
// Created by EchoSun on 2020/11/29.
//
import SwiftUI
struct PostSell: View {
let post:Post
var body: some View {
HStack(spacing: 5.0) {
// 使用 library 窗口快速添加 ⇧⌘ L
Image(uiImage: UIImage(named: post.avatar)!)
.resizable() // 调整到合适的大小
.scaledToFit() // 按比例缩放
// 下面两个语句顺序很关键,由于图片是矩形的,若这两句顺序颠倒,则最终效果是"直边椭圆形"。
.clipShape(Circle()) // 切成一个圆形
.frame(width:50, height: 50) // 设置大小
//
.overlay(
// 为了进一步简化代码,方便我们快速设置角标,我们将头像右下角的”V“抽象到一个新的视图中。
PostVIPBadge(vip:post.vip)
// 设置一个偏移量
.offset(x: 16, y: 16)
)
// VStack:纵向排列
// leading: 左对齐
// spacing: 四种间隔
VStack(alignment: .leading, spacing: 5.0) {
Text(post.name) // 限制行数
.font(Font.system(size: 16))
.foregroundColor(.red)
.lineLimit(1)
Text(post.date)
.font(Font.system(size: 11))
.foregroundColor(.gray)
}
.padding(.leading,10)
Spacer() // 中间填充空间
if !post.isFollowed{
Button(action: {
print("Click follow button")
}) {
Text("关注")
.font(.system(size: 14))
.foregroundColor(.orange)
.frame(width: 50, height: 26) // 设置frame可以便于画矩形边框,也可以增大按键区域。
.overlay(
RoundedRectangle(cornerRadius: 13)
.stroke(Color.orange,lineWidth: 1) // 绘制轮廓
)
}
}
}
}
}
struct PostSell_Previews: PreviewProvider {
static var previews: some View {
PostSell(post: postList.list[0])
// PostSell(post: Post(avata: "d0c21786ly1gavj2c0kcej20c8096dh7.jpg", vip: true, name: "用户昵称", date: "2020-1-1-1", isFollowed: false))
}
}
PostVIPBadge.swift
//
// PostVIPBadge.swift
// WeiboDemo
//
// Created by EchoSun on 2020/11/29.
//
import SwiftUI
struct PostVIPBadge: View {
let vip:Bool
var body: some View {
Group {
if vip{
Text("V")
.bold()
.font(Font.system(size: 11))
.frame(width: 15, height: 15)
.foregroundColor(.yellow)
.background(Color.red)
.clipShape(Circle())
.overlay(
RoundedRectangle(cornerRadius: 7.5)
.stroke(Color.white,lineWidth: 1)
)
}
}
}
}
struct PostVIPBadge_Previews: PreviewProvider {
static var previews: some View {
PostVIPBadge(vip: true)
}
}
Post.swift
//
// Post.swift
// WeiboDemo
//
// Created by EchoSun on 2020/11/29.
//
import SwiftUI
// Codable 是一种可以编码和解码的数据类型
// 结构体与json的名称和类型必须对应,否则解析出错
struct PostList:Codable {
var list:[Post]
}
// data model 看不到的数据模型
struct Post:Codable{
// 下方的所有变量又叫做实例变量,仅在Post的实例创建时创建。
// let 声明常量; var 声明变量. 不清楚的话可以先声明成常量,等到需要变动时再改成变量。
let id:Int // 微博ID
let avatar:String // 用户头像,图片名称
let vip:Bool // 是否是VIP
let name:String // 用户名
let date:String // 日期
var isFollowed:Bool // 是否关注
let text:String // 微博内容
let images:[String] // 微博图片
var commentCount:Int // 评论数
var likeCount:Int // 点赞数
var isLiked:Bool // 是否点赞
}
// 全局变量,任何地方都可以调用
let postList:PostList = loadPostListData(fileName:"PostListData_recommend_1.json")
func loadPostListData(fileName:String)->PostList{
guard let url = Bundle.main.url(forResource: fileName, withExtension: nil) else{
fatalError("Can not find \(fileName) in main Bundle")
}
guard let data = try? Data(contentsOf: url)else{
fatalError("Can not load \(url)")
}
// // 三种方法处理异常
// // 方法1 推荐 try? 如果解析成功就有值,否则为 nil
// let list1 = try?JSONDecoder().decode(PostList.self, from: data)
// print(list1 ?? "None")
// // 方法2 使用try 处理异常,能够接收到错误,并且输出。但是,语法结构复杂。
// do {
// let list2 = try JSONDecoder().decode(PostList.self, from: data)
// print(list2);
// } catch {
// print(error);
// }
// // 方法3 不推荐 try! 如果解析成功就有值,否则崩溃
// let list3 = try!JSONDecoder().decode(PostList.self, from: data)
// print(list3)
guard let list = try?JSONDecoder().decode(PostList.self, from: data) else{
fatalError("Can not parse post list json data")
}
return list
}
本篇博客介绍了如何在iOS开发中使用Codable协议来解析JSON数据,包括理解Codable的可编码概念,以及Swift中的异常处理方法try?和guard语句的用法。同时提供了实战代码示例,如PostCell.swift、PostVIPBadge.swift和Post.swift。

433

被折叠的 条评论
为什么被折叠?



