Skip to content
Merged
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
8 changes: 0 additions & 8 deletions Examples/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,6 @@
MACOSX_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = (
"-Xfrontend",
"-enable-actor-data-race-checks",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
Expand Down Expand Up @@ -438,10 +434,6 @@
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = (
"-Xfrontend",
"-enable-actor-data-race-checks",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand Down
9 changes: 8 additions & 1 deletion Examples/App/CrossPlatform.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import CrossPlatformApp
import SwiftUI

@main
extension CrossPlatformApp {}
struct CrossPlatformApp: App {
var body: some Scene {
WindowGroup {
CrossPlatformRoot()
}
}
}
9 changes: 8 additions & 1 deletion Examples/App/iOS.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import SwiftUI
import iOSApp

@main
extension iOSApp {}
struct iOSApp: App {
var body: some Scene {
WindowGroup {
iOSRoot()
}
}
}
33 changes: 26 additions & 7 deletions Examples/Packages/CrossPlatform/Package.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
// swift-tools-version:5.8
// swift-tools-version:5.9

import PackageDescription

let atoms = Target.Dependency.product(name: "Atoms", package: "swiftui-atom-properties")
let swiftSettings: [SwiftSetting] = [
.unsafeFlags(["-Xfrontend", "-strict-concurrency=complete"]),
.unsafeFlags(["-Xfrontend", "-enable-actor-data-race-checks"]),
]

func target(name: String, dependencies: [Target.Dependency] = []) -> Target {
.target(
name: name,
dependencies: [.product(name: "Atoms", package: "swiftui-atom-properties")] + dependencies,
swiftSettings: swiftSettings
)
}

func testTarget(name: String, dependencies: [Target.Dependency]) -> Target {
.testTarget(
name: name,
dependencies: dependencies,
swiftSettings: swiftSettings
)
}

let package = Package(
name: "CrossPlatformExamples",
Expand All @@ -19,16 +38,16 @@ let package = Package(
.package(path: "../../..")
],
targets: [
.target(
target(
name: "CrossPlatformApp",
dependencies: [
"ExampleCounter",
"ExampleTodo",
]
),
.target(name: "ExampleCounter", dependencies: [atoms]),
.testTarget(name: "ExampleCounterTests", dependencies: ["ExampleCounter"]),
.target(name: "ExampleTodo", dependencies: [atoms]),
.testTarget(name: "ExampleTodoTests", dependencies: ["ExampleTodo"]),
target(name: "ExampleCounter"),
testTarget(name: "ExampleCounterTests", dependencies: ["ExampleCounter"]),
target(name: "ExampleTodo"),
testTarget(name: "ExampleTodoTests", dependencies: ["ExampleTodo"]),
]
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Atoms
import ExampleCounter
import ExampleTodo
import SwiftUI

// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
public struct CrossPlatformRoot: View {
public init() {}

public var body: some View {
AtomRoot {
NavigationStack {
List {
NavigationLink("🔢 Counter") {
ExampleCounter()
}

NavigationLink("📋 Todo") {
ExampleTodo()
}
}
.navigationTitle("Examples")

#if os(iOS)
.listStyle(.insetGrouped)
#endif
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ struct TodoCreator: View {
.textFieldStyle(.roundedBorder)
#endif

Button("Add", action: addTodo)
.disabled(text.isEmpty)
Button("Add") {
addTodo()
}
.disabled(text.isEmpty)
}
.padding(.vertical)
}
Expand Down
41 changes: 30 additions & 11 deletions Examples/Packages/iOS/Package.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
// swift-tools-version:5.8
// swift-tools-version:5.9

import PackageDescription

let atoms = Target.Dependency.product(name: "Atoms", package: "swiftui-atom-properties")
let swiftSettings: [SwiftSetting] = [
.unsafeFlags(["-Xfrontend", "-strict-concurrency=complete"]),
.unsafeFlags(["-Xfrontend", "-enable-actor-data-race-checks"]),
]

func target(name: String, dependencies: [Target.Dependency] = []) -> Target {
.target(
name: name,
dependencies: [.product(name: "Atoms", package: "swiftui-atom-properties")] + dependencies,
swiftSettings: swiftSettings
)
}

func testTarget(name: String, dependencies: [Target.Dependency]) -> Target {
.testTarget(
name: name,
dependencies: dependencies,
swiftSettings: swiftSettings
)
}

let package = Package(
name: "iOSExamples",
Expand All @@ -17,7 +36,7 @@ let package = Package(
.package(path: "../CrossPlatform"),
],
targets: [
.target(
target(
name: "iOSApp",
dependencies: [
.product(name: "CrossPlatformApp", package: "CrossPlatform"),
Expand All @@ -27,13 +46,13 @@ let package = Package(
"ExampleTimeTravel",
]
),
.target(name: "ExampleMovieDB", dependencies: [atoms]),
.testTarget(name: "ExampleMovieDBTests", dependencies: ["ExampleMovieDB"]),
.target(name: "ExampleMap", dependencies: [atoms]),
.testTarget(name: "ExampleMapTests", dependencies: ["ExampleMap"]),
.target(name: "ExampleVoiceMemo", dependencies: [atoms]),
.testTarget(name: "ExampleVoiceMemoTests", dependencies: ["ExampleVoiceMemo"]),
.target(name: "ExampleTimeTravel", dependencies: [atoms]),
.testTarget(name: "ExampleTimeTravelTests", dependencies: ["ExampleTimeTravel"]),
target(name: "ExampleMovieDB"),
testTarget(name: "ExampleMovieDBTests", dependencies: ["ExampleMovieDB"]),
target(name: "ExampleMap"),
testTarget(name: "ExampleMapTests", dependencies: ["ExampleMap"]),
target(name: "ExampleVoiceMemo"),
testTarget(name: "ExampleVoiceMemoTests", dependencies: ["ExampleVoiceMemo"]),
target(name: "ExampleTimeTravel"),
testTarget(name: "ExampleTimeTravelTests", dependencies: ["ExampleTimeTravel"]),
]
)
2 changes: 1 addition & 1 deletion Examples/Packages/iOS/Sources/ExampleMap/Atoms.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Atoms
import CoreLocation

final class LocationObserver: NSObject, ObservableObject, CLLocationManagerDelegate {
final class LocationObserver: NSObject, ObservableObject, CLLocationManagerDelegate, @unchecked Sendable {
let manager: LocationManagerProtocol

deinit {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protocol LocationManagerProtocol: AnyObject {

extension CLLocationManager: LocationManagerProtocol {}

final class MockLocationManager: LocationManagerProtocol {
final class MockLocationManager: LocationManagerProtocol, @unchecked Sendable {
weak var delegate: CLLocationManagerDelegate?
var desiredAccuracy = kCLLocationAccuracyKilometer
var location: CLLocation? = nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Combine
import UIKit

protocol APIClientProtocol {
protocol APIClientProtocol: Sendable {
func getImage(path: String, size: ImageSize) async throws -> UIImage
func getNowPlaying(page: Int) async throws -> PagedResponse<Movie>
func getPopular(page: Int) async throws -> PagedResponse<Movie>
Expand Down Expand Up @@ -94,7 +94,7 @@ private extension APIClient {
}
}

final class MockAPIClient: APIClientProtocol {
final class MockAPIClient: APIClientProtocol, @unchecked Sendable {
var imageResponse = Result<UIImage, Error>.failure(URLError(.unknown))
var filteredMovieResponse = Result<PagedResponse<Movie>, Error>.failure(URLError(.unknown))
var creditsResponse = Result<Credits, Error>.failure(URLError(.unknown))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@propertyWrapper
struct Failable<T: Decodable>: Decodable {
struct Failable<T: Decodable & Sendable>: Decodable & Sendable {
var wrappedValue: T?

init(wrappedValue: T?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
struct PagedResponse<T: Decodable>: Decodable {
struct PagedResponse<T: Decodable & Sendable>: Decodable, Sendable {
let page: Int
let totalPages: Int
let results: [T]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import Atoms
import Combine
import Foundation

struct ValueGenerator {
var date: () -> Date
var uuid: () -> UUID
var temporaryDirectory: () -> String
struct ValueGenerator: Sendable {
var date: @Sendable () -> Date
var uuid: @Sendable () -> UUID
var temporaryDirectory: @Sendable () -> String
}

struct ValueGeneratorAtom: ValueAtom, Hashable {
func value(context: Context) -> ValueGenerator {
ValueGenerator(
date: Date.init,
uuid: UUID.init,
temporaryDirectory: NSTemporaryDirectory
date: { Date.now },
uuid: { UUID() },
temporaryDirectory: { NSTemporaryDirectory() }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ final class AudioPlayer: NSObject, AVAudioPlayerDelegate, AudioPlayerProtocol {
}
}

final class MockAudioPlayer: AudioPlayerProtocol {
final class MockAudioPlayer: AudioPlayerProtocol, @unchecked Sendable {
private(set) var isPlaying = false
var playingError: Error?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ final class AudioRecorder: NSObject, AVAudioRecorderDelegate, AudioRecorderProto
}
}

final class MockAudioRecorder: AudioRecorderProtocol {
final class MockAudioRecorder: AudioRecorderProtocol, @unchecked Sendable {
var isRecording = false
var recordingError: Error?
var currentTime: TimeInterval = 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import AVFAudio
protocol AudioSessionProtocol {
var recordPermission: AVAudioSession.RecordPermission { get }

func requestRecordPermissionOnMain(_ response: @escaping (Bool) -> Void)
func requestRecordPermissionOnMain(_ response: @escaping @MainActor @Sendable (Bool) -> Void)
func setActive(_ active: Bool, options: AVAudioSession.SetActiveOptions) throws
func setCategory(_ category: AVAudioSession.Category, mode: AVAudioSession.Mode, options: AVAudioSession.CategoryOptions) throws
}

extension AVAudioSession: AudioSessionProtocol {
func requestRecordPermissionOnMain(_ response: @escaping (Bool) -> Void) {
func requestRecordPermissionOnMain(_ response: @escaping @MainActor @Sendable (Bool) -> Void) {
requestRecordPermission { isGranted in
Task { @MainActor in
response(isGranted)
Expand All @@ -18,16 +18,15 @@ extension AVAudioSession: AudioSessionProtocol {
}
}

final class MockAudioSession: AudioSessionProtocol {
var requestRecordPermissionResponse: ((Bool) -> Void)?
final class MockAudioSession: AudioSessionProtocol, @unchecked Sendable {
var requestRecordPermissionResponse: (@MainActor @Sendable (Bool) -> Void)?
var isActive = false
var currentCategory: AVAudioSession.Category?
var currentMode: AVAudioSession.Mode?
var currentOptions: AVAudioSession.CategoryOptions?

var recordPermission = AVAudioSession.RecordPermission.granted

func requestRecordPermissionOnMain(_ response: @escaping (Bool) -> Void) {
func requestRecordPermissionOnMain(_ response: @escaping @MainActor @Sendable (Bool) -> Void) {
requestRecordPermissionResponse = response
}

Expand Down
Loading