Skip to content

Commit

Permalink
Merge pull request #150 from theleftbit/swift-6
Browse files Browse the repository at this point in the history
Swift 6
  • Loading branch information
piercifani authored Jul 23, 2024
2 parents 11c9e0d + 759f3ea commit 46771c0
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.8
// swift-tools-version:5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
8 changes: 4 additions & 4 deletions Sources/BSWFoundation/APIClient/APIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ open class APIClient: Identifiable {
extension APIClient {

/// Encapsualtes the Request to be sent to the server.
public struct Request<ResponseType>{
public struct Request<ResponseType: Sendable>: Sendable {

public typealias Validator = (APIClient.Response) throws -> ()
public typealias Validator = @Sendable (APIClient.Response) throws -> ()

/// The Endpoint where to send this request.
public let endpoint: Endpoint
Expand All @@ -128,7 +128,7 @@ extension APIClient {
}

/// Errors thrown from the `APIClient`.
public enum Error: Swift.Error {
public enum Error: Swift.Error, Sendable {
/// The URL resulting from generating the `URLRequest` is not valid.
case malformedURL
/// The response received from the Server is malformed.
Expand Down Expand Up @@ -308,7 +308,7 @@ extension URLSession: APIClientNetworkFetcher {
}

public typealias HTTPHeaders = [String: String]
public struct VoidResponse: Decodable, Hashable {}
public struct VoidResponse: Decodable, Hashable, Sendable {}

private extension Swift.Error {
var is401: Bool {
Expand Down
14 changes: 10 additions & 4 deletions Sources/BSWFoundation/AuthStorage/AuthStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
//

import Foundation
import KeychainAccess
@preconcurrency import KeychainAccess

/// A class that's useful to store sensitive information using the device's Keychain.
public class AuthStorage {
public final class AuthStorage: Sendable {

/// A standard `AuthStorage` with a `.simple` style.
public static let defaultStorage = AuthStorage()

@UserDefaultsBacked(key: Keys.HasAppBeenExecuted, defaultValue: false)
private var appBeenExecuted: Bool!
private var appBeenExecuted: Bool {
get {
UserDefaults.standard.bool(forKey: Keys.HasAppBeenExecuted)
}
set {
UserDefaults.standard.setValue(newValue, forKey: Keys.HasAppBeenExecuted)
}
}
private let keychain: Keychain

/// Where should `AppStorage` put it's values.
Expand Down
6 changes: 6 additions & 0 deletions Sources/BSWFoundation/Extensions/UIApplication+Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ public extension UIApplication {
/// If the application is executing Unit Tests.
@inlinable
var isRunningTests: Bool {
UIApplication.isRunningTests
}

/// If the application is executing Unit Tests.
@inlinable
static var isRunningTests: Bool {
#if DEBUG
return NSClassFromString("XCTest") != nil
#else
Expand Down
23 changes: 15 additions & 8 deletions Sources/BSWFoundation/Location/LocationFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import CoreLocation
let currentLocation = try await LocationFetcher.fetcher.fetchCurrentLocation()
```
*/
@MainActor
public final class LocationFetcher: NSObject, CLLocationManagerDelegate {

public enum LocationErrors: Swift.Error {
Expand Down Expand Up @@ -85,19 +86,23 @@ public final class LocationFetcher: NSObject, CLLocationManagerDelegate {

//MARK:- CLLocationManagerDelegate

public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
self.lastKnownLocation = location
completeCurrentRequest(.success(location))
public nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
MainActor.assumeIsolated {
if let location = locations.first {
self.lastKnownLocation = location
completeCurrentRequest(.success(location))
}
}
}

public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
public nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error finding location: \(error.localizedDescription)")
completeCurrentRequest()
MainActor.assumeIsolated {
completeCurrentRequest()
}
}

public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
public nonisolated func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

guard status != .notDetermined else { return }

Expand All @@ -111,7 +116,9 @@ public final class LocationFetcher: NSObject, CLLocationManagerDelegate {
if isStatusAuthorized {
manager.requestLocation()
} else {
completeCurrentRequest()
MainActor.assumeIsolated {
completeCurrentRequest()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Foundation
///
/// The value parameter can be only property list objects: `NSData`, `NSString`, `NSNumber`, `NSDate`, `NSArray`, or `NSDictionary`.
@propertyWrapper
public class UserDefaultsBacked<T> {
public final class UserDefaultsBacked<T: Sendable>: @unchecked Sendable {
private let key: String
private let defaultValue: T?
private let store: UserDefaults
Expand Down Expand Up @@ -51,7 +51,7 @@ public extension UserDefaultsBacked {

/// Stores the given `T` type on User Defaults (as long as it's `Codable`)
@propertyWrapper
public class CodableUserDefaultsBacked<T: Codable> {
public final class CodableUserDefaultsBacked<T: Codable>: @unchecked Sendable {
private let key: String
private let defaultValue: T?
private let store: UserDefaults
Expand Down
4 changes: 2 additions & 2 deletions Tests/BSWFoundationTests/APIClient/APIClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import XCTest
import BSWFoundation

class APIClientTests: XCTestCase {
class APIClientTests: XCTestCase, @unchecked Sendable {

var sut: APIClient!

Expand Down Expand Up @@ -199,7 +199,7 @@ private func generateRandomData() -> Data {
private class MockAPIClientDelegate: NSObject, APIClientDelegate {
func apiClientDidReceiveUnauthorized(forRequest atPath: String, apiClientID: APIClient.ID) async throws -> Bool {
failedPath = atPath
XCTAssert(Thread.isMainThread)
dispatchPrecondition(condition: .onQueue(.main))
return false
}
var failedPath: String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BSWFoundation

class ProgressObserverTests: XCTestCase {

@MainActor
func testProgressObserving() {

let progress = Progress(totalUnitCount: 2)
Expand Down
4 changes: 2 additions & 2 deletions Tests/BSWFoundationTests/Extensions/ThrottlerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import XCTest
import BSWFoundation

class ThrottlerTests: XCTestCase {
class ThrottlerTests: XCTestCase, @unchecked Sendable {
func testItWorks() {
let sut = Throttler(seconds: 0.5)
var numberOfTimesThisIsExecuted = 0
Expand All @@ -28,7 +28,7 @@ class ThrottlerTests: XCTestCase {
let sut = Throttler(seconds: maxInterval)
var numberOfTimesThisIsExecuted = 0
let exp = expectation(description: "must be filled once")
var areWeDoneHere = false
nonisolated(unsafe) var areWeDoneHere = false
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Int(maxInterval * 100) - 10)) {
exp.fulfill()
areWeDoneHere = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import XCTest
import BSWFoundation

class UIApplicationTests: XCTestCase {
@MainActor
func testItWorks() {
XCTAssert(UIApplication.shared.isRunningTests)
}
Expand Down

0 comments on commit 46771c0

Please sign in to comment.