コードはこちら
//
// ContentView.swift
// SwiftUIShape
//
// Created by tsu-na-gu on 2026/04/10.
//
import SwiftUI
struct ContentView: View {
private var purpleGradient = LinearGradient(gradient: Gradient(colors: [Color(red: 207/255, green: 150/255, blue: 207/255), Color(red: 107/255, green: 116/255, blue: 179/255)]), startPoint: .trailing, endPoint: .leading)
@State private var progress = 0.0
var body: some View {
VStack {
ZStack {
Circle()
.stroke(Color(.systemGray6), lineWidth: 20)
.frame(width: 300, height: 300)
Circle()
.trim(from:0.0, to: progress)
.stroke(purpleGradient, lineWidth: 20)
.frame(width: 300, height: 300)
.rotationEffect(.degrees(-90))
.overlay {
VStack {
Text("\(Int(progress * 100))%")
.font(.system(size: 80, weight: .bold, design: .rounded))
.foregroundColor(.gray)
Text("Complete")
.font(.system(.body, design: .rounded))
.bold()
.foregroundColor(.gray)
}
}
}
.padding(100)
Button {
Task {
await progressStart()
}
} label: {
Label("Start", systemImage: "play.circle")
.foregroundStyle(.white)
}
.buttonStyle(.borderedProminent)
}
}
private func progressStart() async {
progress = 0.0
for i in 0...100 {
try? await Task.sleep(for: .milliseconds(80))
withAnimation(.linear(duration: 0.08)) {
progress = Double(i) / 100.0
}
}
}
}
#Preview {
ContentView()
}
学習ソースはこちら、$20月で開設ビデオが見られるよ
sleepのtolaranceパラメータの意味についてCaludeの回答
Task.sleepのtoleranceパラメータは、主に電力効率の最適化のために機能します。具体的に効果を発揮するのは以下のような場合です:
toleranceが機能する状況
- 複数のタイマーイベントがある場合
swift// 例:複数のタスクが近い時間にスリープしている
Task {
try await Task.sleep(for: .seconds(3), tolerance: .seconds(1))
// 処理A
}
Task {
try await Task.sleep(for: .seconds(3.5), tolerance: .seconds(1))
// 処理B
}
システムはこれらを「まとめて」起動できます(3〜4秒の範囲内で両方を処理)
2. デバイスが低電力状態の場合
iOSデバイスがバックグラウンド状態
Macがアイドル状態でCPUが低電力モードに入っている
→ toleranceがあることで、システムは効率的なタイミングでCPUを起こせます
- バッテリー駆動時
モバイルデバイスで特に効果的。CPUのウェイクアップ回数を減らすことで電力消費を抑えます。
toleranceがあまり意味を持たない場合
CPUが常にアクティブ:ゲームや動画再生中など
単独のタイマーのみ:他にスケジュールされたイベントがない
短時間のスリープ:数ミリ秒程度の場合
実用的な使い分け
swift// 正確なタイミングが必要な場合
try await Task.sleep(for: .seconds(3), tolerance: .zero)
// 電力効率を優先する場合(推奨)
try await Task.sleep(for: .seconds(3), tolerance: .seconds(1))
つまり、toleranceは「このくらいズレても構わない」という余裕をシステムに与えることで、システムが賢く電力管理できるようにする仕組みです。特にバックグラウンド処理や定期的なタスクで効果を発揮します。
続いてTaskは代入先にresultで取得できるenum型を代入することを確認
//
// main.swift
// TaskSleep
//
// Created by tsu-na-gu on 2026/04/10.
//
import Foundation
//try await Task.sleep(for: .seconds(3), tolerance: .seconds(1))
enum LocalError: Error {
case fetchFailed, decodeFailed
}
func fetchQuotes() async {
let downlodadTask = Task {
let url = URL(string: "https://hws.dev/quotes.txt")!
do {
let (data, _) = try await URLSession.shared.data(from: url)
if let string = String(data: data, encoding: .utf8) {
return string
} else {
throw LocalError.decodeFailed
}
} catch {
throw LocalError.fetchFailed
}
}
let result = await downlodadTask.result
switch result {
case .success(let string):
print(string)
case .failure(let error):
print("Error occured: \(error)")
}
}
result.get()をするとエラーが再スローされるのでハンドリングしてもよし
//
// main.swift
// TaskSleep
//
// Created by tsu-na-gu on 2026/04/10.
//
import Foundation
//try await Task.sleep(for: .seconds(3), tolerance: .seconds(1))
enum LocalError: Error {
case fetchFailed, decodeFailed
}
func fetchQuotes() async {
let downlodadTask = Task {
let url = URL(string: "https://hws.dev/quotes.txt")!
do {
let (data, _) = try await URLSession.shared.data(from: url)
if let string = String(data: data, encoding: .utf8) {
return string
} else {
throw LocalError.decodeFailed
}
} catch {
throw LocalError.fetchFailed
}
}
let result = await downlodadTask.result
do {
let string = try result.get()
print(string)
} catch LocalError.fetchFailed {
print("Unable to fetch the quotes.")
} catch LocalError.decodeFailed {
print("Unable to convert data to text.")
} catch {
print("unknown error.")
}
さらにエラーの種類が問題にならないなら、try?でnil代入して早期returnしても構わない
func processQuotes() async {
let downloadTask = Task {
let url = URL(string: "https://hws.dev/quotes.txt")!
let (data, _) = try await URLSession.shared.data(from: url)
guard let string = String(data: data, encoding: .utf8) else {
throw LocalError.decodeFailed
}
return string
}
let result = await downloadTask.result
// try? でOptionalに変換
guard let string = try? result.get() else {
print("Failed to fetch quotes")
return // 早期リターン
}
print(string) // 成功パス
}