# Swift 5.8の新機能
## 参考ページ
Swift 5.8 Released!
https://www.swift.org/blog/swift-5.8-released/
## 1. SE-0362: Piecemeal adoption of upcoming language improvements
swift 6で有効になる機能などを先行的に試せるようになった。
使い方は `-enable-upcoming-feature XXX` をOther Swift Flagに入れる(Xcode Projの場合)
例として以下の4つが挙げられていた
- SE-0274: Concise magic file names (ConciseMagicFile)
- SE-0286: Forward-scan matching for trailing closures (ForwardTrailingClosures)
- SE-0335: Introduce existential any (ExistentialAny)
- SE-0354: Regex literals (BareSlashRegexLiterals)
### SE-0274: Concise magic file names
https://github.com/apple/swift-evolution/blob/main/proposals/0274-magic-file.md
#fileの出力が変わるやつ。
||swift 5.8 通常|-enable-upcoming-feature ConciseMagicFile|
|---|---|---|
|#file|/Users/UserName/XcodeProjeRoot/Module/ContentView.swift|ModuleName/ContentView.swift|
|#filePath|/Users/UserName/XcodeProjeRoot/Module/ContentView.swift|/Users/UserName/XcodeProjeRoot/Module/ContentView.swift|
`fatalError("Something bad happened!")` などの時も `Fatal error: Something bad happened!: file Module/ContentView.swift, line 3` と #fileを見ているので影響があるらしい
Pathは開発者毎に違うので便利そう。有効にしてもいいかも
### SE-0286: Forward-scan matching for trailing closures
https://github.com/apple/swift-evolution/blob/main/proposals/0286-forward-scan-trailing-closures.md
trailing closuresのスキャンが前方からになる変更
multiple trailing closuresの関係で色々壊れていたのを修正するらしい
具体的には現状
```swift=
func animate(
withDuration duration: TimeInterval,
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
)
```
こういうfuncに対して
```swift=
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0
}
```
これが書けないのが問題でそれを修正できるらしい。(completionはdefault = nilでtrailing closureはanimationsになってほしいがそれができてない)
逆に前方からになることで壊れることとかないのかなって思ったりするけど詳しいことは理解できなかった。
iOS Xcode Projではもう有効っぽい
### SE-0335: Introduce existential any (ExistentialAny)
https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
Twitterとかでも話題のやつ
存在型をletなどで宣言する際にanyを強制する。
具体的には
```swift=
protocol CacheDataStore {
...
}
struct CacheDataStoreImpl: CacheDataStore {
...
}
struct HogeRepository {
let cacheDataStore: CacheDataStore
init(cacheDataStore: CacheDataStore) {
self.cacheDataStore = cacheDataStore
}
}
let hogeRepository = HogeRepository(cacheDataStore: CacheDataStoreImpl())
```
というコードがコンパイルエラーになり
```swift=
protocol CacheDataStore {
...
}
struct CacheDataStoreImpl: CacheDataStore {
...
}
struct HogeRepository {
let cacheDataStore: any CacheDataStore
init(cacheDataStore: any CacheDataStore) {
self.cacheDataStore = cacheDataStore
}
}
let hogeRepository = HogeRepository(cacheDataStore: CacheDataStoreImpl())
```
という感じになる。
この記事が詳しく書かれている
https://zenn.dev/treastrain/articles/555d4a2fc1b40b
上の記事からの参照ですがこのFix All Issuesすごい役に立った

またAuto Fixは完全ではないため以下のことに気をつける必要がある
|before|AutoFix|正しい書き方|
|----|----|----|
|cacheDataStore: CacheDataStore?|cacheDataStore: any CacheDataStore?|cacheDataStore: (any CacheDataStore)?|
|cacheDataStore: CacheDataStore!|cacheDataStore: any CacheDataStore!|cacheDataStore: (any CacheDataStore)!|
### SE-0354: Regex literals (BareSlashRegexLiterals)
https://github.com/apple/swift-evolution/blob/main/proposals/0354-regex-literals.md
Regexを `/(?<identifier>[[:alpha:]]\w*) = (?<hex>[0-9A-F]+)/` こんな感じでかけるようにするもの
iOSのXcode Projectでは現在ももう書けるのでSwift Package Managerで作ったSwift Serverとかでの話だと思われる(なんでiOSのXcode Projectはかけるようになっているかは不明)
## SE-0365 Allow implicit self for weak self captures, after self is unwrapped
`[weak self]` を `guarad let self` 以降はselfなしで書けるようになる
```swift=
class ViewController {
let button: Button
func setup() {
button.tapHandler = { [weak self] in
guard let self else { return }
dismiss()
}
}
func dismiss() { ... }
}
```
`guarad let self = self` でもいけた
## SE-0367 Conditional compilation for attributes
attributesに対してConditional compilationを書けるようになった
具体的にはこんな感じ
```swift=
#if hasAttribute(preconcurrency)
@preconcurrency
#endif
protocol P: Sendable {
func f()
func g()
}
```
ちなみに `@preconcurrency` はswift 5.6で導入されている
https://github.com/apple/swift-evolution/blob/main/proposals/0337-support-incremental-migration-to-concurrency-checking.md
@Sendableに対応しなきゃだけで今はできないからみたいな時につけておくとコンパイラーが許してくれるやつっぽいのでこれも今後使いそうなので見ておきたい
## SE-0373: Lift all limitations on variables in result builders
https://github.com/apple/swift-evolution/blob/main/proposals/0373-vars-without-limits-in-result-builders.md
ResultBuilderの中で色々な制限が解除された模様
こういうlazyや
> https://www.hackingwithswift.com/swift/5.8/lift-result-builder-limitations
```swift=
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
lazy var user = fetchUsername()
Text("Hello, \(user).")
}
.padding()
}
func fetchUsername() -> String {
"@twostraws"
}
}
```
Property Wrapperが使えるようになったらしい
```swift=
import SwiftUI
struct AppIntroView: View {
var body: some View {
@UserDefault(key: "user_has_ever_interacted") var hasInteracted: Bool
...
Button("Browse Features") {
...
hasInteracted = true
}
Button("Create Account") {
...
hasInteracted = true
}
}
}
```
具体的これいいなって思ったのはないので使わないかも。。。
## SE-0376: Function Back Deployment
https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md
バックデプロイ用の何か
この記事
> https://www.hackingwithswift.com/swift/5.8/function-back-deployment
によるとこんなのが書けるようになるらしい
```swift=
extension Text {
@backDeployed(before: iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0)
@available(iOS 14.0, macOS 11, tvOS 14.0, watchOS 7.0, *)
public func monospaced(_ isActive: Bool) -> Text {
fatalError("Implementation here")
}
}
```
すごいいいじゃんって思ったけど手元で試した限りはうまく動かずiOS 16でもkoこのextensionのmonospacedが呼ばれてしまっていてよくわからなかった。
ライブラリ側で使える機能なのかもしれない。。。