SwiftUIの素人です。エラーが消せないのでお知恵をいただきたくよろしくお願いします。
https://stackoverflow.com/questions/63765532/swiftui-how-to-run-a-timer-in-background/70046189#70046189
のサイトを参考に以下のように作成したのですが、エラーが出て理由がわかりません。
Stopwatch.swift
swiftui
1import SwiftUI 2 3struct Stopwatch: View { 4 var body: some View { 5 class Stopwatch: ObservableObject { 6 /// String to show in UI 7 @Published private(set) var message = "Not running" 8 9 /// Is the timer running? 10 @Published private(set) var isRunning = false 11 12 /// Time that we're counting from 13 private var startTime: Date? { didSet { saveStartTime() } } 14 15 /// The timer 16 private var timer: AnyCancellable? 17 18 init() { 19 startTime = fetchStartTime()//<----------- ① 20 21 if startTime != nil { 22 start() 23 } 24 } 25 } 26 27 // MARK: - Public Interface 28 29 extension Stopwatch { //<----------- ② 30 31 func start() { 32 timer?.cancel() // cancel timer if any 33 34 if startTime == nil { 35 startTime = Date() 36 } 37 38 message = "" 39 40 timer = Timer 41 .publish(every: 0.1, on: .main, in: .common) 42 .autoconnect() 43 .sink { [weak self] _ in 44 guard 45 let self = self, 46 let startTime = self.startTime 47 else { return } 48 49 let now = Date() 50 let elapsed = now.timeIntervalSince(startTime) 51 52 guard elapsed < 60 else { 53 self.stop() 54 return 55 } 56 57 self.message = String(format: "%0.1f", elapsed) 58 } 59 60 isRunning = true 61 } 62 63 func stop() { 64 timer?.cancel() 65 timer = nil 66 startTime = nil 67 isRunning = false 68 message = "Not running" 69 } 70 } 71 72 // MARK: - Private implementation 73 74 private extention Stopwatch { 75 func saveStartTime() { 76 if let startTime = startTime { 77 UserDefaults.standard.set(startTime, forKey: "startTime") 78 } else { 79 UserDefaults.standard.removeObject(forKey: "startTime") 80 } 81 } 82 83 func fetchStartTime() -> Date? { 84 UserDefaults.standard.object(forKey: "startTime") as? Date 85 } 86 } 87 } 88} 89 90struct Stopwatch_Previews: PreviewProvider { 91 static var previews: some View { 92 Stopwatch() 93 } 94} 95
ContentView.swift
import SwiftUI struct ContentView: View{ @ObservedObject var stopwatch = Stopwatch() //<----------- ③ var body: some View { VStack { Text(stopwatch.message) Button(stopwatch.isRunning ? "Stop" : "Start") { if stopwatch.isRunning { stopwatch.stop() } else { stopwatch.start() } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
3つエラーが出てまして、
①Cannot find 'fetchStartTime' in scope
②Declaration is only valid at file scope
③Generic struct 'ObservedObject' requires that 'Stopwatch' conform to 'ObservableObject'
です。
何かが足りないのだと思うのですが、解決できません。
ものすごく基礎的なことをお聞きしていると思うのですが、お教えいただければ幸いです。
よろしくお願いします。
その後、hoshiさんの③のコメントにあるようにstructに使えないということで、質問の上にあったStopwatch.swiftを
import SwiftUI class Stopwatch2: ObservableObject { /// String to show in UI @Published private(set) var message = "Not running" /// Is the timer running? @Published private(set) var isRunning = false /// Time that we're counting from private var startTime: Date? { didSet { saveStartTime() } }//<--④ /// The timer private var timer: AnyCancellable?// <--⑤ init() { startTime = fetchStartTime() //<--⑥ if startTime != nil { start() //<--⑦ } } } // MARK: - Public Interface extension Stopwatch { func start() { timer?.cancel() // cancel timer if any. <--⑧ if startTime == nil { //<--⑨ 以下同様のエラー多数 startTime = Date() } message = "" timer = Timer .publish(every: 0.1, on: .main, in: .common) .autoconnect() .sink { [weak self] _ in guard let self = self, let startTime = self.startTime else { return } let now = Date() let elapsed = now.timeIntervalSince(startTime) guard elapsed < 60 else { self.stop() return } self.message = String(format: "%0.1f", elapsed) } isRunning = true } func stop() { timer?.cancel() timer = nil startTime = nil isRunning = false message = "Not running" } } // MARK: - Private implementation private extension Stopwatch { func saveStartTime() { if let startTime = startTime { UserDefaults.standard.set(startTime, forKey: "startTime") } else { UserDefaults.standard.removeObject(forKey: "startTime") } } func fetchStartTime() -> Date? { UserDefaults.standard.object(forKey: "startTime") as? Date } }
のようにし、③のエラーは消えたのですが、その代わりclass Stopwatch下の各変数がCannot find '????' in scopeになってしまいます。
例えば④であれば、Cannot find 'saveStartTime' in scopeclass ⑤であればCannot find 'AnyCancellable' in scopeclass です。
class Stopwatch2: ObservableObject {以下を同一スコープの中に入れる方法がわかりません。
質問の仕方が稚拙とは思いますがよろしくお願いします。
回答1件
あなたの回答
tips
プレビュー