Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI - Possible Memory Leak

I recently started looking into SwiftUI and have run through a few tutorials which recommend swapping views based on state (see the snippet below). However, I noticed while debugging that memory usage slowly creeps up with even the most basic UI. This may just be lack of knowledge but is it wrong to swap views in this sort of manner with SwiftUI?

Version 11.0 (11A420a) - iOS 13

// Memory Leak Test
struct ContentView: View {
    @State private var toggle = false

    func cycleViews() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.toggle = !self.toggle
            self.cycleViews()
        }
    }

    var body: some View {
        Group {
            if toggle {
                ViewA()
            } else {
                ViewB()
            }
        }.onAppear {
            self.cycleViews()
        }
    }
}

struct ViewA: View {
    var body: some View {
        VStack {
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
        }
    }
}

struct ViewB: View {
    var body: some View {
        List {
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
            Text("Some Content")
        }
    }
}
like image 263
WafflesRightMeow Avatar asked Sep 23 '19 17:09

WafflesRightMeow


People also ask

How do I find a memory leak in Swift?

Xcode's Memory Graph Debugger If you haven't used this yet, it's easy to access while developing. Tapping on the icon will pause your application and generate a graph of the objects with their references to other objects. If there's leaked memory detected, you will see purple icons on the left pane of Xcode.

What causes memory leaks in Swift?

A memory leak occurs when allocated memory becomes unreachable and the app can't deallocate it. Allowing an allocated-memory pointer to go out of scope without freeing the memory can cause a memory leak. A retain cycle in your app's object graph can also cause a memory leak.

How does Swift prevent memory leaks?

Breaking a retain cycle to prevent memory leak The cycle must exist because it is required, but all the associations cannot be strong. One of them must be weak or unowned. The weak reference is an optional type, which means weak reference will set to nil once the instance it refers to frees from memory.

Is Apple using SwiftUI?

SwiftUI helps you build great-looking apps across all Apple platforms with the power of Swift — and surprisingly little code. You can bring even better experiences to everyone, on any Apple device, using just one set of tools and APIs.


1 Answers

Your code appears to be perfectly acceptable SwiftUI, and there does appear to be a memory leak somewhere, as switching back and forth (even with a manual Toggle() instead of the asyncAfter() call) leads to increasing memory.

I believe this is a bug with List, because if you change the List to another type of view, the issue disappears, and I haven't noticed it when using this same pattern with all other kinds of views.

I'd recommend you file feedback with Apple, and post the feedback number here so others affected can file their own and reference it.

like image 164
John M. Avatar answered Sep 21 '22 05:09

John M.