mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-08 00:04:54 +08:00
feat(spine-ios): Add memory leak detection and fix PMA handling
- Enable debug extension on app startup for leak detection - Add reportLeaks() calls when example views disappear - Fix PMA flag handling by reading it from atlas page instead of hardcoding to false - Add manual dispose() method to SpineController for explicit cleanup if needed Note: SwiftUI view caching may show false positive leaks when views disappear, as SwiftUI keeps views in memory for performance until they're truly no longer needed.
This commit is contained in:
parent
cb62bd70c0
commit
ab53d271a4
@ -28,35 +28,60 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import SpineiOS
|
||||
import SpineSwift
|
||||
import SwiftUI
|
||||
|
||||
// View modifier to report memory leaks when view disappears
|
||||
struct LeakReporter: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.onDisappear {
|
||||
reportLeaks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func reportLeaksOnDisappear() -> some View {
|
||||
modifier(LeakReporter())
|
||||
}
|
||||
}
|
||||
|
||||
struct MainView: View {
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
NavigationLink("Simple Animation") {
|
||||
SimpleAnimation()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Play/Pause") {
|
||||
PlayPauseAnimation()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Animation State Listener") {
|
||||
AnimationStateEvents()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Debug Rendering") {
|
||||
DebugRendering()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Dress Up") {
|
||||
DressUp()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("IK Following") {
|
||||
IKFollowing()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Physics") {
|
||||
Physics()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
NavigationLink("Disable Rendering") {
|
||||
DisableRendering()
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
} header: {
|
||||
Text("Swift + SwiftUI")
|
||||
@ -66,6 +91,7 @@ struct MainView: View {
|
||||
SimpleAnimationViewControllerRepresentable()
|
||||
.navigationTitle("Simple Animation")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.reportLeaksOnDisappear()
|
||||
}
|
||||
} header: {
|
||||
Text("ObjC + UIKit")
|
||||
|
||||
@ -28,11 +28,17 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import SpineiOS
|
||||
import SpineSwift
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct SpineExampleApp: App {
|
||||
|
||||
init() {
|
||||
// Enable debug extension for memory leak detection
|
||||
enableDebugExtension(true)
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
NavigationView {
|
||||
|
||||
@ -110,6 +110,13 @@ public final class SpineController: NSObject, ObservableObject {
|
||||
drawable?.dispose() // TODO move drawable out of view?
|
||||
}
|
||||
}
|
||||
|
||||
/// Manually dispose the drawable. Call this when you know the controller is no longer needed.
|
||||
/// This is useful in SwiftUI where views may be cached and deinit may be delayed.
|
||||
public func dispose() {
|
||||
drawable?.dispose()
|
||||
drawable = nil
|
||||
}
|
||||
|
||||
/// The ``Atlas`` from which images to render the skeleton are sourced.
|
||||
public var atlas: Atlas {
|
||||
|
||||
@ -247,12 +247,15 @@ extension SpineUIView {
|
||||
}
|
||||
|
||||
private func initRenderer(atlasPages: [UIImage]) throws {
|
||||
// Get PMA flag from first atlas page if available
|
||||
let pmaFlag = controller.atlas.pages.count > 0 ? (controller.atlas.pages[0]?.pma ?? false) : false
|
||||
|
||||
renderer = try SpineRenderer(
|
||||
device: SpineObjects.shared.device,
|
||||
commandQueue: SpineObjects.shared.commandQueue,
|
||||
pixelFormat: colorPixelFormat,
|
||||
atlasPages: atlasPages,
|
||||
pma: false // TODO: Get PMA flag from atlas when API is available
|
||||
pma: pmaFlag
|
||||
)
|
||||
renderer?.delegate = controller
|
||||
renderer?.dataSource = controller
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user