Responsible for this is ANECompilerService, have seen virtual RAM usage of over 407 GB right before crashing on an M1 Mac mini with 16gb of RAM.
Crash pattern:
slowing down
opening a dialog to "Force Quit Applications" because I am running out of application memory (only Finder was running)
freezing
after a while, the pink/purple screen mentioned above + reboot
Post
Replies
Boosts
Views
Activity
Just import SwiftUI in the file that needs @AppStorage support, no need to hold back on this convenient wrapper just because of older code, they can co-exist.
Same here, can probably be ignored though which is hard for me because I hate warnings...
That worked like a charm, OOPer, thank you!
UPDATE:
This never really got solved, not by me and not by Apple, so I decided to go with a Class and update the view by adding a bool named "triggerViewUpdate" to my AppState class, and doing a "triggerViewUpdate.toggle()" whenever needed.
This might not be the most elegant solution, but it works well enough for my use case.
Thanks for the efforts, OOPer and Claude31!
I tested on Big Sur, so our results may vary. Someone tested on Catalina and noticed a difference, but he is on an older iMac and the Class slider was also less smooth than on my machine.
Apple requested a test project, so I sent them the test I posted here. I hope they can shed some light on this, and show me a workaround. I will post the results here!
Test project + 8K test_image for assets AND a complete compiled test are available at:
https://www.icloud.com/iclouddrive/0m2o4VTzRyD12IkKj0BJptIqg#Class_vs_Struct/Archive.zip
(Archive.zip)
Please run this fullscreen and let me know your thoughts after running all sliders for a while.
I do have to admit that the sliders are a bit smoother outside of my project. This is with only 1 filter though, while the project might run a combination of about 30 CoreImage filters (pipelined).
Ok, I made 3 videos, one with the binding from a Class, the other with the same Class as an ObservableObject, and one with a Struct
https://www.icloud.com/iclouddrive/0m2o4VTzRyD12IkKj0BJptIqg#Class_vs_Struct
I think it's pretty obvious there's something off here... it's literally the same code, only the way the binding was made has changed...
It does reproduce the issue though.
If you move the Struct and Observed sliders around for a bit, the slider lags behind the pointer.
The Class one sticks to the pointer.
That's with one slider... an array of multiple sliders makes it even worse.
Hi OOPer, thanks for trying!
The Metal View works perfectly, when the bindings are class-based, and isn't even in this example so it's purely the difference between struct / observed / class based bindings that matters here. Sometimes it's less noticeable though, but always too slow for my use case.
I spent one of my 2 yearly code-level helps to get help from an Apple Engineer, something's definitely off or I am doing something very wrong here.
Will update here when I got news from them.
I tested (with your OP code) in Simulator with Xcode 12.2 and did not notice any performance issue you are mentioning.
Can you explain and give figures ?
Anyway, class should be faster because it does not call all the mechanisms to update the UI when its state changes. But that is the core value of SwiftUI !
Question is : is this performance difference, if any, significant enough from a user perspective ?
Main difference is that slider with class is not updated until I move the Struct slider. And that's normal. - Claude31 Thanks for your reply, Claude31.
I assume you tried this on an iOS simulator, right? This works much better, yes.
But my question is specific to macOS, would you mind trying that?
The performance difference is extremely significant, in my simple photo filtering app which renders to a Metal View, my frame rate drops from the requested 60 fps to a mere 6fps... it's a horrible experience.
Do you think there's a workaround for the UI update stuff so I can keep using a Class?
I also added an example to my test code that uses ObservedObject / ObservableObject.
This solves the responsiveness of the UI, but again makes the slide more choppy. Not as bad as the Struct version, but somewhere in between.
Code:
//
//	ContentView.swift
//	SlowStructFastClass
//
//	Created by Michel Storms on 12/01/2021.
//
import SwiftUI
class VC {
		var s1: Double = 0.5
}
class VD: ObservableObject {
		@Published var s1: Double = 0.5
}
struct ContentView: View {
		@State var valueStruct: Double = 0.5
		@State var valueClass = VC()
		@ObservedObject var valueClassObserved = VD()
		
		var body: some View {
				VStack {
						Text("STRUCT")
						Slider(value: $valueStruct)
						Text("\(self.valueStruct)")
						
						Text("CLASS")
						Slider(value: $valueClass.s1)
						Text("\(self.valueClass.s1)")
						
						Text("CLASS - OBSERVABLEOBJECT")
						Slider(value: $valueClassObserved.s1)
						Text("\(self.valueClassObserved.s1)")
				}
		}
}
Thanks everyone for posting your experiences.
I'm building a photo filter app (hobby project) from scratch for macOS. and got here when researching why my sliders started to become too slow to use and what to do about it.
So I added the example by Graphics and Games Engineer to my project to replace my "ImageView" and display my CI / CG images directly without converting them to NSImage.
So far I got a working view, which shows a green background, but I am unable to figure out how to display my image on this, what to pass as context to view as it wants an NSViewRepresentableContext and the only thing I have is a CIContext...
I think I want to be able to display filter.outputImage... here's an example of how I make this:
func ciExposure (inputImage: CIImage, inputEV: Double) -> CIImage {
let filter = CIFilter(name: "CIExposureAdjust")!
filter.setValue(inputImage, forKey: kCIInputImageKey)
filter.setValue(inputEV, forKey: kCIInputEVKey)
return filter.outputImage!
}
Can someone give me a hint about how to do this? I don't mind doing research but it starts to feel like I've hit a wall here...
Thanks in advance!
The perfect answer, this helped me a lot. Thank you so much!
In addition to the solution offered by Quincey Morris, if you can't find said placeholder, try closing and reopening your project, or even Xcode.