The Xcode 16.3 beta is out, which features a new model of Swift. Swift 6.1 is a comparatively small launch that comes with bug fixes, high quality of life enhancements, and a few options. On this submit, I’d wish to discover two of the brand new options that include Swift 6.1. One you could begin utilizing instantly, and one you could opt-in on if it is smart for you.
The options I’d wish to discover are the next:
- Modifications to Activity Teams in Swift 6.1
- Modifications to member visibility for imported code
We’ll begin by trying on the modifications in Concurrency’s TaskGroup
and we’ll cowl member visibility after.
Swift 6.1 and TaskGroup
There have been a few modifications to concurrency in Swift 6.1. These have been primarily small bug fixes and enhancements however one enchancment stood out to me and that’s the modifications which might be made to TaskGroup
. In the event you’re not conversant in activity teams, go forward and skim up on them on my weblog submit proper right here.
Usually, a TaskGroup
is created as proven beneath the place we create a activity group and specify the kind of worth that each little one activity goes to supply:
await withTaskGroup(of: Int.self) { group in
for _ in 1...10 {
group.addTask {
return Int.random(in: 1...10)
}
}
}
Beginning in Swift 6.1, Apple has made it in order that we now not need to explicitly outline the return kind for our little one duties. As an alternative, Swift can infer the return kind of kid duties primarily based on the primary activity that we add to the group.
That implies that the compiler will useaddGroup
it finds to find out the return kind for all of your little one duties.
In follow, that implies that the code beneath is the equal of what we noticed earlier:
await withTaskGroup { group in
for _ in 1...10 {
group.addTask {
return Int.random(in: 1...10)
}
}
}
Now, as you would possibly count on, this does not change the truth that our activity teams need to return the identical kind for each little one activity.
The code above exhibits you ways you need to use this new return kind inference in Swift 6.1. In the event you unintentionally do find yourself with totally different return sorts on your little one activity just like the code beneath exhibits, the compiler will current us with an error that may let you know that the return kind of your name to addTask
is wrong.
await withTaskGroup { group in
for _ in 1...10 {
group.addTask {
return Int.random(in: 1...10)
}
}
group.addTask {
// Can't convert worth of kind 'String' to closure outcome kind 'Int'
return "Hi there, world"
}
}
Now, when you discover that you simply do need to have a number of return sorts, I’ve a weblog submit on that. That strategy nonetheless works. We will nonetheless use an enum as a return kind for our activity group for our little one duties, and that undoubtedly nonetheless is a legitimate technique to have a number of return sorts in a activity group.
I’m fairly pleased with this transformation as a result of having to specify the return kind for my little one duties all the time felt slightly tedious so it’s nice to see the compiler take this job in Swift 6.1.
Subsequent, let’s check out the modifications to imported member visibility in Swift 6.1.
Imported member visibility in Swift 6.1
In Swift, now we have the power so as to add extensions to sorts to reinforce or increase performance that we have already got. For instance, you might add an extension to an Int
to signify it as a foreign money string or one thing comparable.
If I am constructing an app the place I am coping with currencies and purchases and dealing with cash, I might need two packages which might be imported by my app. Each packages could possibly be coping with currencies not directly form or type and I might need an extension on Int
that returns a String
which is a foreign money string as I discussed earlier.
Here is what that would seem like.
// CurrencyKit
func value() -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .foreign money
formatter.locale = Locale.present
let quantity = Double(self) / 100.0 // Assuming the integer represents cents
return formatter.string(from: NSNumber(worth: quantity)) ?? "$(quantity)"
}
// PurchaseParser
func value() -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .foreign money
formatter.locale = Locale.present
let quantity = Double(self) / 100.0 // Assuming the integer represents cents
return formatter.string(from: NSNumber(worth: quantity)) ?? "$(quantity)"
}
The extension proven above exists in each of my packages, and the return kinds of these extensions are the very same (i.e., strings). Which means I can have the next two recordsdata in my app, and it’ll be simply fantastic.
// FileOne.swift
import PurchaseParser
func dealsWithPurchase() {
let quantity = 1000
let purchaseString = quantity.value()
print(purchaseString)
}
// FileTwo.swift
import CurrencyKit
func dealsWithCurrency() {
let quantity = 1000
let currencyString = quantity.value()
print(currencyString)
}
The compiler will know the way to determine which model of value
must be used primarily based on the import
in my recordsdata and issues will work simply fantastic.
Nonetheless, if I’ve two extensions on integer with the identical perform title however totally different return sorts, the compiler would possibly truly get confused about which model of the extension I supposed to make use of.
Think about the next modifications to PurchaseParser
‘s value
methodology:
func value() -> Double {
let formatter = NumberFormatter()
formatter.numberStyle = .foreign money
formatter.locale = Locale.present
let quantity = Double(self) / 100.0 // Assuming the integer represents cents
return quantity
}
Now, value
returns a Double
as a substitute of a String
. In my app code, I’m able to use this extension from any file, even when that file doesn’t explicitly import PurchaseParser
. Consequently, the compiler isn’t positive what I imply after I write the next code in both of the 2 recordsdata that you simply noticed earlier:
let quantity = 1000
let currencyString = quantity.value()
Am I anticipating currencyString
to be a String
or am I anticipating it to be a Double
?
To assist the compiler, I can explicitly kind currencyString
as follows:
let quantity = 1000
let currencyString: String = quantity.value()
It will inform the compiler which model of value
must be used, and my code will work once more. Nonetheless, it’s type of unusual in a approach that the compiler is utilizing an extension on Int
that’s outlined in a module that I didn’t even import on this particular file.
In Swift 6.1, we will decide into a brand new member visibility mode. This member visibility mode goes to work slightly bit extra such as you would possibly count on.
Once I import a selected module like CurrencyKit
, I am solely going to be utilizing extensions that have been outlined on CurrencyKit
. Which means in a file that solely imports CurrencyKit
I gained’t have the ability to use extensions outlined in different packages except I additionally import these. Consequently, the compiler gained’t be confused about having a number of extensions with the tactic title anymore since it will probably’t see what I don’t import.
Opting into this function may be executed by passing the corresponding function flag to your package deal, this is what that appears like whenever you’re in a Swift package deal:
.executableTarget(
title: "AppTarget",
dependencies: [
"CurrencyKit",
"PurchaseParser"
],
swiftSettings: [
.enableExperimentalFeature("MemberImportVisibility")
]
),
In Xcode this may be executed by passing the function to the “Different Swift Flags” setting in your mission settings. In this submit I clarify precisely how to do this.
Whereas I completely love this function, and I believe it is a actually good change in Swift, it doesn’t resolve an issue that I’ve had incessantly. Nonetheless, I can undoubtedly think about myself having that drawback, so I am glad that there is now a repair for that that we will decide into. Hopefully, it will ultimately change into a default in Swift.
In Abstract
Total, Swift 6.1 is a fairly light-weight launch, and it has some good enhancements that I believe actually assist the language be higher than it was earlier than.
What are your ideas on these modifications in Swift 6.1, and do you suppose that they may influence your work in any approach in any respect?