swift - 如何调试 SwiftUI Widget 内存问题?
问题描述
我在 swiftui 中创建了一个小部件,带有预填充的模拟 json,存储在本地。
模拟 JSON 有以下数据:
{
"id":"111",
"title":"some dummy title",
"date":"1609865285",
"thumbnail":"mock4"
}
而 mock4 图像存储在 Assets 文件夹中。
我在时间线方法中加载模拟数据如下:
for mockItem in storyManager.getMockData() {
let item = WidgetFeedItem(newsData: mockItem)
items.append(item)
}
let entry = FeedItemEntry(date: Date(), items: entries)
if let nextDate = Calendar.current.date(byAdding: .minute, value: 15, to: Date()) {
let timeline = Timeline(entries: [entry], policy: .after(nextDate))
completion(timeline)
}
struct WidgetFeedItem: Hashable {
var newsTitle = ""
var newsDate = Date()
var newsID = ""
var newsimageURL = ""
var articleLink = ""
var deviceName = ""
init(newsData: NSDictionary) {
newsID = newsData.getStringForKey("id")
newsTitle = newsData.getStringForKey("title")
newsDate = newsData.getDateForKey("date")
deviceName = newsData.getStringForKey("device_name")
newsimageURL = newsData.getStringForKey("thumbnail")
articleLink = newsData.getStringForKey("link")
}
}
我的 widgetui 也是一个简单的:
var body: some View {
ZStack {
VStack {
header
Spacer()
largeBody
Rectangle().fill(Color("separatorColor")).frame(height: 1).padding(.horizontal, 20)
Spacer()
}
getHeaderIcon()
}
}
var header: some View {
ZStack {
if let url = getDeepLink(.none, .header) {
Link(destination: url) {
getHeaderBackground()
getHeaderLabel()
}
}
}
}
var largeBody: some View {
ForEach(entry.items, id: \.self) { item in
HStack {
if let url = getDeepLink(item, .storySubtitle) {
Link(destination: url) {
getImage(item)
getHeadlines(item)
Spacer()
}
}
}.padding(.leading, 20)
.padding(.trailing, 50)
}
}
func getHeaderBackground() -> some View {
VStack {
if isGreenApp() {
Rectangle().fill(LinearGradient(gradient: Gradient(colors: [Color("gr1"), Color("gr2")]), startPoint: .top, endPoint: .bottom)).frame(height: 36)
}
else {
Rectangle().fill(Color("WidgetBackground")).frame(height: 36)
}
}
}
func getHeaderLabel() -> some View {
VStack {
HStack {
Text(getHeaderTitle()).foregroundColor(.white).font(headerFont)
Spacer()
}.padding(.leading, 15)
}
}
func getHeaderIcon() -> some View {
VStack {
if let url = getDeepLink(.none, .header) {
Link(destination: url) {
HStack {
Spacer()
Image("headerIcon").resizable().frame(width: 35, height: 35, alignment: .center).padding(.trailing, 20).padding(.top, 20)
}
}
}
Spacer()
}
}
func getHeadlines(_ item: WidgetFeedItem?) -> some View {
VStack(alignment: .leading) {
Text(item?.newsTitle ?? "").font(titleFont).foregroundColor(Color("textColor")).fixedSize(horizontal: false, vertical: true).lineLimit(3)
Text(item?.newsDate.articleDateFormatForWidget() ?? "").font(subtitleFont).foregroundColor(Color("textColor"))
}
}
func getImage(_ item: WidgetFeedItem?) -> some View {
return HStack {
Image("newsImage")
.data(url: URL(string: item?.newsimageURL ?? "")!).frame(width: 80, height: 50)
}
}
一切都很好,除了每次我尝试重新加载小部件时这个设置崩溃,并观察泄漏仪器上的内存。
最初内存消耗远低于 15MB,但在第二次重新加载后,它会跳到 30MB 并崩溃。
我在本地文件夹中的所有资产都没有超过 2.5MB 和 1.0MB 的自定义字体。
调试内存图:
我在崩溃时导出了内存图,得到了以下信息:
概括:
Physical footprint: 34.4M
Physical footprint (peak): 34.4M
----
ReadOnly portion of Libraries: Total=505.5M resident=218.4M(43%) swapped_out_or_unallocated=287.1M(57%)
Writable regions: Total=615.1M written=24.3M(4%) resident=33.2M(5%) swapped_out=0K(0%) unallocated=581.9M(95%)
VIRTUAL RESIDENT DIRTY SWAPPED VOLATILE NONVOL EMPTY REGION
REGION TYPE SIZE SIZE SIZE SIZE SIZE SIZE SIZE COUNT (non-coalesced)
=========== ======= ======== ===== ======= ======== ====== ===== =======
Activity Tracing 256K 32K 32K 0K 0K 32K 0K 1
CoreAnimation 16K 16K 16K 0K 0K 0K 0K 1
CoreUI image data 5632K 5632K 5632K 0K 0K 0K 0K 1
Foundation 784K 784K 784K 0K 0K 0K 0K 5
IOKit 224K 224K 224K 0K 0K 0K 0K 14
Kernel Alloc Once 32K 16K 16K 0K 0K 0K 0K 1
MALLOC guard page 128K 0K 0K 0K 0K 0K 0K 8
MALLOC metadata 240K 208K 208K 0K 0K 0K 0K 11
MALLOC_LARGE 1632K 1632K 1632K 0K 0K 0K 0K 30 see MALLOC ZONE table below
MALLOC_LARGE metadata 16K 16K 16K 0K 0K 0K 0K 1 see MALLOC ZONE table below
MALLOC_NANO 512.0M 2128K 2128K 0K 0K 0K 0K 1 see MALLOC ZONE table below
MALLOC_SMALL 48.0M 1008K 976K 0K 0K 0K 0K 6 see MALLOC ZONE table below
MALLOC_TINY 7168K 592K 576K 0K 0K 0K 0K 7 see MALLOC ZONE table below
Performance tool data 32.9M 19.8M 19.7M 0K 0K 0K 0K 10 not counted in TOTAL below
STACK GUARD 96K 0K 0K 0K 0K 0K 0K 6
Stack 3728K 304K 272K 0K 0K 0K 0K 6
Stack (reserved) 544K 0K 0K 0K 0K 0K 0K 1 reserved VM address space (unallocated)
Stack Guard 16K 0K 0K 0K 0K 0K 0K 1
VM_ALLOCATE 2608K 1504K 1488K 0K 0K 0K 0K 5
VM_ALLOCATE (reserved) 16K 0K 0K 0K 0K 0K 0K 1 reserved VM address space (unallocated)
__AUTH 1946K 1898K 82K 0K 0K 0K 0K 264
__AUTH_CONST 14.8M 8245K 3432 0K 0K 0K 0K 389
__DATA 9926K 5739K 944K 0K 0K 0K 0K 381
__DATA_CONST 12.9M 9.8M 80K 0K 0K 0K 0K 394
__DATA_DIRTY 1325K 1245K 661K 0K 0K 0K 0K 319
__FONT_DATA 4K 0K 0K 0K 0K 0K 0K 1
__LINKEDIT 152.2M 28.7M 0K 0K 0K 0K 0K 8
__OBJC_CONST 2883K 2883K 13K 0K 0K 0K 0K 237
__OBJC_RO 71.2M 55.0M 0K 0K 0K 0K 0K 1
__OBJC_RW 2896K 1805K 13K 0K 0K 0K 0K 1
__TEXT 353.3M 189.7M 80K 0K 0K 0K 0K 414
__UNICODE 588K 528K 0K 0K 0K 0K 0K 1
mapped file 31.9M 4592K 48K 0K 0K 0K 0K 9
shared memory 48K 48K 48K 0K 0K 0K 0K 3
unused but dirty shlib __DATA 268K 268K 268K 0K 0K 0K 0K 74
=========== ======= ======== ===== ======= ======== ====== ===== =======
TOTAL 1.2G 323.5M 15.9M 0K 0K 32K 0K 2603
TOTAL, minus reserved VM space 1.2G 323.5M 15.9M 0K 0K 32K 0K 2603
VIRTUAL RESIDENT DIRTY SWAPPED ALLOCATION BYTES DIRTY+SWAP REGION
MALLOC ZONE SIZE SIZE SIZE SIZE COUNT ALLOCATED FRAG SIZE % FRAG COUNT
=========== ======= ========= ========= ========= ========= ========= ========= ====== ======
DefaultMallocZone_0x10227c000 512.0M 2128K 2128K 0K 15522 888K 1240K 59% 1
MallocHelperZone_0x102254000 55.6M 3216K 3168K 0K 1056 2559K 609K 20% 43
QuartzCore_0x1023b0000 1024K 32K 32K 0K 7 1888 30K 95% 1
=========== ======= ========= ========= ========= ========= ========= ========= ====== ======
TOTAL 568.6M 5376K 5328K 0K 16585 3449K 1879K 36% 45
堆信息:
Physical footprint: 34.4M
Physical footprint (peak): 34.4M
----
Process 409: 3 zones
All zones: 16585 nodes malloced - Sizes: 1024KB[1] 64KB[1] 48KB[1] 32KB[4] 16KB[23] 13KB[4] 12KB[1] 10KB[2] 9KB[1] 8.5KB[7] 8KB[18] 6.5KB[1] 5KB[5] 4.5KB[3] 4KB[13] 3.5KB[6] 3KB[13] 2.5KB[15] 2KB[25] 1.5KB[40] 1KB[20] 1008[1] 960[1] 944[1] 896[1] 880[1] 864[15] 848[1] 832[1] 800[9] 784[9] 768[2] 752[5] 688[6] 672[1] 656[32] 640[8] 624[1] 608[15] 592[2] 576[3] 544[22] 528[14] 512[52] 480[53] 464[12] 448[3] 432[12] 400[10] 384[18] 368[173] 352[60] 336[39] 320[12] 304[9] 288[35] 272[29] 256[76] 240[36] 224[21] 208[224] 192[66] 176[97] 160[140] 144[84] 128[523] 112[920] 96[617] 80[858] 64[1638] 48[3851] 32[5588] 16[974]
Found 491 ObjC classes
Found 483 Swift classes
Found 143 CFTypes
-----------------------------------------------------------------------
All zones: 16585 nodes (3531952 bytes)
COUNT BYTES AVG CLASS_NAME TYPE BINARY
===== ===== === ========== ==== ======
3327 1837840 552.4 non-object
1948 62336 32.0 Class.data (class_rw_t) C libobjc.A.dylib
1011 32352 32.0 NSMutableDictionary ObjC CoreFoundation
973 172160 176.9 NSMutableDictionary (Storage) C CoreFoundation
857 43008 50.2 CFString ObjC CoreFoundation
571 27408 48.0 Class.data.extended (class_rw_ext_t) C libobjc.A.dylib
458 120336 262.7 CFData ObjC CoreFoundation
454 21792 48.0 NSMutableArray ObjC CoreFoundation
437 13808 31.6 NSMutableArray (Storage) C CoreFoundation
346 17888 51.7 Swift closure context Swift <unknown>
267 44640 167.2 Class.methodCache._buckets (bucket_t) C libobjc.A.dylib
256 15120 59.1 __NSMallocBlock__ ObjC libsystem_blocks.dylib
231 7392 32.0 NSDictionary ObjC CoreFoundation
231 3696 16.0 NSDictionary.cow (struct __cow_state_t) C CoreFoundation
228 80304 352.2 NSDictionary (Storage) C CoreFoundation
176 5632 32.0 NSNumber ObjC CoreFoundation
134 8704 65.0 Class.data.methods (method_array_t) C libobjc.A.dylib
133 6784 51.0 _ContiguousArrayStorage<AGAttribute> Swift libswiftCore.dylib
104 13280 127.7 _ContiguousArrayStorage<DisplayList.Item> Swift libswiftCore.dylib
100 43312 433.1 NSDictionary ObjC CoreFoundation
88 8448 96.0 TypedElement<AccessibilityProperties.ViewTypeDescription> Swift SwiftUI
81 4560 56.3 __NSMallocBlock__ ObjC libsystem_blocks.dylib
80 3216 40.2 NSArray ObjC CoreFoundation
72 4608 64.0 TypedElement<AccessibilityProperties.TraitsKey> Swift SwiftUI
69 4384 63.5 _ContiguousArrayStorage<ViewTransform.Chunk> Swift libswiftCore.dylib
69 3312 48.0 Chunk Swift SwiftUI
69 3312 48.0 _ContiguousArrayStorage<ViewTransform.Chunk.Tag> Swift libswiftCore.dylib
68 3264 48.0 _ContiguousArrayStorage<CGFloat> Swift libswiftCore.dylib
66 1056 16.0 NSArray ObjC CoreFoundation
59 19360 328.1 CFDictionary (Value Storage) C CoreFoundation
58 5568 96.0 TypedElement<AccessibilityProperties.LabelKey> Swift SwiftUI
57 912 16.0 NSSet ObjC CoreFoundation
55 2640 48.0 NSKeyValueObservance ObjC Foundation
52 4352 83.7 CFString (Storage) C CoreFoundation
49 10192 208.0 UITraitCollection ObjC UIKitCore
47 22560 480.0 ResolvedStyledText Swift SwiftUI
47 16544 352.0 _ContiguousArrayStorage<AccessibilityNodeAttachment> Swift libswiftCore.dylib
47 2256 48.0 __SharedStringStorage Swift libswiftCore.dylib
47 1504 32.0 NSConcreteMutableAttributedString ObjC Foundation
47 752 16.0 NSMutableRLEArray ObjC Foundation
44 2816 64.0 CFDictionary ObjC CoreFoundation
44 1408 32.0 AGSubgraph CFType AttributeGraph
41 2624 64.0 TypedElement<AccessibilityProperties.InputLabelsKey> Swift SwiftUI
40 1840 46.0 Class.data.properties (property_array_t) C libobjc.A.dylib
36 13440 373.3 CFDictionary (Key Storage) C CoreFoundation
36 2304 64.0 OS_os_log ObjC libsystem_trace.dylib
35 4496 128.5 _ContiguousArrayStorage<PreferencesOutputs.KeyValue> Swift libswiftCore.dylib
35 1120 32.0 NSAttributeDictionaryEnumerator ObjC UIFoundation
34 2048 60.2 _ContiguousArrayStorage<AccessibilityNode> Swift libswiftCore.dylib
33 3696 112.0 CUIRenditionKey ObjC
由于 SO 的正文限制,我实际上只发布了部分堆日志。
我如何从这里继续进行更多调试并找出为什么我的小部件正在消耗更多内存?
注意:只有当我尝试在仪器中进行分析时它才会崩溃。在正常情况下,内存消耗保持在 12MB 以下。
解决方案
推荐阅读
- gupshup - gupshup api中特定号码的选择加入状态
- ansible - 在 ansible 2.3 版中导入或包含剧本
- php - woocommerce 产品属性为空
- javascript - 如何防止浏览器在基于脚本的 Web 应用程序的 URL 中添加用户参数?
- android - SQLite UPDATE WHERE 性能
- javascript - 将数组传递给按钮的 href
- discord - Discord Python 重写 - Reaction 帮助 (Cog)
- python - Python Scrapy - 如何在不忽略过滤器的情况下获取这些名称?
- autodesk-forge - Forge Viewer 中的自定义光照环境和着色器
- swift - 如何在 Firebase Firestore 中存储 alertView 的文本?