UITextView 在循环期间不更新
UITextView does not update during loop
所以我尝试了两种不同的方式来在屏幕上显示计时器倒计时。
代码将打印到控制台而不是 UITextView(在两种循环情况下)重复 UITextView 以 0 结尾,这是它显示的唯一内容,而不是原始 txt“时间计数”。 .. 在实现注释循环的情况下,UITextView 仅显示 1(倒计时结束)...为什么它打印到控制台,尽管这些命令与 UITextView 位于相同的括号中并且它们重复
图像是在 运行 代码和单击“软”之后(这是 brewery egg timer 应用程序的衍生产品)
//
// ViewController.swift
// EggTimer
//
// Created by Angela Yu on 08/07/2019.
// Copyright © 2019 The App Brewery. All rights reserved.
//
import UIKit
let softTime = 5
let medTime = 7
let hardTime = 12
class ViewController: UIViewController {
@IBOutlet weak var timerTextView: UITextView!
@IBAction func eggHardnessButton(_ sender: UIButton) {
let hardness = sender.currentTitle
func timeCountDownSoft() {
var time = 3
repeat {
time = time - 1 //repeats
timerTextView.selectAll("") // does not repeat
timerTextView.insertText("") // does not repeat
let timeWord = String(time) // repeats
timerTextView.insertText(timeWord)//does not repeat
print(time) //repeats
sleep(1) //repeats
} while time >= 1
/*for timer in stride(from: 2, to: 0 , by: -1){
let time = String(timer)
timerTextView.selectAll("")
timerTextView.insertText("")
timerTextView.insertText(time)
print(time)
sleep(1)
}*/
}
func timeCountDownMed() {
for timer in stride(from: 420, to: 0 , by: -1) {
print(timer)
sleep(1)
}
}
func timeCountDownHard() {
for timer in stride(from: 720, to: 0 , by: -1) {
print(timer)
sleep(1)
}
}
if hardness == "Soft" {
print(softTime) // does not repeat
timeCountDownSoft() // does not repeat
} else if hardness == "Medium" {
print(medTime)
timeCountDownMed()
} else {
print(hardTime)
timeCountDownHard()
}
}
}
您从不(好吧,几乎从不)想要使用sleep()
.
您的文本未更新的原因是因为您是 运行 闭环,不允许 UIKit 更新视图。
您想要做的是使用具有 one-second
间隔的重复 Timer
。每次计时器触发时,减少您的计数器并更新 UI。当计数器达到零时,停止计时器。
这是一个简单的例子:
import UIKit
let softTime = 5
let medTime = 7
let hardTime = 12
class ViewController: UIViewController {
@IBOutlet weak var timerTextView: UITextView!
var theTimer: Timer?
@IBAction func eggHardnessButton(_ sender: UIButton) {
let hardness = sender.currentTitle
var numSeconds = 0
// set number of seconds based on button title
switch hardness {
case "Soft":
numSeconds = softTime * 60
case "Medium":
numSeconds = medTime * 60
case "Hard":
numSeconds = hardTime * 60
default:
// some other button called this func, so just return
return()
}
// stop current timer if it's running
if let t = theTimer {
if t.isValid {
t.invalidate()
}
}
// update text field with selected time
let timeWord = String(numSeconds)
self.timerTextView.text = timeWord
// start a timer with 1-second interval
theTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
numSeconds -= 1
let timeWord = String(numSeconds)
self.timerTextView.text = timeWord
// if we've reached Zero seconds remaining
if numSeconds == 0 {
// stop the timer
timer.invalidate()
}
}
}
}
几点:
当您的应用更改 UI 时,这些更改实际上并没有得到
呈现在屏幕上,直到您的代码 returns 并访问应用程序的
事件循环。因此,在你的重复循环中,什么都不会出现在
UI 直到循环完成
不要在主线程上使用 sleep()。这阻止了一切,并且
您的应用突然停止。
如果你想每秒更新一次UI,设置一个重复定时器
每秒触发一次并在计时器代码中进行 UI 更新。
所以我尝试了两种不同的方式来在屏幕上显示计时器倒计时。
代码将打印到控制台而不是 UITextView(在两种循环情况下)重复 UITextView 以 0 结尾,这是它显示的唯一内容,而不是原始 txt“时间计数”。 .. 在实现注释循环的情况下,UITextView 仅显示 1(倒计时结束)...为什么它打印到控制台,尽管这些命令与 UITextView 位于相同的括号中并且它们重复
图像是在 运行 代码和单击“软”之后(这是 brewery egg timer 应用程序的衍生产品)
//
// ViewController.swift
// EggTimer
//
// Created by Angela Yu on 08/07/2019.
// Copyright © 2019 The App Brewery. All rights reserved.
//
import UIKit
let softTime = 5
let medTime = 7
let hardTime = 12
class ViewController: UIViewController {
@IBOutlet weak var timerTextView: UITextView!
@IBAction func eggHardnessButton(_ sender: UIButton) {
let hardness = sender.currentTitle
func timeCountDownSoft() {
var time = 3
repeat {
time = time - 1 //repeats
timerTextView.selectAll("") // does not repeat
timerTextView.insertText("") // does not repeat
let timeWord = String(time) // repeats
timerTextView.insertText(timeWord)//does not repeat
print(time) //repeats
sleep(1) //repeats
} while time >= 1
/*for timer in stride(from: 2, to: 0 , by: -1){
let time = String(timer)
timerTextView.selectAll("")
timerTextView.insertText("")
timerTextView.insertText(time)
print(time)
sleep(1)
}*/
}
func timeCountDownMed() {
for timer in stride(from: 420, to: 0 , by: -1) {
print(timer)
sleep(1)
}
}
func timeCountDownHard() {
for timer in stride(from: 720, to: 0 , by: -1) {
print(timer)
sleep(1)
}
}
if hardness == "Soft" {
print(softTime) // does not repeat
timeCountDownSoft() // does not repeat
} else if hardness == "Medium" {
print(medTime)
timeCountDownMed()
} else {
print(hardTime)
timeCountDownHard()
}
}
}
您从不(好吧,几乎从不)想要使用sleep()
.
您的文本未更新的原因是因为您是 运行 闭环,不允许 UIKit 更新视图。
您想要做的是使用具有 one-second
间隔的重复 Timer
。每次计时器触发时,减少您的计数器并更新 UI。当计数器达到零时,停止计时器。
这是一个简单的例子:
import UIKit
let softTime = 5
let medTime = 7
let hardTime = 12
class ViewController: UIViewController {
@IBOutlet weak var timerTextView: UITextView!
var theTimer: Timer?
@IBAction func eggHardnessButton(_ sender: UIButton) {
let hardness = sender.currentTitle
var numSeconds = 0
// set number of seconds based on button title
switch hardness {
case "Soft":
numSeconds = softTime * 60
case "Medium":
numSeconds = medTime * 60
case "Hard":
numSeconds = hardTime * 60
default:
// some other button called this func, so just return
return()
}
// stop current timer if it's running
if let t = theTimer {
if t.isValid {
t.invalidate()
}
}
// update text field with selected time
let timeWord = String(numSeconds)
self.timerTextView.text = timeWord
// start a timer with 1-second interval
theTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
numSeconds -= 1
let timeWord = String(numSeconds)
self.timerTextView.text = timeWord
// if we've reached Zero seconds remaining
if numSeconds == 0 {
// stop the timer
timer.invalidate()
}
}
}
}
几点:
当您的应用更改 UI 时,这些更改实际上并没有得到 呈现在屏幕上,直到您的代码 returns 并访问应用程序的 事件循环。因此,在你的重复循环中,什么都不会出现在 UI 直到循环完成
不要在主线程上使用 sleep()。这阻止了一切,并且 您的应用突然停止。
如果你想每秒更新一次UI,设置一个重复定时器 每秒触发一次并在计时器代码中进行 UI 更新。