Skip to content

Commit

Permalink
Refactor to fix StrictConcurrency warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
paololeonardi committed Jul 25, 2024
1 parent f760844 commit 54eb385
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 116 deletions.
1 change: 1 addition & 0 deletions Sources/WaterfallGrid/Environment/GridSyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct GridSyle {
let spacing: CGFloat
let animation: Animation?

@MainActor
var columns: Int {
#if os(OSX) || os(tvOS) || targetEnvironment(macCatalyst) || os(visionOS)
return columnsInLandscape
Expand Down
15 changes: 15 additions & 0 deletions Sources/WaterfallGrid/Preference/AnyHashableAndSendable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Copyright © 2024 Paolo Leonardi.
//
// Licensed under the MIT license. See the LICENSE file for more info.
//

import Foundation

struct AnyHashableAndSendable: @unchecked Sendable, Hashable {
private let wrapped: AnyHashable

init(_ wrapped: some Hashable & Sendable) {
self.wrapped = .init(wrapped)
}
}
6 changes: 3 additions & 3 deletions Sources/WaterfallGrid/Preference/ElementPreference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

import SwiftUI

struct ElementPreferenceData: Equatable {
let id: AnyHashable
struct ElementPreferenceData: Equatable, Sendable {
let id: AnyHashableAndSendable
let size: CGSize
}

struct ElementPreferenceKey: PreferenceKey {
typealias Value = [ElementPreferenceData]

static var defaultValue: [ElementPreferenceData] = []
static let defaultValue: [ElementPreferenceData] = []

static func reduce(value: inout [ElementPreferenceData], nextValue: () -> [ElementPreferenceData]) {
value.append(contentsOf: nextValue())
Expand Down
6 changes: 3 additions & 3 deletions Sources/WaterfallGrid/Preference/PreferenceSetter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

import SwiftUI

struct PreferenceSetter<ID: Hashable>: View {
var id: ID
struct PreferenceSetter: View {
var id: AnyHashableAndSendable
var body: some View {
GeometryReader { geometry in
Color.clear
.preference(key: ElementPreferenceKey.self, value: [ElementPreferenceData(id: AnyHashable(self.id), size: geometry.size)])
.preference(key: ElementPreferenceKey.self, value: [ElementPreferenceData(id: self.id, size: geometry.size)])
}
}
}
28 changes: 14 additions & 14 deletions Sources/WaterfallGrid/WaterfallGrid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SwiftUI

/// A container that presents items of variable heights arranged in a grid.
@available(iOS 13, OSX 10.15, tvOS 13, visionOS 1, watchOS 6, *)
public struct WaterfallGrid<Data, ID, Content>: View where Data : RandomAccessCollection, Content : View, ID : Hashable {
public struct WaterfallGrid<Data, ID, Content>: View where Data : RandomAccessCollection, Content : View, ID : Hashable & Sendable {

@Environment(\.gridStyle) private var style
@Environment(\.scrollOptions) private var scrollOptions
Expand All @@ -20,7 +20,7 @@ public struct WaterfallGrid<Data, ID, Content>: View where Data : RandomAccessCo
@State private var loaded = false
@State private var gridHeight: CGFloat = 0

@State private var alignmentGuides = [AnyHashable: CGPoint]() {
@State private var alignmentGuides = [AnyHashableAndSendable: CGPoint]() {
didSet { loaded = !oldValue.isEmpty }
}

Expand All @@ -29,12 +29,12 @@ public struct WaterfallGrid<Data, ID, Content>: View where Data : RandomAccessCo
GeometryReader { geometry in
self.grid(in: geometry)
.onPreferenceChange(ElementPreferenceKey.self, perform: { preferences in
DispatchQueue.global(qos: .userInteractive).async {
let (alignmentGuides, gridHeight) = self.alignmentsAndGridHeight(columns: self.style.columns,
spacing: self.style.spacing,
scrollDirection: self.scrollOptions.direction,
preferences: preferences)
DispatchQueue.main.async {
Task.detached(priority: .userInitiated) {
let (alignmentGuides, gridHeight) = await self.alignmentsAndGridHeight(columns: self.style.columns,
spacing: self.style.spacing,
scrollDirection: self.scrollOptions.direction,
preferences: preferences)
await MainActor.run {
self.alignmentGuides = alignmentGuides
self.gridHeight = gridHeight
}
Expand All @@ -55,20 +55,20 @@ public struct WaterfallGrid<Data, ID, Content>: View where Data : RandomAccessCo
self.content(element)
.frame(width: self.scrollOptions.direction == .vertical ? columnWidth : nil,
height: self.scrollOptions.direction == .horizontal ? columnWidth : nil)
.background(PreferenceSetter(id: element[keyPath: self.dataId]))
.alignmentGuide(.top, computeValue: { _ in self.alignmentGuides[element[keyPath: self.dataId]]?.y ?? 0 })
.alignmentGuide(.leading, computeValue: { _ in self.alignmentGuides[element[keyPath: self.dataId]]?.x ?? 0 })
.opacity(self.alignmentGuides[element[keyPath: self.dataId]] != nil ? 1 : 0)
.background(PreferenceSetter(id: AnyHashableAndSendable(element[keyPath: self.dataId])))
.alignmentGuide(.top, computeValue: { _ in self.alignmentGuides[AnyHashableAndSendable(element[keyPath: self.dataId])]?.y ?? 0 })
.alignmentGuide(.leading, computeValue: { _ in self.alignmentGuides[AnyHashableAndSendable(element[keyPath: self.dataId])]?.x ?? 0 })
.opacity(self.alignmentGuides[AnyHashableAndSendable(element[keyPath: self.dataId])] != nil ? 1 : 0)
}
}
.animation(self.loaded ? self.style.animation : nil, value: UUID())
}

// MARK: - Helpers

func alignmentsAndGridHeight(columns: Int, spacing: CGFloat, scrollDirection: Axis.Set, preferences: [ElementPreferenceData]) -> ([AnyHashable: CGPoint], CGFloat) {
func alignmentsAndGridHeight(columns: Int, spacing: CGFloat, scrollDirection: Axis.Set, preferences: [ElementPreferenceData]) -> ([AnyHashableAndSendable: CGPoint], CGFloat) {
var heights = Array(repeating: CGFloat(0), count: columns)
var alignmentGuides = [AnyHashable: CGPoint]()
var alignmentGuides = [AnyHashableAndSendable: CGPoint]()

preferences.forEach { preference in
if let minValue = heights.min(), let indexMin = heights.firstIndex(of: minValue) {
Expand Down
Loading

0 comments on commit 54eb385

Please sign in to comment.