Skip to content

Isolate the UIKit-facing API to the main actor - #54

Open
radimvaculik wants to merge 1 commit into
futuredapp:mainfrom
radimvaculik:feature/main-actor-isolation
Open

Isolate the UIKit-facing API to the main actor#54
radimvaculik wants to merge 1 commit into
futuredapp:mainfrom
radimvaculik:feature/main-actor-isolation

Conversation

@radimvaculik

Copy link
Copy Markdown

Motivation

CellKit is a UITableView/UICollectionView data source layer — every one of its protocols is only ever exercised on the main thread. But the protocols are declared nonisolated, so under Swift 6 every consumer conformance reports:

warning: conformance of 'FooCellModel' to protocol 'CellConvertible' crosses into
main actor-isolated code and can cause data races; this is an error in the Swift 6 language mode

In an app I migrated to Swift 6 this accounted for 61 of 498 warnings — the second largest group. The only consumer-side workaround is to annotate every single conformance:

extension FooCellModel: CellModel, @MainActor ReusableCellConvertible {

which had to be repeated 45 times, plus a @preconcurrency import CellKit where a cell model is built off the main thread.

Change

@MainActor on the API that touches UIKit:

  • CellKitReusableView, CellConfigurable, CellModel, SupplementaryViewModel, CellConvertible, CellModelSelectable, CellModelDataSourceDelegate, DataSource, CollectionSupplementaryViewModel, AbstractDataSource, CellModelDataSource, LazyCellProvider, LazySupplementaryViewProvider
  • DiffableCellKitDifferentiableCellModel, DifferentiableCellModelDataSource

DifferentiableCellModelWrapper needed a small rework: DifferenceKit's Differentiable/Equatable requirements are nonisolated, so differenceIdentifier is now computed once in a @MainActor init and stored, and == uses MainActor.assumeIsolated. Wrappers are only ever created and diffed by DifferentiableCellModelDataSource, which is now main actor-isolated, so the assumption holds.

MainActor.assumeIsolated requires iOS 13, so Package.swift platforms go from .v9 to .v13. DiffableCellKit already required iOS 13 throughout, and current SPM toolchains no longer accept iOS 9 anyway.

This is source-breaking

Any conformance that is not main actor-isolated will stop compiling. In practice these types are all cells, cell models and data sources, so this should be a no-op for real consumers — but it is a breaking change and probably warrants a minor version bump.

Verification

xcodebuild build passes for both the CellKit and DiffableCellKit schemes on generic/platform=iOS. SwiftLint reports the same 9 pre-existing violations as main — none added.

Building CellKit with SWIFT_STRICT_CONCURRENCY=complete succeeds; two warnings remain in SupplementaryElementKind, which reads UICollectionView.elementKindSectionHeader/Footer from a nonisolated RawRepresentable conformance. I left it alone because marking the enum @MainActor would break RawRepresentable, and the values are immutable strings. Happy to address it separately if you'd prefer.

I could not run the app-side end-to-end check (the consumer pins the released tag), so I have not empirically confirmed that all 45 @MainActor annotations become removable — though that is what the change is for.

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.

1 participant