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 publish, 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:
- Adjustments to Job Teams in Swift 6.1
- Adjustments 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 had 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
. When you’re not acquainted with process teams, go forward and skim up on them on my weblog publish proper right here.
Usually, a TaskGroup
is created as proven beneath the place we create a process group and specify the kind of worth that each little one process 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 a substitute, Swift can infer the return kind of kid duties primarily based on the primary process 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 anticipate, this does not change the truth that our process teams need to return the identical kind for each little one process.
The code above reveals you ways you should use this new return kind inference in Swift 6.1. When you unintentionally do find yourself with totally different return varieties in your little one process just like the code beneath reveals, the compiler will current us with an error that may inform you that the return kind of your name to addTask
is inaccurate.
await withTaskGroup { group in
for _ in 1...10 {
group.addTask {
return Int.random(in: 1...10)
}
}
group.addTask {
// Can not convert worth of kind 'String' to closure consequence kind 'Int'
return "Whats up, world"
}
}
Now, should you discover that you just do wish to have a number of return varieties, I’ve a weblog publish on that. That method nonetheless works. We will nonetheless use an enum as a return kind for our process group for our little one duties, and that undoubtedly nonetheless is a sound strategy to have a number of return varieties in a process group.
I’m fairly proud of this modification as a result of having to specify the return kind for my little one duties all the time felt somewhat 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, we’ve the flexibility so as to add extensions to varieties to boost or increase performance that we have already got. For instance, you would add an extension to an Int
to signify it as a foreign money string or one thing related.
If I am constructing an app the place I am coping with currencies and purchases and dealing with cash, I may 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 may need an extension on Int
that returns a String
which is a foreign money string as I discussed earlier.
This is what that might appear to be.
// CurrencyKit
func worth() -> 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 worth() -> 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 varieties of these extensions are the very same (i.e., strings). Which means that I can have the next two recordsdata in my app, and it will be simply superb.
// FileOne.swift
import PurchaseParser
func dealsWithPurchase() {
let quantity = 1000
let purchaseString = quantity.worth()
print(purchaseString)
}
// FileTwo.swift
import CurrencyKit
func dealsWithCurrency() {
let quantity = 1000
let currencyString = quantity.worth()
print(currencyString)
}
The compiler will know the way to determine which model of worth
needs to be used primarily based on the import
in my recordsdata and issues will work simply superb.
Nonetheless, if I’ve two extensions on integer with the identical operate identify however totally different return varieties, the compiler would possibly really get confused about which model of the extension I meant to make use of.
Think about the next modifications to PurchaseParser
‘s worth
methodology:
func worth() -> 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, worth
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 just noticed earlier:
let quantity = 1000
let currencyString = quantity.worth()
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.worth()
It will inform the compiler which model of worth
needs to be used, and my code will work once more. Nonetheless, it’s sort of unusual in a method 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 choose into a brand new member visibility mode. This member visibility mode goes to work somewhat bit extra such as you would possibly anticipate.
After I import a particular module like CurrencyKit
, I am solely going to be utilizing extensions that had been outlined on CurrencyKit
. Which means that in a file that solely imports CurrencyKit
I gained’t be capable of 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 strategy identify anymore since it could actually’t see what I don’t import.
Opting into this characteristic will be achieved by passing the corresponding characteristic flag to your package deal, this is what that appears like while you’re in a Swift package deal:
.executableTarget(
identify: "AppTarget",
dependencies: [
"CurrencyKit",
"PurchaseParser"
],
swiftSettings: [
.enableExperimentalFeature("MemberImportVisibility")
]
),
In Xcode this may be achieved by passing the characteristic to the “Different Swift Flags” setting in your mission settings. In this publish I clarify precisely how to try this.
Whereas I completely love this characteristic, and I feel it is a actually good change in Swift, it doesn’t resolve an issue that I’ve had regularly. Nonetheless, I can undoubtedly think about myself having that downside, so I am glad that there is now a repair for that that we will choose into. Hopefully, this can ultimately turn into a default in Swift.
In Abstract
General, Swift 6.1 is a reasonably light-weight launch, and it has some good enhancements that I feel 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’ll influence your work in any method in any respect?