I'm creating a widget in swiftui, with a prefilled mock json, stored locally.
Mock JSON has following data:
{
"id":"111",
"title":"some dummy title",
"date":"1609865285",
"thumbnail":"mock4"
}
and mock4 image is stored in the Assets folder.
I load the mock data in the timeline method as follows:
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")
}
}
my widgetui is also a simple one:
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)
}
}
Everything works great, except this setup crashing everytime I try to reload the widget, and observe the memory on Leaks Instrument.
Intially memory consumption is well below 15MB, but after second reload, it jumps to 30MB and crashes.
All the assets I have in local folder did NOT exceed more than 2.5MB and 1.0MB for the custom fonts.
Debuggin MemoryGraph:
I exported the memorygraph at the time of crash, and I got the following info:
Summary:
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
Heap Info:
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
I actually posted only part of heap log, due to body limit on SO.
How do I go forward from here and debug more and find why my widget is eating more memory ?
Note: It is only crashing whenever I try to profile in instruments. In normal cases, the memory consumption stayed below 12MB.