【问题标题】:WKExtendedRuntimeSession stopping after about 30 seconds?WKExtendedRuntimeSession 在大约 30 秒后停止?
【发布时间】:2021-04-08 03:00:28
【问题描述】:

这真是让我抓狂。我在这里尝试了各种组合,甚至达到了这一点。它有时有效,有时无效。当它确实工作时,它会在后台自行停止。请帮忙。总的来说,我对编码完全是个菜鸟,并且一直在尝试许多不同的方法,所以我对这个问题表示歉意。

    if inspectionTime == true {
        if stopWatchManager.mode == .stopped {
            ZStack{
            HStack {
                if stopWatchManager.minutesElapsed > 0 {
                    if stopWatchManager.secondsElapsed < 10 {
                    Text("\(stopWatchManager.minutesElapsed) :0")
                        .font(.largeTitle)
                        .contentShape(Rectangle())
                        .onTapGesture(count: 2, perform: {
                            stopWatchManager.resetToZero()
                        })
                        .foregroundColor(isPressingDown ? .green : .white)
                        
                        .gesture(LongPressGesture(minimumDuration: 0.5)
                            .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                            .updating($isPressingDown) { value, state, transaction in
                                
                                switch value {
                                    case .second(true, nil): //This means the first Gesture completed
                                        state = true
                                        
                                    default: break
                                }
                            })
                }
                 else   {
                    Text("\(stopWatchManager.minutesElapsed) :")
                        .font(.largeTitle)
                        .contentShape(Rectangle())
                        .onTapGesture(count: 2, perform: {
                            stopWatchManager.resetToZero()
                        })
                        .foregroundColor(isPressingDown ? .green : .white)
                        
                        .gesture(LongPressGesture(minimumDuration: 0.5)
                            .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                            .updating($isPressingDown) { value, state, transaction in
                                
                                switch value {
                                    case .second(true, nil): //This means the first Gesture completed
                                        state = true
                                        
                                    default: break
                                }
                            })
                }
                }
                Text("\(stopWatchManager.secondsElapsed, specifier: "%.02f")")
            .font(.largeTitle)
            .contentShape(Rectangle())
            .onTapGesture(count: 2, perform: {
                stopWatchManager.resetToZero()
                
                
            })
            
            .foregroundColor(isPressingDown ? .green : .white)
            
            .gesture(LongPressGesture(minimumDuration: 0.5)
                .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                .updating($isPressingDown) { value, state, transaction in
                    
                    switch value {
                        case .second(true, nil): //This means the first Gesture completed
                            state = true
                            
                        default: break
                    }
                })
            .onChange(of: isPressingDown, perform: { value in
                if isPressingDown == false {
                    if session.state == WKExtendedRuntimeSessionState.notStarted{
                        session.start()}
                    if showCountdown == false {

                        showCountdown = true
                        DispatchQueue.main.asyncAfter(deadline: .now() + 13.5){
                            if showCountdown == true {
                                stopWatchManager.start()
                                showCountdown = false}
                        }
                    }
                    else if showCountdown == true{
                    stopWatchManager.start()
                    showCountdown = false
                    
                    }
                    turnGreen = false
                    
                }
                else if isPressingDown == true{
                //    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5){
                        WKInterfaceDevice.current().play(.click)

                //    }
                    

                }
                if showCountdown == true && isPressingDown == true {
                   turnGreen = true
                }
            })

        }
                if showCountdown == true {
                    CountdownView()}
                Rectangle()
                    .contentShape(Rectangle())
                    .onTapGesture(count: 2, perform: {
                        stopWatchManager.resetToZero()
                        showCountdown = false
                    })
                    .gesture(LongPressGesture(minimumDuration: 0.5)
                        .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                        .updating($isPressingDown) { value, state, transaction in
                            
                            switch value {
                                case .second(true, nil): //This means the first Gesture completed
                                    state = true
                                    
                                default: break
                            }
                        })
                    .opacity(0.1)
                    .foregroundColor(.black)
                    .gesture(LongPressGesture(minimumDuration: 0.5)
                        .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                                .updating($testing) { value, state, transaction in
                            
                            switch value {
                                case .second(true, nil): //This means the first Gesture completed
                                    state = true
                                    
                                default: break
                            }
                        })
        }
        }
       else if stopWatchManager.mode == .running {
        ZStack{
        HStack{
        if stopWatchManager.minutesElapsed > 0 {
            if stopWatchManager.secondsElapsed < 10 {
            Text("\(stopWatchManager.minutesElapsed) :0")
                .font(.largeTitle)
                .contentShape(Rectangle())
                .onTapGesture(count: 2, perform: {
                    stopWatchManager.resetToZero()
                })
                .foregroundColor(isPressingDown ? .green : .white)
                
                .gesture(LongPressGesture(minimumDuration: 0.5)
                    .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                    .updating($isPressingDown) { value, state, transaction in
                        
                        switch value {
                            case .second(true, nil): //This means the first Gesture completed
                                state = true
                                
                            default: break
                        }
                    })
        }
         else   {
            Text("\(stopWatchManager.minutesElapsed) :")
                .font(.largeTitle)
              //  .frame(width: 500.0, height: 500.0)
                .contentShape(Rectangle())
                .onTapGesture(count: 2, perform: {
                    stopWatchManager.resetToZero()
                })
                .foregroundColor(isPressingDown ? .green : .white)
                
                .gesture(LongPressGesture(minimumDuration: 0.5)
                    .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                    .updating($isPressingDown) { value, state, transaction in
                        
                        switch value {
                            case .second(true, nil): //This means the first Gesture completed
                                state = true
                                
                            default: break
                        }
                    })
        }
        }
            Text(String(format: "%.02f", stopWatchManager.secondsElapsed))


                .font(.largeTitle)
                //.frame(width: 500.0, height: 500.0)
                .contentShape(Rectangle())
                .onTapGesture {
                    if stopWatchManager.mode == .running {
                        stopWatchManager.stop()
                    }
                }
                .onChange(of: stopWatchManager.secondsElapsed, perform: {value in
                        if stopWatchManager.secondsElapsed >= 60{
                            stopWatchManager.secondsElapsed = 0
                            stopWatchManager.minutesElapsed = stopWatchManager.minutesElapsed + 1

                        }})
            
    }
        Rectangle()
            .contentShape(Rectangle())
            .onTapGesture{
            if stopWatchManager.mode == .running {
                stopWatchManager.stop()
            }
            }
            .gesture(LongPressGesture(minimumDuration: 0.5)
                .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                .updating($isPressingDown) { value, state, transaction in
                    
                    switch value {
                        case .second(true, nil): //This means the first Gesture completed
                            state = true
                            
                        default: break
                    }
                })
            .opacity(0.01)
            .foregroundColor(.black)}}}

    class StopWatchManager: ObservableObject {
    var session = WKExtendedRuntimeSession()
    let scoreList = ScoreList()
    @AppStorage("countdown") var countdown = "15"

    @AppStorage("bigDNF") var bigDNF: Bool = false

    @Published var secondsElapsed = 0.00
    @Published var minutesElapsed = 0

    @Published var mode: stopWatchMode = .stopped
    @State private var timeRemaining = 100
    let countdownTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    @ObservedObject var scoreStore = ScoreStore()
    @AppStorage("newScore") var newScore = ""
    @AppStorage("save") var save = false
    @AppStorage("plus2") var plus2 = false

    var timer = Timer()
    
    

    func start() {
        session = WKExtendedRuntimeSession()
        if session.state == WKExtendedRuntimeSessionState.notStarted{
            session.start()}

        mode = .running
        WKInterfaceDevice.current().play(.start)
        secondsElapsed = 0
        minutesElapsed = 0

        timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in
            self.secondsElapsed += 0.01
        }
        
    }
    func stop() {
        let formattedSeconds = String(format: "%.02f", secondsElapsed)
        
        timer.invalidate()
        
        mode = .stopped
        WKInterfaceDevice.current().play(.start)
        
        if plus2 == true {
        secondsElapsed = secondsElapsed + 2
        }
        //DispatchQueue.main.asyncAfter(deadline: .now() + 1.0)

        if minutesElapsed > 0{
            
            newScore = "\(minutesElapsed) :\(formattedSeconds)"
            save = true
        }
        else {
            newScore = "\(formattedSeconds)"

        }
        save = true
        
       // session.invalidate()


    }
    
    func resetToZero() {
            
            secondsElapsed = 0
        minutesElapsed = 0
        WKInterfaceDevice.current().play(.click)
        bigDNF = false

    }
    
    
}

【问题讨论】:

  • 您在 info.plist 中配置了哪种扩展运行时会话?老实说,这可能不是创建秒表的最佳方式。您只需在秒表启动时记录Date,然后您就可以轻松确定经过的时间。当您的应用实际在屏幕上时,您只需要一个计时器来定期更新经过的时间。如果你坚持开始日期(比如UserDefaults),那么你不需要你的应用程序继续运行。这样电池效率更高
  • 我将不得不研究这种方法,谢谢!我对完全编码仍然非常陌生,并且在研究时发现了这种方法。然而,使用这种方法,我并没有触及绘图文件本身。我确实将背景模式设置为物理治疗会话类型。甚至尝试在其上启用音频。我在控制台中也看到了一些错误:“Error Domain=com.apple.CarouselServices.SessionErrorDomain Code=19 “no client found for pid””和“WKExtendedRuntimeObject 在运行时被释放。使会话无效”

标签: ios swift swiftui watch watchos


【解决方案1】:

WatchOS 故意限制在后台执行的机会,因为它会耗尽电池电量。不需要后台任务来实现秒表。

您需要在您的应用在屏幕上运行时运行一个计时器,以便定期更新显示。要跟踪经过的时间,您可以简单地记录秒表开始时的Date。由于时间总是向前移动,当应用程序不在屏幕上时,您不需要后台任务。当用户返回您的应用时,您可以简单地根据该开始日期计算并显示经过的时间。

我在下面包含了一个最小的秒表视图。请注意,UserDefaults 无法存储 Date 对象,因此我将开始日期存储为 Double - 自参考日期以来的时间。

也不需要手势识别器 - 您只需使用 Button

struct StopwatchView: View {
    
    @AppStorage("running") var running = false
    @AppStorage("started") var started = Date.distantPast.timeIntervalSinceReferenceDate
    let timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
    
    @AppStorage("minutes") var elapsedMinutes = 0
    @AppStorage("seconds") var elapsedSeconds = 0
    @State var elapsed = "00:00"
    
    var body: some View {
        VStack {
            Text(elapsed).onReceive(timer) { input in
                self.elapsed = elapsedTime()
            }.font(.system(.headline, design: .monospaced))
            Spacer()
            Button( action: {
                self.running.toggle()
                if self.running {
                    self.started = Date().timeIntervalSinceReferenceDate
                }
            }) {
                Text(self.running ? "Stop":"Start")
            }.buttonStyle(BorderedButtonStyle(tint: self.running ? Color.red : Color.green))
        }
        .padding()
        
    }
    
    func elapsedTime() -> String {
        if self.running {
            
            let startDate = Date(timeIntervalSinceReferenceDate: self.started)
            let elapsedTime = max( Date().timeIntervalSince(startDate),0)
            elapsedMinutes = Int(elapsedTime / 60)
            elapsedSeconds = Int(elapsedTime - Double(elapsedMinutes * 60))
        }
        
        return String(format:"%02d:%02d",elapsedMinutes,elapsedSeconds)
        
    }
}

【讨论】:

  • 非常感谢!我现在正在调查这个。请原谅我的无知,这又是全新的,但是我将如何使用像 00:00.00 这样的计时器来设置它?非常感谢!!
  • 就像我在分秒中所做的一样;除以 3600 得到整数小时数,然后减去整数小时数乘以 3600 得到重命名分钟(以秒为单位),然后使用那里的代码
  • 感谢您的帮助!我在你的建议下取得了巨大的进步。我遇到的一个障碍(因为我现在确实出现了小数)它们一次只更新 1 秒,并使其与秒同步。而它应该运行得更快,正如秒表所预期的那样。
  • 那么你需要减少计时器延迟并显示小数秒(在计算时将elapsedSeconds 设为Double 并删除Int()
猜你喜欢
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 2020-03-29
  • 2019-01-11
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多