Post

Replies

Boosts

Views

Activity

What does the @__EntryDefaultValue macro expand to?
In Xcode 16.0 and 16.1, it was clear how @Entry macro works from the generated code. If you explicitly specify the type, then defaultValue is a computed property, if you do not specify the type, then a stored property. In Xcode 16.2, @__EntryDefaultValue has been added to the generated code, which Xcode does not want to expand. Visually, it seems that a stored property is generated, but the behavior shows that as a result we have a computed property, and for both options: with an explicit type and without an explicit type. So the question is: what does this @__EntryDefaultValue macro generate and is the result a bug? Or was it a bug in previous versions of Xcode?
1
0
212
3w
What's wrong with the List in debug mode on Xcode 16? And partly in the release mode.
When building in Xcode 15.4 debug, only a part of the initial View for List is initialized. As you scroll, new ones are initialized, and old ones are destroyed. When building the same code in Xcode 16.2, ALL Views are initialized first, and then immediately destroyed as you scroll, new ones are initialized, and old ones are destroyed. MRE: struct ContentView: View { private let arr = Array(1...5555) var body: some View { List(arr, id: \.self) { ListCellView(number: $0) } } } struct ListCellView: View { private let number: Int private let arr: [Int] @StateObject private var vm: ListCellViewModel // Just to print init/deinit init(number: Int) { print(#function, Self.self, number) self.arr = Array(0...number) self.number = number let vm = ListCellViewModel(number: number) // To see duplicates of init self._vm = StateObject(wrappedValue: vm) // because here is @autoclosure } var body: some View { let _ = print(#function, Self.self, number) Text("\(number)") } } class ListCellViewModel: ObservableObject { private let number: Int init(number: Int) { print(#function, Self.self, number) self.number = number } deinit { print(#function, Self.self, number) } } An example from a memory report with this code: Fortunately, the behavior in release mode is the same as in Xcode 15.4. However, the double initialization of Views is still present and has not been fixed. ... init(number:) ListCellView 42 init(number:) ListCellViewModel 42 init(number:) ListCellView 42 init(number:) ListCellViewModel 42 deinit ListCellViewModel 42 body ListCellView 42 Yes, unnecessary View initializations and extra body calls are "normal" for SwiftUI, but why do they here twice so that one is discarded immediately?
2
0
209
Jan ’25
Debug Memory Graph does not show memory leaks.
Here is a modified code from the documentation example https://www.swift.org/documentation/server/guides/memory-leaks-and-usage.html#troubleshooting : class ViewController: UIViewController { var closure: () -> Void = { () } public func doNothing() {} public func doSomethingThatLeaks() { self.closure = { // This will leak as it'll create a permanent reference cycle: // // self -> self.closure -> self self.doNothing() } } override func viewDidLoad() { super.viewDidLoad() // Memory leak example: doSomethingThatLeaks() // Abandoned memory example: // NotificationCenter.default.addObserver(forName: .init("Abandoned"), object: nil, queue: nil) { _ in // print("\(self)") // } } deinit { print(#function, Self.self) } } If you place it, for example, in a navigation controller, do a push-pop several times, deinit will not be printed. But if you look in the Debug Memory Graph, it will not even show that there is a strong reference to this controller: Only if you manually select: You can see that it is held by the closure context, which it holds: This is definitely not abandoned memory (like the commented piece of the code example), but it is not shown either in the Debug Memory Graph or in Instruments Leaks. Why?
0
1
317
Nov ’24