Skip to content

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

Merged
kean merged 1 commit into
kean:mainfrom
jszumski:fix-uiscreen-uses-main-actor
Mar 20, 2024
Merged

Fix Xcode 15.3 concurrency warnings when using Screen.scale#766
kean merged 1 commit into
kean:mainfrom
jszumski:fix-uiscreen-uses-main-actor

Conversation

@jszumski

@jszumski jszumski commented Mar 7, 2024

Copy link
Copy Markdown
Contributor

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

kean commented Mar 7, 2024

Copy link
Copy Markdown
Owner

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

jszumski commented Mar 8, 2024

Copy link
Copy Markdown
Contributor Author

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

kean commented Mar 8, 2024

Copy link
Copy Markdown
Owner

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

kean commented Mar 9, 2024

Copy link
Copy Markdown
Owner

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
Copy Markdown
Contributor Author

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

@kean

kean commented Mar 20, 2024

Copy link
Copy Markdown
Owner

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
@jszumski jszumski deleted the fix-uiscreen-uses-main-actor branch March 20, 2024 18:48
@kean

kean commented Mar 26, 2024

Copy link
Copy Markdown
Owner

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

jszumski commented Apr 2, 2024

Copy link
Copy Markdown
Contributor Author

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

@kean

kean commented May 2, 2024

Copy link
Copy Markdown
Owner

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