置顶
菜鸟入门,各位大佬轻喷,如有谬误之处欢迎讨论建议,也欢迎各位道友与我同行
“不积跬步,无以至千里;不积小流,无以成江海”
继续
上文中我们引入了第三方库 Popup,所以本文我们来讨论 Popup 的封装,实现一个 全局Toast 的功能
效果如下:
在这里插入图片描述
期望的调用方式如下:
showToast("测试");
hideToast();
思考
按照上文的调用方式描述,很显然我们不希望这几个方法被定义在本身的视图上,一定是在另一个文件中定义好,这里可以直接使用
所以我们将会用到 extension
同样的我们也不希望这个封装会大量地放到某一个视图中去,最好是直接在封装的地方就能做完,同时在原来的页面视图中只需要进行调用即可,最好是直接在初始化的时候用一次即可。
所以我们将会用到 ViewModifier
结合之前我们用到的 @AppStorage ,完全可以实现一个全局的 Toast
实现
我们新增一个文件:Toast.swift 用来存放所有的对 Toast 的封装,内容如下:
import SwiftUI
import ExytePopupView
/// extension 顾名思义即扩展
/// extension 可以给指定的对象、类型、struct、protocol 等扩展 func,不用再在具体的结构里面显式声明方法
/// 很好的一个横向解耦方式,很像PHP中的 Trait
/// 假如以后有相同方法的两个view,我们完全可以抽象到一起
extension View{
// 初始化启动Toast 返回一个 some View
public func enableToast() -> some View{
@AppStorage("showGlobalToast") var showGlboalToast:Bool = false;
@AppStorage("globalToastText") var globalToastText:String = "";
// 这里将全局变量重置,以避免正好在显示Toast的时候退出了app
// 导致下次打开app的时候就有一个 Toast
showGlboalToast = false
globalToastText = ""
// 这里调用了一个view modifier
return self.modifier(initToast())
}
// 显示一个Toast,传入内容
public func showToast(content:String){
@AppStorage("showGlobalToast") var showGlboalToast:Bool = false;
@AppStorage("globalToastText") var globalToastText:String = "";
// 修改全局变量
showGlboalToast = true;
globalToastText = content;
}
}
/// view modifier 相当于在外面修改某个视图的结构
/// body方法中提供了一个content就是调用你的那个视图
/// 你也可以理解为这是在跳转页面,但是把原始页面的实例给你了
struct initToast:ViewModifier{
@AppStorage("showGlobalToast") var showGlboalToast:Bool = false;
@AppStorage("globalToastText") var globalToastText:String = "";
public func body(content: Content) -> some View {
// 直接给 content 调用popup
content.popup(isPresented: $showGlboalToast, type:.default, position: .bot***, ani**tion: .easeOut(duration: 0), autohideIn: 2, dragToDismiss: false,closeOnTap: false,closeOnTapOutside: true,backgroundColor: .clear
){
Text(globalToastText)
.fr**e(width: 150, height: 80)
.background(.gray)
.foregroundColor(.white)
.cornerRadius(20.0)
}
}
}
整个的封装过程就结束
接下来就是调用部分
修改 helloworldApp.swift ,即你的 APP入口文件
import SwiftUI
@**in
struct helloworldApp: App {
var body: some Scene {
WindowGroup {
IndexView()
// 调用封装中扩展的方法即可
.enableToast()
}
}
}
在新增 todo 的按钮上进行调用
Button("添加"){
// 这里可以直接调用 showToast()
showToast(content: "添加成功")
todos.add(n**e: newItem)
newItem = ""
}
因为我们是对 View 进行的扩展,所以,所有的页面和视图都可以调用这些方法
以上,我们实现了一个全局的 Toast
踩坑
我曾经思考过,封装一个方法在 View 上,可以用以下方式调用
self.body.showToast("asdfasdf")
这样我就可以省略入口文件的那个启用方法 enableToast()
但是实际上并不会成功,中途倒是没报几个错,但是 toast 的效果一直都没出来
.popup 一定要写在视图定义的后面,而不能在中途的方法调用中动态的执行
也许这就是所谓的 强类型 + 声明式视图?
总结
- extension 是扩展方法,就说所有的结构都能扩展,包括基础数据类型,用法与 js 中的 prototype比较类似
- ViewModifier 是对视图的修改,你可以拿到视图本身,添加方法调用,也可以再加一些其他的元素进去,可以理解为拿得到上个页面视图的页面的跳转
- 全局 Loading 可以参照上面的实现,无非就是在文字上面加一个 Loading 的 gif 动图,本文不再赘述。
- 包括一些全局的 prompt 、confirm框等,也可以参照以上实现
- 貌似 popup 这个库引入得比较多余,我直接在 modifier 里面加一个框框在中间,使用 ZStack 这个框框显示在原始视图的上面不就完事儿了?但是怎么消除Toast是个问题,或许SwiftUI自己处理了这些不显示的视图?这个后续再继续讨论。。。
欢迎关注微信公众号【思跃喵】,一起探讨。
【风险提示】写在付款前:
1. 全站8500+源码,除了热门商业区的几十个源码外,只要有下载按钮的,终身VIP都可以免费下载。
2. 本站源码大多全网各种渠道采购,文章描述一般系转载渠道方的测试描述,不代表本站观点。但是文章开头带演示的源码,代表本站亲自测试过,至少表示能搭建起来,一般没什么大问题,可以放心购买。
=======================================
3. 文章开头没有演示站的,表示我们没有来得及亲自测试,源码有存在缺陷的风险,所以低价出售。一旦购买视为接受该风险,将无法退款!!!但是,同时你也有可能捡便宜。因为,很多是渠道方测试过的,只是我们没有来得及亲测确认而已,如果我们亲测没问题的话,价格都会翻好多倍。
=======================================
4. 本站使用在线支付,付款完毕后,积分自动到账。
5. 充值比例:1:1。是否属于VIP免费下载,需登陆后显示。
6. 所有源码默认是没有 安装教程 的,如果里面有那也是随机的。
7. 所有源码不提供免费安装,如需我们代安装请联系客服详谈。
请先
!