iOS SwiftUI List 未实现懒加载?求解原因
问题解答
首先要明确两个核心概念:视图结构体的初始化和视图的实际渲染是完全不同的两件事:
视图结构体(比如你的
ItemRow)是值类型,创建实例的开销极低。SwiftUI在构建视图树时,会提前为所有列表条目创建对应的ItemRow结构体实例——这就是你看到30000次初始化打印的原因,重复两次是因为SwiftUI在视图初始化过程中可能会进行两次视图树的构建(比如首次加载和一次校验更新),属于正常现象。SwiftUI List的懒加载特性针对的是实际渲染环节:只有当列表单元格进入屏幕可视区域时,SwiftUI才会真正执行该单元格视图的
body计算,并创建对应的底层UIKit(UITableViewCell)进行显示。你当前把打印放在init里,无法验证懒加载,应该把打印移到body中,再滚动列表测试:
struct ItemRow:View{ let item: Item init(item: Item){ self.item = item print("init #\(item.id)") } var body: some View{ let _ = print("body rendered #\(item.id)") Text(String(item.id)) } }
运行后你会发现:启动时只有可视区域内的条目会打印body rendered,滚动列表时,新进入可视区域的条目才会触发该打印——这才是List懒加载的真正体现。
另外补充:如果想避免提前创建所有ItemRow结构体实例,可以用你注释掉的ScrollView + LazyVStack组合,这种方式下只有当条目即将进入可视区域时,才会创建对应的视图结构体实例。不过List本身基于UITableView的单元格复用机制,性能已经足够优秀,大部分场景下直接用List即可。
内容的提问来源于stack exchange,提问作者gswierczynski
相关产品推荐
相关产品推荐

