【发布时间】:2021-09-09 11:26:07
【问题描述】:
我在屏幕上有一个垂直列表来显示图像类别,每个类别/列表都包含水平显示的图像列表。 (附图供参考)
现在当我水平或垂直滚动时,应用程序由于内存泄漏而崩溃。我猜很多人在 ForEach 循环中遇到了这个问题。
我也尝试使用List 而不是ForEach 和ScrollView 进行垂直/水平滚动,但不幸的是遇到了同样的问题。
以下代码是创建垂直列表的主视图:
@ObservedObject var mainCatData = DataFetcher.sharedInstance
var body: some View {
NavigationView {
VStack {
ScrollView(showsIndicators: false) {
LazyVStack(spacing: 20) {
ForEach(0..<self.mainCatData.arrCatData.count, id: \.self) { index in
self.horizontalImgListView(index: index)
}
}
}
}.padding(.top, 5)
.navigationBarTitle("Navigation Title", displayMode: .inline)
}
}
我正在使用下面的代码在每个类别中创建水平列表,我使用了LazyHStack、ForEach 循环和ScrollView
@ViewBuilder
func horizontalImgListView(index : Int) -> some View {
let dataContent = self.mainCatData.arrCatData[index]
VStack {
HStack {
Spacer().frame(width : 20)
Text("Category \(index + 1)").systemFontWithStyle(style: .headline, design: .rounded, weight: .bold)
Spacer()
}
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 20) {
ForEach(0..<dataContent.catData.count, id: \.self) { count in
VStack(spacing : 0) {
VStack(spacing : 0) {
if let arrImgNames = themeContent.catData[count].previewImgName {
// Use dynamic image name and it occurs app crash & memory issue and it reached above 1.0 gb memory
Image(arrImgNames.first!).resizable().aspectRatio(contentMode: .fit)
// If I will use the same image name then there is no memory issue and it consumes only 75 mb
// Image("Category_Image_1").resizable().aspectRatio(contentMode: .fit)
}
}.frame(width: 150, height: 325).cornerRadius(8.0)
}
}
}
}
}
}
以下是我用来从 json 文件中获取图像并将其显示在列表中的数据模型
class DataFetcher: ObservableObject {
static let sharedInstance = DataFetcher()
@Published var arrCatData = [CategoryModel]()
init() {
do {
if let bundlePath = Bundle.main.url(forResource: FileName.CategoryData, withExtension: "json"),
let jsonData = try? Data(contentsOf: bundlePath) {
let decodedData = try JSONDecoder().decode([CategoryModel].self, from: jsonData)
DispatchQueue.main.async { [weak self] in
self?.arrCatData = decodedData
}
}
} catch {
print("Could not load \(FileName.CategoryData).json data : \(error)")
}
}
}
struct CategoryModel : Codable , Identifiable {
let id: Int
let catName: String
var catData: [CategoryContentDataModel]
}
struct CategoryContentDataModel : Codable {
var catId : Int
var previewImgName : [String]
}
崩溃日志:
malloc: can't allocate region
:*** mach_vm_map(size=311296, flags: 100) failed (error code=3)
(82620,0x106177880) malloc: *** set a breakpoint in malloc_error_break to debug
2021-07-01 18:33:06.934519+0530 [82620:5793991] [framework] CoreUI: vImageDeepmap2Decode() returned 0.
2021-07-01 18:33:06.934781+0530 [82620:5793991] [framework] CoreUI: CUIUncompressDeepmap2ImageData() fails [version 1].
2021-07-01 18:33:06.934814+0530 [82620:5793991] [framework] CoreUI: Unable to decompress 2.0 stream for CSI image block data. 'deepmap2'
(82620,0x106177880) malloc: can't allocate region
:*** mach_vm_map(size=311296, flags: 100) failed (error code=3)
(82620,0x106177880) malloc: *** set a breakpoint in malloc_error_break to debug
注意:所有类别的图像都仅从资产加载,如果我将在循环中使用图像的静态名称,则没有内存压力,它只会消耗 75 mb。
我认为存在图像缓存问题。即使我从资产加载图像,我是否必须管理图像缓存?
谁能帮我解决这个问题?任何帮助都感激不尽。谢谢!!
【问题讨论】:
-
代替函数 horizontalImgListView (每次刷新都会生成和渲染内容)尝试使用分离视图,然后 SwiftUI 可以以更健壮的方式处理它。
-
@ViewBuilder 和分离视图(struct)不一样吗?
-
上传崩溃日志。
-
能不能做个小demo app推送到github上?这样我们就可以看得更清楚了。例如,我创建了一个基本的演示应用程序,但我不知道我们在这里处理的是哪种图像。
-
应用程序很少因为内存泄漏而崩溃得那么快。就像它需要一些疯狂和实质性的东西才能崩溃一样。您可以编辑问题并包含崩溃日志吗?
标签: ios memory-leaks swiftui swiftui-list