Skip to content

Commit 04c3d19

Browse files
committed
Add support for Swift 6
1 parent ed0c598 commit 04c3d19

File tree

10 files changed

+137
-20
lines changed

10 files changed

+137
-20
lines changed

Package.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 5.9
1+
// swift-tools-version: 6.2
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription
@@ -35,5 +35,6 @@ let package = Package(
3535
)
3636
]
3737
),
38-
]
38+
],
39+
swiftLanguageModes: [.v6]
3940
)

Package@swift-5.9.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// swift-tools-version: 5.9
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "FoundationPlus",
8+
platforms: [
9+
.iOS(.v13),
10+
.tvOS(.v13),
11+
.watchOS(.v6),
12+
.macOS(.v10_15),
13+
],
14+
products: [
15+
.library(
16+
name: "FoundationPlus",
17+
targets: ["FoundationPlus"]
18+
),
19+
],
20+
dependencies: [
21+
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"),
22+
],
23+
targets: [
24+
.target(
25+
name: "FoundationPlus",
26+
resources: [.process("PrivacyInfo.xcprivacy")]
27+
),
28+
.testTarget(
29+
name: "FoundationPlusTests",
30+
dependencies: ["FoundationPlus"],
31+
linkerSettings: [
32+
.linkedFramework(
33+
"XCTest",
34+
.when(platforms: [.macOS, .iOS, .tvOS, .watchOS])
35+
)
36+
]
37+
),
38+
]
39+
)

Sources/Extensions/Sequence/Sequence+Parallel.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

3-
public extension Sequence {
4-
3+
public extension Sequence where Element: Sendable {
4+
55
/// Performs a map operation on the sequence's elements concurrently.
66
///
77
/// The transformed elements are collected
@@ -15,14 +15,14 @@ public extension Sequence {
1515
/// - Returns: An array of transformed values `T`.
1616
/// - Throws: Rethrows any errors encountered during the filtering process. Due to implementation details,
1717
/// `parallelMap` can't use the `rethrows` keyword. In practice, it only throws if the `transform` function throws.
18-
func parallelMap<T>(
18+
func parallelMap<T: Sendable>(
1919
preservingOrder: Bool = true,
20-
_ transform: @escaping (Element) async throws -> T
20+
_ transform: @Sendable @escaping (Element) async throws -> T
2121
) async rethrows -> [T] {
2222
try await withThrowingTaskGroup(of: (Int, T).self, returning: [T].self) { group in
2323
var results: [(Int, T)] = []
2424
results.reserveCapacity(self.underestimatedCount)
25-
25+
2626
var index = 0
2727
for element in self {
2828
let indexCopy = index
@@ -31,11 +31,11 @@ public extension Sequence {
3131
}
3232
index += 1
3333
}
34-
34+
3535
for try await (index, element) in group {
3636
results.append((index, element))
3737
}
38-
38+
3939
return if preservingOrder {
4040
results
4141
.sorted(by: \.0, ascending: true)
@@ -45,7 +45,7 @@ public extension Sequence {
4545
}
4646
}
4747
}
48-
48+
4949
/// Performs a filter operation on the sequence's elements concurrently.
5050
///
5151
/// Elements that satisfy the closure (return `true`)
@@ -61,11 +61,11 @@ public extension Sequence {
6161
/// `parallelFilter` can't use the `rethrows` keyword. In practice, it only throws if the `isIncluded` function throws.
6262
func parallelFilter(
6363
preservingOrder: Bool = true,
64-
_ isIncluded: @escaping (Element) async throws -> Bool
64+
_ isIncluded: @Sendable @escaping (Element) async throws -> Bool
6565
) async throws -> [Element] {
6666
try await withThrowingTaskGroup(of: Optional<(Int, Element)>.self, returning: [Element].self) { group in
6767
var results = [(Int, Element)]()
68-
68+
6969
var index = 0
7070
for element in self {
7171
let indexCopy = index
@@ -74,13 +74,13 @@ public extension Sequence {
7474
}
7575
index += 1
7676
}
77-
77+
7878
for try await result in group {
7979
if let (index, element) = result {
8080
results.append((index, element))
8181
}
8282
}
83-
83+
8484
return if preservingOrder {
8585
results
8686
.sorted(by: \.0, ascending: true)

Sources/Extensions/Timer/Timer+ScheduledTimer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public extension Timer {
2525
static func scheduledTimer(
2626
withTimeInterval timeInterval: TimeInterval,
2727
repeats: Bool = false,
28-
block: @escaping () -> Void
28+
block: @Sendable @escaping () -> Void
2929
) -> Timer {
3030
self.scheduledTimer(withTimeInterval: timeInterval, repeats: repeats, block: { _ in
3131
block()

Sources/PropertyWrappers/BackgroundPublished.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Combine
1717
/// ```
1818
///
1919
/// In this example, changes to `myProperty` will automatically trigger updates on the main thread, even if called from a background thread.
20-
@propertyWrapper
20+
@propertyWrapper @MainActor
2121
public struct BackgroundPublished<Value> {
2222

2323
private var value: Value

Sources/PropertyWrappers/EquatablePublished.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ typealias CombinePublisher = Combine.Publisher
1818
/// ```
1919
///
2020
/// In this example, `myProperty` will only trigger updates to any subscribers when the value actually changes.
21-
@propertyWrapper
21+
@propertyWrapper @MainActor
2222
public struct EquatablePublished<Value: Equatable> {
2323
private var publisher: Publisher?
2424
private var storage: Storage

Sources/PropertyWrappers/SettingStorage/PublishedCodableSettingStorage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Combine
1818
/// ```
1919
///
2020
/// In this example, `mySetting` is stored in `UserDefaults` and changes to it will be published.
21-
@propertyWrapper
21+
@propertyWrapper @MainActor
2222
public struct PublishedCodableSettingStorage<Value> where Value: Codable {
2323
private let key: String
2424
private var dataHash: Int

Sources/PropertyWrappers/SettingStorage/PublishedSettingStorage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Combine
1818
/// ```
1919
///
2020
/// In this example, `mySetting` is stored in `UserDefaults` and changes to it will be published.
21-
@propertyWrapper
21+
@propertyWrapper @MainActor
2222
public struct PublishedSettingStorage<Value> {
2323
private let explicitKey: String?
2424
private var initialValue: Value
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Foundation
2+
3+
extension Array {
4+
5+
/**
6+
Removes the specified number of elements from the beginning of the collection, if they exist.
7+
8+
- Note : If less elements than specified exist, they will be removed anyway.
9+
*/
10+
mutating func removeFirstIfExist(_ n : Int) {
11+
self.removeFirst(Swift.min(n, self.count))
12+
}
13+
14+
func removingFirstIfExists() -> ArraySlice<Element> {
15+
if self.count == 0 {
16+
return self[...]
17+
}
18+
return self[1..<self.count]
19+
}
20+
21+
/**
22+
Removes the specified number of elements from the end of the collection, if they exist.
23+
24+
- Note : If less elements than specified exist, they will be removed anyway.
25+
*/
26+
mutating func removeLastIfExist(_ n : Int) {
27+
self.removeLast(Swift.min(n, self.count))
28+
}
29+
30+
func split(isInFirstArray: (Element) -> Bool) -> ([Element], [Element]) {
31+
var first = [Element]()
32+
var second = [Element]()
33+
34+
for element in self {
35+
if isInFirstArray(element) {
36+
first.append(element)
37+
} else {
38+
second.append(element)
39+
}
40+
}
41+
42+
return (first, second)
43+
}
44+
}
45+
46+
public extension NSMutableAttributedString {
47+
48+
/**
49+
Adds an attribute with the given name and value to the entire receiver.
50+
*/
51+
func addAttribute(_ name: NSAttributedString.Key, value : Any){
52+
addAttribute(name, value: value, range: NSRange(location: 0, length: self.length))
53+
}
54+
55+
/**
56+
Removes the named attribute from the characters in the entire receiver.
57+
*/
58+
func removeAttribute(_ name: NSAttributedString.Key){
59+
removeAttribute(name, range: NSRange(location: 0, length: self.length))
60+
}
61+
62+
/**
63+
Adds the characters of a given string to the end of the receiver.
64+
*/
65+
func append(_ string: String){
66+
append(NSAttributedString(string: string))
67+
}
68+
69+
/**
70+
Adds the given character to the end of the receiver.
71+
*/
72+
func append(_ character: Character){
73+
append(NSAttributedString(string: String(character)))
74+
}
75+
}

Tests/PropertyWrappers/EquatablePublishedTests.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Combine
33

44
@testable import FoundationPlus
55

6+
@MainActor
67
final class EquatablePublishedTests: XCTestCase {
78
private var cancellables: Set<AnyCancellable> = []
89

@@ -46,7 +47,8 @@ final class EquatablePublishedTests: XCTestCase {
4647
extension EquatablePublishedTests {
4748

4849
// Helper class to use in tests
49-
private class TestClass: ObservableObject {
50+
@MainActor
51+
private class TestClass: @MainActor ObservableObject {
5052
let objectWillChange = ObservableObjectPublisher()
5153

5254
@EquatablePublished var myProperty: Int = 1

0 commit comments

Comments
 (0)