Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Xcode 15.3 concurrency warnings when using Screen.scale #766

Merged
merged 1 commit into from
Mar 20, 2024

Conversation

jszumski
Copy link
Contributor

@jszumski jszumski commented Mar 7, 2024

Fixes #765. The viral nature of concurrency unfortunately means that the blast radius is pretty high for just 2 warning fixes:

  • Adds @MainActor to direct and downstream callers of Screen.scale
  • Adds @MainActor to downstream callers in tests
  • Moves @MainActor from XCTestCases to individual test functions instead
  • Switches the image pipeline thread safety test from resizing to blurring. This avoids marking the test as @MainActor which would destroy its ability to test threading.

@kean
Copy link
Owner

kean commented Mar 7, 2024

Hey, @jszumski. Thanks for raising the issue and taking a stab at it.

means that the blast radius is pretty high for just 2 warning

Right, I also would prefer to avoid limiting most of these APIs to the main-thread. What I would suggest trying instead is updating ImageTargetSize so that it no longer pre-computes the size in pixels.

@jszumski
Copy link
Contributor Author

jszumski commented Mar 8, 2024

What I would suggest trying instead is updating ImageTargetSize so that it no longer pre-computes the size in pixels.

@kean Any pointers to where an async call to the MainActor might fit best? I don't know much about the internals of Nuke, but I assume the entire pipeline should be able to run in a background thread, so it would have to be done in an initial step somewhere and fed down into these other call sites?

@kean
Copy link
Owner

kean commented Mar 8, 2024

Any pointers to where an async call to the MainActor might fit best?

I briefly looked into it, and I'm really not sure. None of these potential solutions seem ideal. You need the pixel size during resizing and resizing happens in the background. I'm also not sure how pre-computing it would look like. After considering these options, restricting certain, but not all, initializers to the main thread doesn't seem like the worst option.

@kean
Copy link
Owner

kean commented Mar 9, 2024

If you remove the @MainActor attribute from Nuke.Screen, the warning goes away. It was added in 2022 to fix a warning in one of the previous versions of Xcode.

UIScreen.main is also deprecated, so it's probably worth just removing ImageProcessingOptions.Unit and only allowing to use the size in pixels.

@jszumski jszumski force-pushed the fix-uiscreen-uses-main-actor branch from 85cbd65 to 3e03d0e Compare March 20, 2024 18:15
@jszumski
Copy link
Contributor Author

Updated with that fix. I'm honestly surprised it works.

@kean
Copy link
Owner

kean commented Mar 20, 2024

Yeah, it seems like a compiler bug. I gave up trying to find any official documentation on how it's supposed to work. The rules for Sendable will now probably require a separate book.

Maybe it works because it's static and the compiler knows to init it on the main actor.

@kean kean merged commit b01a8f7 into kean:main Mar 20, 2024
8 checks passed
@jszumski jszumski deleted the fix-uiscreen-uses-main-actor branch March 20, 2024 18:48
@kean
Copy link
Owner

kean commented Mar 26, 2024

Updated with that fix. I'm honestly surprised it works.

I think it was just a bug with "minimum" concurrency checking, which I use, and now it's been fixed. I wouldn't expect a warning here with "minimum" checking.

Btw, if you enable "complete" checking, it becomes an error:

Screenshot 2024-03-26 at 7 53 12 PM

@jszumski
Copy link
Contributor Author

jszumski commented Apr 2, 2024

I wonder if UITraitCollection.current.displayScale is a better replacement that could side step the main actor requirement?

@kean
Copy link
Owner

kean commented May 2, 2024

I wonder if UITraitCollection.current.displayScale is a better replacement that could side step the main actor requirement?

Great suggestion! It looks like it is and it is not confined to the main thread:

UIKit stores the value of the currentTraitCollection property as a thread-local variable, so access is lightweight and free of side effects. 

I'm going to go with UITraitCollection.current.displayScale in the upcoming version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Xcode 15.3 concurrency warnings when using Screen.scale
2 participants