首页 > 解决方案 > 如何调试 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 以下。

标签: swiftswiftuiios14xcode-instrumentswidgetkit

解决方案


推荐阅读