I can't update the original post, so I'll provide more context here:
Turns out, the ForEach is not the problem. The problem is simply that each subview will add 60 calls each per second of animation duration.
Interestingly, this happens even when the subview has no dependencies and all values are hardcoded.
Could the problem be with the custom animation implementation?
Post
Replies
Boosts
Views
Activity
I'm surprised there is no actual answer to this question. SwiftUI seems to take us quite some steps back when trying to do real-world things. I would be happy to use UIKit for this (less than a morning to get it done), but since this needs to live in a live activity, that is a no-go.
Is it really that difficult to 'declare' in SwiftUI that subviews do not need to be re-rendered during animation, animate(:::) does not neet to be called 60 times for each subview for the same time, and layout should be differently during animation as opposed to between animations?
Where is the documentation that goes in-debt in how things work together? Or are documentation writers as lost in generics&protocols-land as developers are?
If Scrollview is not the right fit, I can probably manage using regular views. I am not looking for user interaction anyway, but to set the offsrt programmatically based on sensor input.
Hi jblaker,
Did you ever find a solution to this one? If so please share, It might help me with a similar issue: https://forums.developer.apple.com/forums/thread/745840
Cheers,
Joride
I've now been unable to load any app on my device. Here is the exact error I get:
Error mounting image: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)
The developer disk image could not be mounted on this device.
Domain: com.apple.dt.CoreDeviceError
Code: 12040
Failure Reason: Error mounting image: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)
User Info: {
DDIPath = "/Users/Joride/Library/Developer/DeveloperDiskImages/iOS_DDI.dmg";
DVTErrorCreationDateKey = "2024-02-07 12:09:32 +0000";
DeviceIdentifier = "625254F9-0CB7-4135-B261-D73FA85274F3";
IDERunOperationFailingWorker = IDEInstallCoreDeviceWorker;
NSURL = "file:///Users/Joride/Library/Developer/DeveloperDiskImages/iOS_DDI.dmg";
Options = {
MountedBundlePath = "file:///private/var/tmp/CoreDevice_DDI_Staging_501/625254F9-0CB7-4135-B261-D73FA85274F3/";
UseCredentials = 0;
};
"com.apple.dt.DVTCoreDevice.operationName" = enablePersonalizedDDI;
}
--
Error mounting image: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)
Domain: com.apple.mobiledevice
Code: -402652907
User Info: {
FunctionName = AMDeviceRemoteMountPersonalizedBundle;
LineNumber = 2108;
}
--
Failed to initialize remote device attributes: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)
Domain: com.apple.mobiledevice
Code: -402652907
User Info: {
FunctionName = "-[PersonalizedImage mountImage:]";
LineNumber = 1772;
}
--
Failed to retrieve personalization identifiers: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)
Domain: com.apple.mobiledevice
Code: -402652907
User Info: {
FunctionName = "-[PersonalizedImage initializeRemoteDeviceAttributes:]";
LineNumber = 1367;
}
--
Event Metadata: com.apple.dt.IDERunOperationWorkerFinished : {
"device_isCoreDevice" = 1;
"device_model" = "iPhone16,1";
"device_osBuild" = "17.3 (21D50)";
"device_platform" = "com.apple.platform.iphoneos";
"dvt_coredevice_version" = "355.7.7";
"dvt_mobiledevice_version" = "1643.60.2";
"launchSession_schemeCommand" = Run;
"launchSession_state" = 1;
"launchSession_targetArch" = arm64;
"operation_duration_ms" = 230972;
"operation_errorCode" = "-402652907";
"operation_errorDomain" = "com.apple.dt.CoreDeviceError.12040.com.apple.mobiledevice";
"operation_errorWorker" = IDEInstallCoreDeviceWorker;
"operation_name" = IDERunOperationWorkerGroup;
"param_debugger_attachToExtensions" = 0;
"param_debugger_attachToXPC" = 1;
"param_debugger_type" = 3;
"param_destination_isProxy" = 0;
"param_destination_platform" = "com.apple.platform.iphoneos";
"param_diag_MainThreadChecker_stopOnIssue" = 0;
"param_diag_MallocStackLogging_enableDuringAttach" = 0;
"param_diag_MallocStackLogging_enableForXPC" = 1;
"param_diag_allowLocationSimulation" = 1;
"param_diag_checker_tpc_enable" = 1;
"param_diag_gpu_frameCapture_enable" = 0;
"param_diag_gpu_shaderValidation_enable" = 0;
"param_diag_gpu_validation_enable" = 0;
"param_diag_memoryGraphOnResourceException" = 0;
"param_diag_queueDebugging_enable" = 1;
"param_diag_runtimeProfile_generate" = 0;
"param_diag_sanitizer_asan_enable" = 0;
"param_diag_sanitizer_tsan_enable" = 0;
"param_diag_sanitizer_tsan_stopOnIssue" = 0;
"param_diag_sanitizer_ubsan_stopOnIssue" = 0;
"param_diag_showNonLocalizedStrings" = 0;
"param_diag_viewDebugging_enabled" = 1;
"param_diag_viewDebugging_insertDylibOnLaunch" = 1;
"param_install_style" = 0;
"param_launcher_UID" = 2;
"param_launcher_allowDeviceSensorReplayData" = 0;
"param_launcher_kind" = 0;
"param_launcher_style" = 99;
"param_launcher_substyle" = 8192;
"param_runnable_appExtensionHostRunMode" = 0;
"param_runnable_productType" = "com.apple.product-type.application";
"param_structuredConsoleMode" = 1;
"param_testing_launchedForTesting" = 0;
"param_testing_suppressSimulatorApp" = 0;
"param_testing_usingCLI" = 0;
"sdk_canonicalName" = "iphoneos17.2";
"sdk_osVersion" = "17.2";
"sdk_variant" = iphoneos;
}
--
System Information
macOS Version 14.3 (Build 23D56)
Xcode 15.2 (22503) (Build 15C500b)
Timestamp: 2024-02-07T13:09:32+01:00
Running this in an optimised build will change the numbers signifcantly. Filling the frame AND generating a CGImage from those raw bytes takes 16 µs (average of a couple of hundred runs)!
The difference between an optimized build and a debug build is quite staggering (to me). Of course that is why profiling gets done on release (i.e. optimized) builds.
Important to add
let screenWidth: Int = 256 let screenHeight: Int = 240
`
While waiting for review and approval (seriously?), let me add some relevant info:
Instruments shows that most of the time is being spent in Swifts IndexingIterator.next() function. There is quite a substantial subtree inside it, maybe there is way to reduce the time spent there?
Yes right, thank you. Your first point is indeed a better phrased version of mine. The 2nd point make sense too, and did not occur to me.
I will dive into Swift actors, and look forward to learning how these will help me simplify and strengthen my code.
Thanks for going along with me and help me structure my thoughts!
Thanks for sharing. I think that article made me see 2 possible benefits, correct me if I’m wrong:
if there is code that never makes its way up to a synchronous context, code will look more linear. Example: downloading some data and persisting it, without directly surfacing the new content in the ui
code that does make its way into a sync context (like my example), will have only a sinlge place where the code is non-linear. Everything behind that function call can be impkemented wit async/await, simplifying the underlying code possibly a lot
Is that about right? Anything else I am missing?
Thank you Rincewind, that is th answer that made it all clear to me. I guess I should have l led with my last post when opening this thread. I'm happy it now works, and more importantly, I understand why it works!
Thanks for taking the time and effort to bear with me, I appreciate it!
So in your case you should update everything directly. Unfortunately you have to do that for every navigation controller you want to do this with individually.
This is not a problem at all: there is only one navigationbar in my app, and so I am quite happy to update the navigation bar directly. In fact, this is how I wrote it originally, and worked great:
self.rootNavigationController.navigationBar.barTintColor = color;
self.rootNavigationController.navigationBar.tintColor = textColor;
self.rootNavigationController.navigationBar.translucent = NO;
The issue is that this code no longer works when building against iOS16: the navigation bar stays transparent no matter how many times this code is called.
For dynamically changing styles you should instead update the navigation bar directly. As my colleague pointed out the biggest issue with appearance proxy here is that it gets slower every time you request a new proxy (i.e. call -appearance).
So then my question would be: what is the proper way to update the navigation bar directly in iOS16?
Thanks, that is helpful!
I think it is important to explain the VC hierarchy a bit (it involves a UIScrollView (well, UICollectionView), which seems to have some acquired 'behind-the-scenes' connections with UINavigationBar)
UIWindow
|-- UINavigationController
|-- CustomContainerViewController (1)
|-- CustomContainerViewController (2) + DrawerViewController // from top side
|-- ContentViewController + DrawerViewController // from right side
CustomContainerViewController (1) contains two viewcontrollers: one filling the view of the container itself, the 'content' which is itself a CustomContainerViewController (the one called CustomContainerViewController (2). The 2nd viewcontroller in this CustomContainerViewController (1) is one that can be pulled down using a 'handle', drawn by the CustomContainerViewController (1), (making it seem as if it is pulled from behind the navigationbar).
CustomContainerViewController (2) is the 'content' of CustomContainerViewController (1). This container has the actual content in it's first viewController, and another viewController that can be pulled in from the right side of the screen, using another 'handle'.
That last one (the one that can be pulled in from the right side of the screen), has a UICollectionView filling the view of that viewController (not sure if this is important).
Here is the code that is called in -application:didFinishLaunchingWithOptions: and in response to a button tapped by the user to change the navigationBar's color:
UIColor *color = ...;
UIColor *textColor = ...;
self.rootNavigationController.navigationBar.barTintColor = color;
self.rootNavigationController.navigationBar.tintColor = textColor;
self.rootNavigationController.navigationBar.translucent = NO;
When building this against iOS16, the app has a transparent UINavigationBar, not what it should be: an opaque color. When those three lines hit, the navigationbar stays transparent.
With a small change (see below), the navigationbar now has the correct color (after this code gets called in application:didFinishLaunchingWithOptions:), but afterwards this code seems to have no effect.
UIColor *color = ...;
UIColor *textColor = ...;
if (@available(iOS 13.0, *))
{
[UINavigationBar appearance].standardAppearance.backgroundColor = color;
[UINavigationBar appearance].compactAppearance = [UINavigationBar appearance].standardAppearance;
[UINavigationBar appearance].scrollEdgeAppearance = [UINavigationBar appearance].standardAppearance;
}
self.rootNavigationController.navigationBar.barTintColor = color;
self.rootNavigationController.navigationBar.tintColor = textColor;
self.rootNavigationController.navigationBar.translucent = NO;
Might this be a bug in the iOS16 sdk?
Thanks for a your answer Rincewind.
I don't have a particularly large app, there are only 4 or 5 viewcontrollers in total.
The reason I am working with the appearance api is because it seems I have no choice: in when building against iOS16, the navigationbar behaves differently (i.e. it is transparent in iOS16, whereas it is not when building against iOS15).
I came across this thread in which you provided a solution using the appearance api, which makes it seem to me that the only way to solve my original issue is to use the appearance apis.
If there is a way to do update the colors and attributes of a navigationbar 'manually' in iOS16, without using the appearance apis, I would love to hear it. There is only one code-path for this feature, so it would be simple enough (famous last words...).
Unfortunately not. I gave up on building using that document based stuff. Even if I could get it to work now, it seems very fragile to me, and not something I want to use as a foundation for my app.