【Swift】第9周 小说列表展示案例

1. 使用 GeometryReader 调整尺寸

.resizable() 设置图片尺寸是可以被调整的
.frame(width:300, height: 300) 调整图片尺寸
.aspectRatio(contentMode: .fit) 保持长宽比例
GeometryReader 可以使图片更好的显示

GeometryReader{ geo in
Image("road")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: 300)
}

2. 滚动视图 ScrollView

import SwiftUI


struct CustomText: View{
	var number: Int
	var body: some View{
		Text("CustomText \(number)")
	}
	init(_ number: Int){
		self.number = number
		print("CustomText \(number)")
	}
}

struct ContentView: View {
	var body: some View {
		ScrollView(.vertical){
			VStack{
				ForEach(0...100, id:\.self){
					CustomText($0)
					.font(.title)
				}
			}
		}
	}
}

在这里插入图片描述

3. NavigationLink

SwiftUI中的NavigationView采用的是“视图堆栈”的操作机制。它会在APP界面的顶部显示一个导航栏,用来指示我们当前是哪一个视图。

所谓的“视图堆栈”机制就是当前显示的视图是在“栈顶”的,当需要打开新的视图时,就把新的视图‘‘入栈”,让这个新的视图称为新的栈顶。当我们在导航栏中点击“back”时,相当于让当前的视图“出栈”,而之前在栈中“原来栈顶”下面的那个视图就成了“新的栈顶

import SwiftUI
struct ContentView: View {
	var body: some View {
		NavigationView{
			NavigationLink(destination: Text("world")){
				Text("Hello")
			}
			.navigationBarTitle("SwiftUI")
		}
	}
}

上述代码中的第6行使用了NavigationLink来创建导航,它的参数destination可以是任何view类成员,一个Text,一个button,-个view均可。
这种机制跟之前学过的“sheet”的方式显示新的视图是不一样的。

  • NavigationLink 有些类似于剥洋葱,-层一层的剥开,一层一层的深入去展示。

  • sheet有些类似于它就是这个视图的一个组成部分,只不过不需要显示它的时候就把它隐藏起来,需要的时候再让它显示出来。

    如果在NavigationLink中使用了List, 那么会在每- -行的后面都出现一一个“>”,用于指示用户点击可进入下一层。

4. 使用 Codable 对多层级的 JSON 进行压缩

// ****** ?? 3?******
Button("解析圆形"){
let myCircle = """
{
"radius": 10.4,
"point": {
"x": 12.0,
"y": -15.3
}
"""
}


struct Circle: Codable{
	var radius: Double
	var point: PointXY
}
struct PointXY: Codable{
	var x: Double
	var y: Double
}

//解析上面数据的代码
	let data = Data(myCircle.utf8)
	let decoder = JSONDecoder()
	if let circle = try? decoder.decode(Circle.self, from: data) {
		print(circle.point.x)
	}
}

5. 扩展Bundle

// ****** Astronaut.swift ******
import Foundation
struct Astronaut: Codable, Identifiable{
	var id: Int
	var name: String
	var description: String
}
// ****** Bundle-Decodable.swift ******
import Foundation
extension Bundle {
	func decode<T: Codable>(_ file: String) -> T {
		guard let url = self.url(forResource: file, withExtension: nil) else {
			fatalError("Failed to locate \(file) in bundle.")
		}
		guard let data = try? Data(contentsOf: url) else {
			fatalError("Failed to load \(file) from bundle.")
		}
		let decoder = JSONDecoder()
		guard let loaded = try? decoder.decode(T.self, from: data)	else {
			fatalError("Failed to decode \(file) from bundle.")
		}
		return loaded
	}
}

在ContentView中编写代码

let astronauts = Bundle.main.decode("astronaut.json") 

在这里插入图片描述

6.案例

6.1 json数据

novels.json

[
	{
        "id": 1,
        "list": [
            {
                "name": "两钱铜币",
                "author": "(日)江户川乱步"
            },
            {
                "name": "人生",
                "author": "路遥"
            },
            {
                "name": "鬼谷子的局",
                "author": "寒川子"
            }
        ],
        "description": "电子书畅销小说"
    },
	{
		"id": 2,
        "sort": "社会生活小说",
		"list": [
            {
                "name": "人生",
                "author": "路遥"
            },
            {
                "name": "边城",
                "author": "沈从文"
            },
            {
                "name": "海边的卡夫卡",
                "author": "(日)村上春树"
            }
		],
		"description": "《人生》是获得茅盾文学奖的作品,《边城》是我国文学大师沈从文久负盛名的作品,《海边的卡夫卡》是村上春树仅次于《挪威的森林》的重要长篇小说。"
	},
	{
		"id": 3,
        "sort": "历史小说",
		"list": [
            {
                "name": "鬼谷子的局",
                "author": "寒川子"
            },
            {
                "name": "巨人的陨落",
                "author": "(英)肯·福莱特"
            }
		],
		"description": "《鬼谷子的局》是一部巨著,全书共十卷,讲述谋略家、兵法家、纵横家、阴阳家、道家共同的祖师爷——鬼谷子布局天下的辉煌传奇。《巨人的陨落》是全球读者平均3个通宵读完的超级巨著。碾压全球畅销榜的伟大故事,全球每三秒卖出一本!"
	},
    {
        "id": 4,
        "sort": "侦探悬疑小说",
        "list": [
            {
                "name": "两钱铜币",
                "author": "(日)江户川乱步"
            },
            {
                "name": "梦幻花",
                "author": "(日)东野圭吾"
            },
            {
                "name": "无人生还",
                "author": "(英)阿加莎·克里斯蒂"
            }
        ],
        "description": "当当网侦探悬疑推理类的热销小说"
    }
]

books.json

[
	{
        "id": "两钱铜币",
        "author": "(日)江户川乱步 著 王志芳 译",
        "price": "6.99",
		"description": "江户川乱步(1894—1965)是日本久富盛名的推理作家、评论家,被誉为日本“侦探推理小说之父”,其笔下的侦探明智小五郎(《名侦探柯南》中毛利小五郎姓名由来,其本人为《名侦探柯南》中江户川柯南姓由来)更是日本家喻户晓的人物。 江户川乱步的中短篇代表作,小说内容取材广泛,构思拍案叫绝、气氛妖异诡谲、情节跌宕起伏,不读到最后一刻,永远不会知道真相是什么!本套书共分两册,将收录江户川乱步最为经典的侦探小说,例如《两钱铜币》《湖畔亭离奇命案》《月亮与手套》《心理测试》《地狱的面具》《出没于顶棚里的人》《D坂街杀人事件》等。"
	},
	{
        "id": "梦幻花",
        "author": "(日)东野圭吾",
        "price": "9.90",
        "description": "错综交织的悬案,揭百年的谜团 年轻夫妇的身体被武士刀贯穿,仅有年幼的女儿生还; 一见钟情的初恋女孩,却在几天后人间蒸发; 大学生跳楼身亡,桌上摆着半杯可乐; 独居老人疑被室强盗杀害,丢失的财物却是一盆鲜花…… “梦幻花”究竟是什么?为什么一旦追寻就会自取灭亡? 源自真实故事的创作灵感 日本的江户时代出现过黄色的牵牛花。为什么到现在反而没有了呢? 想到这里,一股悬疑的气息袅袅升起。"
    },
    {
        "id": "无人生还",
        "author": "(英)阿加莎·克里斯蒂",
        "price": "6.99",
        "description": "十个相互陌生、身份各异的人受邀前往德文郡海岸边一座孤岛上的豪宅。客人到齐后,主人却没有出现。当晚,一个神秘的声音发出指控,分别说出每个人心中罪恶的秘密。接着,一位客人离奇死亡。暴风雨让小岛与世隔绝,《十个小士兵》——这首古老的童谣成了死亡咒语。如同歌谣中所预言的,客人一个接一个死去……杀人游戏结束后,竟无一人生还!"
    },
    {
        "id": "人生",
        "author": "路遥",
        "price": "18.99",
        "description": "《人生》是茅盾文学奖得主路遥的代表作,激励万千读者的文学经典。《人生》改变了马云的一生,也深刻影响了陈忠实、贾樟柯等人的创作。 《人生》以陕北高原的城乡生活为背景,叙述了知识青年高加林回到家乡又离家乡,再回归家乡的人生变化过程。《人生》讲述了一个年轻人面临的爱情与事业、理想与现实间的艰难选择,具有巨大的共情力量,说出了每个人,尤其是年轻人的困境、期待与追求。《人生》在有限生命中不懈追寻的激情,在每个人的心底激起回响;《人生》大地般宽广的气质,给予对生活失望的人莫大的安慰与力量。这是路遥的《人生》,也是我们每个人的人生。"
    },
    {
        "id": "边城",
        "author": "沈从文",
        "price": "5.99",
        "description": "《边城》是沈从文久负盛名的作品,由此奠定了他在中国现代文学史上的地位。它入选“20世纪中文小说百强”第二名,并被翻译成40多个国家的文字出版,亦被编入美国、日本等十多个国家和地区的大学课本。 这是一部田园牧歌式的杰作。在这部小说中,沈从文描绘了一个如同世外桃源般的边城小镇,以及一个纯粹、美丽而淡淡忧伤的爱情故事。在他的笔下,湘西淳朴天然的人情世道,野性自由的生命形态,以及澄澈纯净的人性,均一一铺呈开来,婉约而惆怅。沈从文关于“爱”与“美”的美学理想,在这部小说中得到了完整的体现。 本书另外还收录了《三三》《萧萧》等沈从文具有代表性的小说作品,基本囊括了沈从文文字精髓,全面展示了大师的文风神采。"
    },
    {
        "id": "海边的卡夫卡",
        "author": "(日)村上春树",
        "price": "12.99",
        "description": "本书是村上春树仅次于《挪威的森林》的重要长篇小说,以其独特风格的两条平行线展。一条平行线是少年“田村卡夫卡”,为了挣脱“你要亲手杀死父亲,与母亲乱伦”的诅咒,离家乡投成人世界。此后父亲在家被杀,他却疑心自己是在睡梦中杀父。他在一座旧图书馆遇到一位50岁的优雅女性,梦中却与这位女性的少女形象交合,而这位女性又可能是他的生母。一条平行线是一名失忆老人中田,因为一桩离奇的杀人事件走上逃亡之路,在汽车司机星野的帮助下恢复了遥远的战争记忆。书中对日本军国主义的复活表达了忧虑,对日本的文化传统作出了反思。本书平装本2003年由我社初版,此后于2007年更换了封面,并作了修订。2014年,我社又出版了本书的精装本,再次作了修订。因上一个平装本封面已经10年未变,故第三次更换本书封面设计,使这部名作焕发新的活力。"
    },
    {
        "id": "鬼谷子的局",
        "author": "寒川子",
        "price": "19.99",
        "description": " 本书为《鬼谷子的局》第五卷。在本卷中天下大势瞬息万变,转眼间,四子山已过三年。庞涓习得《吴起兵法》,自觉技艺已成,告别鬼谷子和其余三人下山。他先齐,再魏,助魏惠王与七万齐军决战黄池,退秦、赵、韩联军,尽解魏围。 由此,庞涓封侯拜将,名扬天下。他的杀父仇人陈轸深惧报复,仓皇投秦。 另一方面,魏惠王急使太子申重金礼聘孙宾下山。下山前,鬼谷子为孙宾更名为“孙膑”。 之后孙膑辅佐庞涓献屯田之谋,使魏国军力财力迅速复苏,隐隐有称霸七国之相。这让苏秦、张仪也禁不住跃跃欲试,但鬼谷子却以学艺未成为由,刻意挽留二人,授予其纵横捭阖之术。"
    },
    {
        "id": "巨人的陨落",
        "author": "(英)肯·福莱特(KenFollett)(著),于大卫(译)",
        "price": "19.99",
        "description": " 在第一次世界大战的硝烟中,每一个迈向死亡的生命都在热烈地生长――威尔士的矿工少年、刚失恋的美国法律系大学生、穷困潦倒的俄国兄弟、富有英俊的英格兰伯爵,以及痴情的德国特工……从充满灰尘和危险的煤矿到闪闪发光的皇室宫殿,从代表着权力的走廊到爱恨纠缠的卧室,五个家族迥然不同又纠葛不断的命运逐渐揭晓,波澜壮阔地展现了一个我们自认为了解,但从未如此真切感受过的20世纪。"
    }
]

6.2 结构体定义

Book

// ****** Book.swift ******
import Foundation
struct Book: Codable, Identifiable {
	let id: String
	let author: String
	let price: String
	let description: String
}

Novel

// ****** Novel.swift *******
import Foundation
struct Novel: Codable, Identifiable{
	struct CrewList: Codable{
		let name: String
		let author: String
	}
	let id: Int
	var sortVar: String?
	let crew: [CrewList]
	let description: String
	var displayName: String{
		"Novel \(id)"
	}
	var image: String{
		"novel \(id)"
	}
	//软解包
	if let sort = sortVar{
		
	}else{
		print("nil")
	}

}

6.3 BookView

BookView

import SwiftUI
struct BookView: View {
	let book: Book
	var body: some View {
		GeometryReader{ geometry in
			ScrollView(.vertical){
				VStack{
					Image(self.book.id)
						.resizable()
						.scaledToFit()
						.frame(width: geometry.size.width)
					Text(self.book.author)
					Text(self.book.price)
					Text(self.book.description)
						.padding()
						.layoutPriority(1)
				}
			}
		}
		.navigationBarTitle(Text(book.id),displayMode: .inline)
	}
}

struct BookView_Previews: PreviewProvider {
	static let books: [Astronaut] = Bundle.main.decode("books.json")
		static var previews: some View {
			BookView(book: books[0])
		}
}

6.4 NovelView

import SwiftUI
struct NovelView: View {

	struct CrewMember{
		let name: String
		let author: String
		let book: Book
	}
	
	let novel: Novel
	let books: [CrewMember]
	
	init(novel: Novel, books: [Book]){
		self.novel= novel
		//定义一个空的数组存放 books
		var matches = [CrewMember]()
		for member in novel.crew{
			if let match = books.first(where: {
						$0.id == member.name
					}){
				matches.append(CrewMember(name: member.name,author: member.author, book: match))
			}else{
				fatalError("Missing \(member)")
			}
		}//for
		self.books= matches
	}	
	
var body: some View {
	GeometryReader{ geometry in
		ScrollView(.vertical){
			VStack{
				Image(self.novel.image)
					.resizable()
					.scaledToFit()
					.frame(maxWidth:geometry.size.width * 0.7)
					.padding(.top)
				Text(self.novel.sort)
				Text(self.novel.description)
					.padding()
				ForEach(self.books, id:\.id){ crewMember in
					NavigationLink(destination: BookView(book: crewMember.book)){
						HStack{
							Image(crewMember.book.id)
								.resizable()
								.frame(width: 83, height: 60)
								.clipShape(Capsule())
							VStack(alignment:.leading){
								Text(crewMember.book.id)
									.font(.headline)
								Text(crewMember.book.author)
									.foregroundColor(.secondary)
							}
							Spacer()
						}
						.padding()
					}
					.buttonStyle(PlainButtonStyle())
				}
				Spacer(minLength: 25)
			}
		}
	}//GeometryReader
	.navigationBarTitle(Text(novel.displayName),displayMode: .inline)
}//View 
}//NovelView



struct NovelView_Previews: PreviewProvider {
	static let novels: [Novel] = Bundle.main.decode("novels.json")
	static let books: [Book] = Bundle.main.decode("books.json")
	static var previews: some View {
		NovelView(novel: novels[0], books: books)
	}
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ContentView

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一款极为优秀的资料搜索、资料收集、资料数据库保存、资料浏览、资料批处理的专业工具软件,是学习、科研、开发人员的极好助手; 本地搜索功能较WINDOWS自带的搜索功能更为实用,并且功能在逐步增加; 可以按关键词的组合快速搜索各种文件类型或文件名的文件; 可以轻松编辑文件列表:反选择文件;选择全部文件;不选任何文件; 可以对列表中文件按“文件名”“文件路径”“文件大小”“文件创建日期”“文件修改日期”“文件搜索范围”“文件版本”进行进一步模糊查询,和轻松选定; 可以打开列表中任何文件或目录; 可以查看列表文件的详细信息; 可以批量大写或小写所选文件名或文件夹名; 可以用默认的程序打开所选文件名或文件夹名; 可以复制、移动和删除文件,在复制和移动文件时,对相同的文件名可以自动重命名...; 可以批量重置文件各种属性; 可以搜索网页文件,自带浏览器的极为方便,快捷; 可以保存和加载保存的搜索列表文件; 可以批量修改网页软件,替换或插入您需要的内容; 可以自动生成电脑中网页文件的索引文件; 可以定时自动快速浏览网页文件、WORD文件、文本文件的内容,每秒可以浏览几十个文件; 可以实现*.JS文件和*.HTM网页文件之间的转换; 可以将某个网页文件或某个目录下的所有网页文件内容导入数据库保存,可以将他人保存的数据导入自己的数据库中,便于数据信息交流 可以对数据库实现SQL查询; 利用本软件上网浏览网页,会自动将网页内容载入数据库保存; 软件窗口自动伸缩,便于浏览、切换...... 本软件的特点: 1、组合快速本地搜索,进一步的模糊查询和筛选; 2、快速智能网络搜索,自动网页过滤保存、数据库保存及数据库的查询; 3、方便的网页浏览,页面内容快速模糊查询
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_popo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值