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

Adopt "complete" Swift concurrency #123

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ jobs:
run: Scripts/build.swift spm ${{ matrix.platform }} `which xcpretty`
bazel:
name: Bazel
runs-on: macOS-12
runs-on: macOS-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Select Xcode Version
run: sudo xcode-select --switch /Applications/Xcode_15.4.app/Contents/Developer
- name: Build and Test
run: bazel test //...
run: bazel test //... --xcode_version=15.4.0
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ swift_library(
name = "Paralayout.lib",
srcs = glob(["Paralayout/**/*.swift"]),
module_name = "Paralayout",
copts = ["-strict-concurrency=complete"],
tags = ["manual"],
visibility = ["//visibility:public"],
deps = [],
Expand All @@ -22,6 +23,7 @@ swift_library(
testonly = True,
srcs = glob(["ParalayoutTests/**/*.swift"]),
module_name = "ParalayoutTests",
copts = ["-strict-concurrency=complete"],
tags = ["manual"],
deps = [":Paralayout.lib"],
)
Expand Down
14 changes: 14 additions & 0 deletions Example/ParalayoutSnapshotTests/ViewAlignmentSnapshotTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import SnapshotTesting

final class ViewAlignmentSnapshotTests: SnapshotTestCase {

@MainActor
func testSiblingAlignment() {
let containerView = UIView(frame: .init(x: 0, y: 0, width: 200, height: 200))
containerView.backgroundColor = .white
Expand All @@ -31,6 +32,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
secondSubview.backgroundColor = .red
containerView.addSubview(secondSubview)

@MainActor
func verifySnapshot(
receiverPosition: Position,
targetPosition: Position,
Expand Down Expand Up @@ -80,6 +82,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
verifySnapshot(receiverPosition: .center, targetPosition: .topRight, verticalOffset: -15)
}

@MainActor
func testLayoutDirection() {
let containerView = UIView(frame: .init(x: 0, y: 0, width: 100, height: 100))
containerView.backgroundColor = .white
Expand All @@ -88,6 +91,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
targetView.backgroundColor = .lightGray
containerView.addSubview(targetView)

@MainActor
func addAlignedSubview(
receiverPosition: Position,
receiverLayoutDirection: UIUserInterfaceLayoutDirection,
Expand Down Expand Up @@ -140,6 +144,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testTransformHasNoEffect() {
let containerView = UIView(frame: .init(x: 0, y: 0, width: 100, height: 100))
containerView.backgroundColor = .white
Expand All @@ -152,6 +157,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
secondSubview.backgroundColor = .red
containerView.addSubview(secondSubview)

@MainActor
func verifySnapshot(
receiverTransform: CGAffineTransform,
targetTransform: CGAffineTransform,
Expand Down Expand Up @@ -185,6 +191,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
verifySnapshot(receiverTransform: .identity, targetTransform: .init(scaleX: 2, y: 3))
}

@MainActor
func testNonZeroBoundsOrigin() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -213,6 +220,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testAlignmentWithLayoutMargins() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -246,6 +254,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: ["bothLayoutMargins"]))
}

@MainActor
func testAlignmentUsingCapInsets() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 250, height: 100))
containerView.backgroundColor = .white
Expand All @@ -269,6 +278,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testAlignmentUsingFirstLine() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 250, height: 100))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -299,6 +309,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testAlignmentUsingFirstLineCapInsets() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 250, height: 100))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -329,6 +340,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testAlignmentWithRect() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -365,6 +377,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testAlignmentWithFrame() {
let targetTransform = CGAffineTransform(translationX: -20, y: 10)
let receiverTransform = CGAffineTransform(scaleX: 0.8, y: 0.8)
Expand All @@ -390,6 +403,7 @@ final class ViewAlignmentSnapshotTests: SnapshotTestCase {
receiverView.transform = receiverTransform
containerView.addSubview(receiverView)

@MainActor
func updateMirrorViews() {
targetView.transform = .identity
targetFrameView.frame = targetView.frame.applying(targetView.transform.inverted())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import SnapshotTesting

final class ViewDistributionSnapshotTests: SnapshotTestCase {

@MainActor
func testDistribution() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
containerView.backgroundColor = .white
Expand All @@ -45,6 +46,7 @@ final class ViewDistributionSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: ["vertical"]))
}

@MainActor
func testDistributionIgnoresTransform() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -72,6 +74,7 @@ final class ViewDistributionSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testDistributionUsingCapInsets() {
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))
containerView.backgroundColor = .white
Expand Down Expand Up @@ -104,6 +107,7 @@ final class ViewDistributionSnapshotTests: SnapshotTestCase {
assertSnapshot(matching: containerView, as: .image, named: nameForSnapshot(with: []))
}

@MainActor
func testHorizontalDistributionFollowsLayoutDirection() {
let view = HorizontalDistributionView(frame: CGRect(x: 0, y: 0, width: 160, height: 60))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import SnapshotTesting

final class ViewSpeadingSnapshotTests: SnapshotTestCase {

@MainActor
func testHorizontallySpreadSubviews() {
let container = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
container.backgroundColor = .white
Expand All @@ -35,6 +36,7 @@ final class ViewSpeadingSnapshotTests: SnapshotTestCase {
greenView.backgroundColor = .green
container.addSubview(greenView)

@MainActor
func verifySnapshot(
margin: CGFloat = 0,
inRect rect: CGRect? = nil,
Expand Down Expand Up @@ -92,6 +94,7 @@ final class ViewSpeadingSnapshotTests: SnapshotTestCase {
verifySnapshot(margin: 40, inRect: CGRect(x: 20, y: 10, width: 300, height: 50))
}

@MainActor
func testVerticallySpreadSubviews() {
let container = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
container.backgroundColor = .white
Expand All @@ -108,6 +111,7 @@ final class ViewSpeadingSnapshotTests: SnapshotTestCase {
greenView.backgroundColor = .green
container.addSubview(greenView)

@MainActor
func verifySnapshot(
margin: CGFloat = 0,
inRect rect: CGRect? = nil,
Expand Down
4 changes: 4 additions & 0 deletions Paralayout/Alignable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import UIKit
/// Describes an object that can participate in alignment. In practice, this represents a view.
public protocol Alignable {

@MainActor
var alignmentContext: AlignmentContext { get }

}

@MainActor
public struct AlignmentContext {

// MARK: - Life Cycle
Expand All @@ -47,6 +49,7 @@ public struct AlignmentContext {

extension UIView: Alignable {

@MainActor
public var alignmentContext: AlignmentContext {
return AlignmentContext(view: self, alignmentBounds: bounds)
}
Expand Down Expand Up @@ -168,6 +171,7 @@ public struct FrameAlignmentProxy: Alignable {

// MARK: - Private Methods

@MainActor
private func withViewInSuperview<T>(view: UIView, perform: (_ superview: UIView) -> T) -> T {
if let superview = view.superview {
return perform(superview)
Expand Down
2 changes: 1 addition & 1 deletion Paralayout/Angle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import CoreGraphics

public struct Angle: Comparable {
public struct Angle: Comparable, Sendable {

// MARK: - Public Static Properties

Expand Down
23 changes: 12 additions & 11 deletions Paralayout/AspectRatio.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import UIKit

/// A value type representing the ratio between a width and a height.
public struct AspectRatio: Comparable, CustomDebugStringConvertible {
public struct AspectRatio: Comparable, CustomDebugStringConvertible, Sendable {

// MARK: - Public Static Properties

Expand Down Expand Up @@ -105,15 +105,15 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
///
/// - parameter width: The desired width.
/// - parameter scaleFactor: The view/window/screen to use for pixel rounding.
public func height(forWidth width: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGFloat {
@MainActor public func height(forWidth width: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGFloat {
return (ratioHeight * width / ratioWidth).roundedToPixel(in: scaleFactor)
}

/// Returns the width of the aspect ratio for a given `height` rounded to the nearest pixel.
///
/// - parameter height: The desired height.
/// - parameter scaleFactor: The view/window/screen to use for pixel rounding.
public func width(forHeight height: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGFloat {
@MainActor public func width(forHeight height: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGFloat {
return (ratioWidth * height / ratioHeight).roundedToPixel(in: scaleFactor)
}

Expand All @@ -122,7 +122,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
///
/// - parameter width: The desired width.
/// - parameter scaleFactor: The view/window/screen to use for pixel rounding.
public func size(forWidth width: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGSize {
@MainActor public func size(forWidth width: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGSize {
return CGSize(
width: width,
height: height(forWidth: width, in: scaleFactor)
Expand All @@ -134,7 +134,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
///
/// - parameter height: The desired height.
/// - parameter scaleFactor: The view/window/screen to use for pixel rounding.
public func size(forHeight height: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGSize {
@MainActor public func size(forHeight height: CGFloat, in scaleFactor: ScaleFactorProviding) -> CGSize {
return CGSize(
width: width(forHeight: height, in: scaleFactor),
height: height
Expand All @@ -147,7 +147,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter size: The bounding size.
/// - parameter scaleFactor: The view/window/screen to use for pixel alignment.
/// - returns: A size with the receiver's aspect ratio, no larger than the bounding size.
public func size(toFit size: CGSize, in scaleFactor: ScaleFactorProviding) -> CGSize {
@MainActor public func size(toFit size: CGSize, in scaleFactor: ScaleFactorProviding) -> CGSize {
if size.aspectRatio <= self {
// Match width, narrow the height.
let fitHeight = min(size.height, height(forWidth: size.width, in: scaleFactor))
Expand All @@ -169,7 +169,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter scaleFactor: The view/window/screen to use for pixel alignment.
/// - parameter layoutDirection: The effective layout direction of the view in which the `rect` is defined.
/// - returns: A rect with the receiver's aspect ratio, strictly within the bounding rect.
public func rect(
@MainActor public func rect(
toFit rect: CGRect,
at position: Position,
in scaleFactor: ScaleFactorProviding,
Expand All @@ -193,7 +193,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter context: The view/window/screen that provides the scale factor and effective layout direction in
/// which the rect should be positioned.
/// - returns: A rect with the receiver's aspect ratio, strictly within the bounding rect.
public func rect(
@MainActor public func rect(
toFit rect: CGRect,
at position: Position,
in context: (ScaleFactorProviding & LayoutDirectionProviding)
Expand All @@ -212,7 +212,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter size: The bounding size.
/// - parameter scaleFactor: The view/window/screen to use for pixel alignment.
/// - returns: A size with the receiver's aspect ratio, at least as large as the bounding size.
public func size(toFill size: CGSize, in scaleFactor: ScaleFactorProviding) -> CGSize {
@MainActor public func size(toFill size: CGSize, in scaleFactor: ScaleFactorProviding) -> CGSize {
if size.aspectRatio <= self {
// Match height, expand the width.
let fillWidth = width(forHeight: size.height, in: scaleFactor)
Expand All @@ -234,7 +234,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter scaleFactor: The view/window/screen to use for pixel alignment.
/// - parameter layoutDirection: The effective layout direction of the view in which the `rect` is defined.
/// - returns: A rect with the receiver's aspect ratio, strictly containing the bounding rect.
public func rect(
@MainActor public func rect(
toFill rect: CGRect,
at position: Position,
in scaleFactor: ScaleFactorProviding,
Expand All @@ -257,7 +257,7 @@ public struct AspectRatio: Comparable, CustomDebugStringConvertible {
/// - parameter context: The view/window/screen that provides the scale factor and effective layout direction in
/// which the rect should be positioned.
/// - returns: A rect with the receiver's aspect ratio, strictly containing the bounding rect.
public func rect(
@MainActor public func rect(
toFill rect: CGRect,
at position: Position,
in context: (ScaleFactorProviding & LayoutDirectionProviding)
Expand Down Expand Up @@ -294,6 +294,7 @@ extension CGRect {

// MARK: - Life Cycle

@MainActor
fileprivate init(
size newSize: CGSize,
at position: Position,
Expand Down
2 changes: 1 addition & 1 deletion Paralayout/Interpolation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public enum Clamp {

// MARK: -

public struct Interpolation: Comparable {
public struct Interpolation: Comparable, Sendable {

// MARK: - Public Types

Expand Down
1 change: 1 addition & 0 deletions Paralayout/LayoutDirection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import UIKit
/// Defines an object that vends its current user interface layout direction.
public protocol LayoutDirectionProviding {

@MainActor
var effectiveUserInterfaceLayoutDirection: UIUserInterfaceLayoutDirection { get }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@skorulis-ap this needs to be MainActor for UIView to have a valid conformance on L27, but that means all the calculations that use LayoutDirectionProviding also need to be marked MainActor


}
Expand Down
Loading