Supported platforms
- Apple
- Linux
- Windows
- WebAssembly
- Ubuntu
- Amazon Linux
- CentOS
- Red Hat UBI
- Fedora
- Debian
Static Linux SDK for Swift
--swift-sdk aarch64-swift-linux-musl
Identify which SDK to build against.
- Built the service for macOS on macOS
- Installed fully static Linux SDK for Swift
- Built the service for Linux on macOS
Swift everywhere
Swift Testing
// Swift Testing - Customize test's name / organize test function with tags / parameterize test with arguments
import Testing
@Test("Recognized rating",
.tags(.critical),
arguments: [
(1, "A Beach", "⭐️⭐️⭐️⭐️⭐️"),
(2, "Mystery Creek", "⭐️⭐️⭐️⭐️"),
])
func rating(videoId: Int, videoName: String, expectedRating: String) {
let video = Video(id: videoId, name: videoName)
#expect(video.rating == expectedRating)
}
Implicitly built modules
Explicitly built modules
- More parallelism in builds
- Better visibility into build steps
- Improved reliability of builds
- Faster debugger start-up
Language updates
- github.com/swiftlang
Noncopyable types
- Supported in all generic contexts
- Standard library support for
Optional
,Result
,Unsafe Pointers
// Before
struct File: ~Copyable {
private let fd: CInt
init(descriptor: CInt) {
self.fd = descriptor
}
func write(buffer: [UInt8]) {
// ...
}
deinit {
close(fd)
}
}
guard let fd = open(name) else {
return
}
let file = File(descriptor: fd)
file.write(buffer: data)
// After
struct File: ~Copyable {
private let fd: CInt
init?(name: String) {
guard let fd = open(name) else {
return nil
}
self.fd = fd
}
func write(buffer: [UInt8]) {
// ...
}
deinit {
close(fd)
}
}
Embedded Swift
- Small and standalone binaries
- Disables feature that need a runtime: reflection, “any” types
- Special compiler techniques: full generics specialization, static linking
- Embedded Swift subset close to “full” Swift
- Systems with limited memory
- ARM and RISC-V micro-controllers
C++ interoperability
- Virtual methods
- Default arguments
- C++ move-only types,
std::map
,std::set
,std::optional
,std::chrono::duration
// C++
struct Person {
Person(const Person&) = delete;
Person(Person &&) = default;
// ...
};
// Swift
struct Developer: ~Copyable {
let person: Person
init(person: consuming Person) {
self.person = person
}
}
let person = Person()
let developer = Developer(person: person)
person.printInfo()
Typed throws
Use typed throws when:
- Same module error handling
- Propagating error type in generic contexts
- Constrained environments
// Untyped throws
enum IntegerParseError: Error {
case nonDigitCharacter(String, index: String.Index)
}
func parse(string: String) throws -> Int {
for index in string.indices {
// ...
throw IntegerParseError.nonDigitCharacter(string, index: index)
}
}
do {
let value = try parse(string: "1+234")
}
catch let error as IntegerParseError {
// ...
}
catch {
// error is 'any Error'
}
func parse(string: String) throws -> Int {
//...
}
func parse(string: String) -> Int {
//...
}
// typed throws
enum IntegerParseError: Error {
case nonDigitCharacter(String, index: String.Index)
}
func parse(string: String) throws(IntegerParseError) -> Int {
for index in string.indices {
// ...
throw IntegerParseError.nonDigitCharacter(string, index: index)
}
}
do {
let value = try parse(string: "1+234")
}
catch {
// error is 'IntegerParseError'
}
func parse(string: String) throws(any Error) -> Int {
//...
}
func parse(string: String) throws(Never) -> Int {
//...
}
Data-race safety
// Pass NonSendable reference across actor isolation boundaries
class Client {
init(name: String, balance: Double) {}
}
actor ClientStore {
static let shared = ClientStore()
private var clients: [Client] = []
func addClient(_ client: Client) {
clients.append(client)
}
}
@MainActor
func openAccount(name: String, balance: Double) async {
let client = Client(name: name, balance: balance)
await ClientStore.shared.addClient(client) // the client here won't show warnings
}
// Atomic
import Dispatch
import Synchronization
let counter = Atomic<Int>(0)
DispatchQueue.concurrentPerform(iterations: 10) { _ in
for _ in 0 ..< 1_000_000 {
counter.wrappingAdd(1, ordering: .relaxed)
}
}
print(counter.load(ordering: .relaxed))
// Mutex
import Synchronization
final class LockingResourceManager: Sendable {
let cache = Mutex<[String: Resource]>([:])
func save(_ resource: Resource, as key: String) {
cache.withLock {
$0[key] = resource
}
}
}
Comments
Join the discussion for this article at here . Our comments is using Github Issues. All of posted comments will display at this page instantly.