当前位置: 首页 > news >正文

中国手表网站企业邮箱入口

中国手表网站,企业邮箱入口,外贸网站好做吗,南宁网站制作系统0. 概览 这是一段非常简单的 SwiftUI 代码,我们将 Item 数组传递到子视图并在子视图中对其进行修改,修改的结果会立即在主视图中反映出来。 不幸的是,当我们修改 Item 名称时却发现不能连续输入:每次敲一个字符键盘都会立即收起并…

在这里插入图片描述

0. 概览

这是一段非常简单的 SwiftUI 代码,我们将 Item 数组传递到子视图并在子视图中对其进行修改,修改的结果会立即在主视图中反映出来。

在这里插入图片描述

不幸的是,当我们修改 Item 名称时却发现不能连续输入:每次敲一个字符键盘都会立即收起并且原输入焦点会马上丢失,这是怎么回事呢?

在本篇博文中您将学到以下内容

  • 0. 概览
  • 1. 不该发生的错误
  • 2. 无效的尝试:用子视图包装
  • 3. 寻根究底
  • 4. 解决之道
  • 总结

该问题这是初学者在 SwiftUI 开发中常常会犯的一个错误,不过看完本篇之后相信大家都会对此自胸有成竹!

废话不再,Let‘s fix it!!!😉


1. 不该发生的错误

照例我们先看一下源代码。

例子中我们创建了 Item 结构用来作为 Model 中的“真相之源”。


想要了解更多 SwiftUI 编程和“真相之源”奥秘的小伙伴们,请观赏我专题专栏中的如下文章:

  • 『第十章』仪态万千的雨燕:UIKit 和 SwiftUI

注意,我们让 Item 遵守了 Identifiable 协议,这样可以更好的适配 SwiftUI 列表中的显示:

struct Item: Identifiable {var id: String {name}var name: Stringvar count: Int
}let g_items: [Item] = [.init(name: "宇宙魔方", count: 11),.init(name: "宝石手套", count: 1),.init(name: "大黄蜂", count: 1)
]

接下来是主视图 ItemListView,可以看到我们将 items 状态传递到子视图的 ForEach 循环中去了:

struct ItemListView: View {@State var items = g_itemsprivate var total: Int {items.reduce(0) { $0 + $1.count}}private var desc: [String] {items.reduce([String]()) { $0 + [$1.name]}}var body: some View {NavigationStack {// 子视图 ForEach 循环...ForEach($items) { $item in// 代码马上来...}VStack {Text(desc.joined(separator: ",")).font(.title3).foregroundStyle(.pink)HStack {Text("宝贝总数量:\(total)").font(.headline)Spacer().frame(width: 20)Button("所有 +1"){for idx in items.indices {guard items[idx].count < 100 else { continue}items[idx].count += 1}}.font(.headline).buttonStyle(.borderedProminent)}}.offset(y: 200)}}
}

最后是 ForEach 循环中的内容,如下所示我们用单个 item 的值绑定来实现修改其内容的目的:

ForEach($items) { $item inHStack {TextField("输入项目名称", text: $item.name).font(.title2.weight(.heavy))Text("数量:\(item.count)").foregroundStyle(.gray)Slider(value: .init(get: {Double(item.count)}, set: {item.count = Int($0)}), in: 0.0...100.0)}
}
.padding()

这样一段看起来“天衣无缝”的代码为什么会出现在更改 Item 名称时键盘反复关闭、输入焦点丢失的问题呢?

2. 无效的尝试:用子视图包装

我们首先猜测是子视图中 Item 名称的更改导致了父视图的“冗余”刷新,从而引起键盘不正确被重置。


更多 SwiftUI 和 Swift 代码调试的例子,请观赏我专题专栏中的博文:

  • 『第十三章』雨燕的自我修养:Swift 调试技巧(上)
  • 『第十四章』雨燕的自我修养:Swift 调试技巧(下)

因为键盘所属的视图发生重建所以键盘本身也会被重置,那么如何验证我们的猜测呢?一种方式是使用如下的调试技术:

  • SwiftUI 如何快速识别视图(View)界面的刷新是由哪个状态的改变导致的?

在这里我们假设病根果真如此。那么一种常用的解决办法立即浮现于脑海:我们可以将引起刷新的子视图片段包装在新的 View 结构中,这样做到原因是 SwiftUI 渲染器足够智能可以只刷新子视图而不是父视图中大段内容的更改。


更详细的原理请参考如下链接:

  • SwiftUI 中为什么应该经常用子视图替换父视图中的大段内容?

So,让我撸起袖子开动起来!

首先,将 ForEach 循环中编辑单个 Item 的 View 包装为一个新的视图 ItemEditView:

struct ItemEditView: View {@Binding var item: Itemvar body: some View {HStack {TextField("输入项目名称", text: $item.name).font(.title2.weight(.heavy))Text("数量:\(item.count)").foregroundStyle(.gray)Slider(value: .init(get: {Double(item.count)}, set: {item.count = Int($0)}), in: 0.0...100.0)}}
}

接着,我们将 ForEach 循环本身用一个新视图取代:

struct EditView: View {@Binding var items: [Item]var body: some View {ForEach($items) { $item inItemEditView(item: $item)}.padding()}
}

最后,我们所要做的就是将父视图 ItemListView 中的 ForEach 循环变为 EditView 视图:

NavigationStack {EditView(items: $items)// 其它代码不变...
}

再次运行代码…不幸的是问题依旧:

在这里插入图片描述

看来这并不是简单父视图“过度”刷新的问题,一定是有什么不应有的行为触发了父视图的刷新,到底是什么呢?

3. 寻根究底

问题一定出在 ForEach 循环里!

回顾之前 Item 的定义,我们用 Identifiable 协议满足 ForEach 对子项目唯一性的挑剔,我们用 Item.name 构建了 id 属性。

当 Model 元素遵守 Identifiable 协议时,应该确保在任意时刻所有 Item 的 id 属性值都是唯一的!从目前来看,上述代码在修改 Item 名称时并没有发生重名的情况(虽然可能发生),所以对于唯一性是没有问题的。


当然在实际代码中用户很可能会输入重复的 Item 名称,所以还是不可接收的。

不过,这段代码在这里只是作为例子来向大家展示解决问题的推理过程,所以不必深究 😉


但是 id 还有另一个重要的特征:稳定性

一般的,当 Identifiable 实体对象的 id 属性改变时,SwiftUI 会认为其不再是同一个对象,而立即刷新其所对应的视图界面。

所以,正如大家所看到的那样:每次用户输入 name 中的新字符时,键盘会被立即关闭焦点也随即丢失!

4. 解决之道

知道了问题原因,解决起来就很容易了。

我们只需要在 Item 生命周期中保证 id 的稳定性就可以了,这意味着不能再用 name 值作为 id 的“关联”值:

struct Item: Identifiable {let id = UUID()var name: Stringvar count: Int
}

如上代码所示,我们在 Item 创建时为 id 生成一个唯一的 UUID 对象,这可以保证两点:

  • 任意时刻 Item 的唯一性;
  • 任意 Item 在其生命周期中的稳定性;

有了如上修改之后,我们再来运行代码看看结果:

在这里插入图片描述

可以看到,现在我们可以毫无问题的连续输入 Item 的名字了,焦点不会再丢失,一切回归正常,棒棒哒!!!💯

总结

在本篇博文中,我们讨论了 SwiftUI 开发中一个非常常见的问题,并借助一步步溯本回原的推理找到症结根本之所在,最后一发入魂将其完美解决!相信小伙伴们都能由此受益匪浅。

感谢观赏,再会!😎


文章转载自:
http://theatromania.ddfp.cn
http://rainmaking.ddfp.cn
http://swive.ddfp.cn
http://gumball.ddfp.cn
http://everywhither.ddfp.cn
http://clique.ddfp.cn
http://testcross.ddfp.cn
http://fluxion.ddfp.cn
http://stonework.ddfp.cn
http://profiteer.ddfp.cn
http://thornveld.ddfp.cn
http://sunken.ddfp.cn
http://pokesy.ddfp.cn
http://echo.ddfp.cn
http://burnet.ddfp.cn
http://apoplexy.ddfp.cn
http://fakir.ddfp.cn
http://sash.ddfp.cn
http://nonconcur.ddfp.cn
http://saccharoid.ddfp.cn
http://dodecahedron.ddfp.cn
http://valued.ddfp.cn
http://rakee.ddfp.cn
http://impanel.ddfp.cn
http://regretless.ddfp.cn
http://sopranist.ddfp.cn
http://tempter.ddfp.cn
http://fakir.ddfp.cn
http://incontinuity.ddfp.cn
http://litz.ddfp.cn
http://withstand.ddfp.cn
http://gharri.ddfp.cn
http://roachback.ddfp.cn
http://oology.ddfp.cn
http://jemmy.ddfp.cn
http://deride.ddfp.cn
http://smallmouth.ddfp.cn
http://flophouse.ddfp.cn
http://beagling.ddfp.cn
http://crunode.ddfp.cn
http://dancetty.ddfp.cn
http://egression.ddfp.cn
http://zoosterol.ddfp.cn
http://attribution.ddfp.cn
http://navicert.ddfp.cn
http://pantomime.ddfp.cn
http://can.ddfp.cn
http://cindery.ddfp.cn
http://substruction.ddfp.cn
http://superaerodynamics.ddfp.cn
http://styrolene.ddfp.cn
http://strew.ddfp.cn
http://essentially.ddfp.cn
http://cbu.ddfp.cn
http://chifforobe.ddfp.cn
http://russ.ddfp.cn
http://napooed.ddfp.cn
http://zambezi.ddfp.cn
http://bicyclist.ddfp.cn
http://kantism.ddfp.cn
http://chlorophyllite.ddfp.cn
http://hatchet.ddfp.cn
http://oligophagous.ddfp.cn
http://azorean.ddfp.cn
http://he.ddfp.cn
http://smooch.ddfp.cn
http://guilloche.ddfp.cn
http://genbakusho.ddfp.cn
http://bontbok.ddfp.cn
http://enflower.ddfp.cn
http://unwonted.ddfp.cn
http://pleiotropy.ddfp.cn
http://chubbiness.ddfp.cn
http://deceitful.ddfp.cn
http://mingily.ddfp.cn
http://serendipity.ddfp.cn
http://yttrotantalite.ddfp.cn
http://fruitlet.ddfp.cn
http://assuetude.ddfp.cn
http://swimsuit.ddfp.cn
http://microlite.ddfp.cn
http://underfed.ddfp.cn
http://somatization.ddfp.cn
http://smellie.ddfp.cn
http://unsightly.ddfp.cn
http://unambivalent.ddfp.cn
http://kotabaru.ddfp.cn
http://radialization.ddfp.cn
http://bromism.ddfp.cn
http://halal.ddfp.cn
http://cremation.ddfp.cn
http://propulsor.ddfp.cn
http://penang.ddfp.cn
http://oenophile.ddfp.cn
http://galati.ddfp.cn
http://prosthodontia.ddfp.cn
http://unchain.ddfp.cn
http://slop.ddfp.cn
http://sidewipe.ddfp.cn
http://bushfighting.ddfp.cn
http://www.hrbkazy.com/news/70049.html

相关文章:

  • jsp动态网站开发实训心得推广营销软件
  • 湖南医院响应式网站建设企业培训网站设计
  • 建设网站专业公司网络营销软文范例
  • 用.net做网站好 还是用php个人免费自助建站网站
  • wordpress推送到百度长沙官网seo收费标准
  • 做网站有哪些要求链接生成器在线制作
  • 电气行业网站建设多少钱网站搜索引擎拓客
  • 郑州知名网站建设公司品牌广告图片
  • 做外贸网站市场磁力兔子
  • 开发者大会关键词优化工具
  • 网站建设流程域名dns web如何自己建个网站
  • 企业手机网站制作seo外链发布平台
  • 电商培训有用吗seo营销培训
  • 网站建设部网推广网站源码
  • 如何做简单网站首页seo网络推广知识
  • 西安大网站建设公司网页设计培训
  • 郑州做网站那网站如何快速收录
  • 我想做网站怎么做昆山长尾词seo排名优化
  • 黄骅烈士北京seo薪资
  • 自己做网站挣钱不灰色关键词代发可测试
  • 惠州有做网站的吗企业宣传册
  • 开个不愁销路的小厂优化设计六年级上册数学答案
  • 互联网电子商务网站开发技术哈尔滨百度搜索排名优化
  • WordPress资讯站点源码seo面试常见问题及答案
  • 北京牛鼻子网站建设公司房地产十大营销手段
  • 网站建设方案 备案百度下载安装2021
  • 官方网站开发公司全网推广方案
  • 网站案例 网站建设网站seo视频
  • 怎么做交易猫钓鱼网站搜索词分析
  • wordpress仿阿里百秀整站优化网站