带计时器的绘图应用程序。绘图不到 20 秒后计时器开始滞后
Drawing app with timer. Timers begins to lag after drawing for less than 20 seconds
我在一些朋友的帮助下制作了这个应用程序。我真的不知道代码是如何工作的。
它基本上使用苹果铅笔记录数据(平板电脑上的时间、苹果铅笔的速度、笔划数等)。然而,随着时间的流逝和绘图的增多,计时器与实际时间不同步。
这个应用程序的目的是用于痴呆症研究,我让患者在平板电脑上画画,然后我收集相关信息。如果计时器发臭,我就无法进行研究了。
我试过禁用所有计时器,但延迟仍然一样。我有一种感觉,它与笔画的采样方式有关。我只需要一个笔画计数,我不需要它来显示每分钟的笔画(这是它目前正在做的)。我认为中风计数器可能是原因???
这是程序:
https://drive.google.com/open?id=1lwzKwG7NLcX1qmE5yoxsdq5HICV2TNHm
class StrokeSegment {
var sampleBefore: StrokeSample?
var fromSample: StrokeSample!
var toSample: StrokeSample!
var sampleAfter: StrokeSample?
var fromSampleIndex: Int
var segmentUnitNormal: CGVector {
return segmentStrokeVector.normal!.normalized!
}
var fromSampleUnitNormal: CGVector {
return interpolatedNormalUnitVector(between: previousSegmentStrokeVector, and: segmentStrokeVector)
}
var toSampleUnitNormal: CGVector {
return interpolatedNormalUnitVector(between: segmentStrokeVector, and: nextSegmentStrokeVector)
}
var previousSegmentStrokeVector: CGVector {
if let sampleBefore = self.sampleBefore {
return fromSample.location - sampleBefore.location
} else {
return segmentStrokeVector
}
}
var segmentStrokeVector: CGVector {
return toSample.location - fromSample.location
}
var nextSegmentStrokeVector: CGVector {
if let sampleAfter = self.sampleAfter {
return sampleAfter.location - toSample.location
} else {
return segmentStrokeVector
}
}
init(sample: StrokeSample) {
self.sampleAfter = sample
self.fromSampleIndex = -2
}
@discardableResult
func advanceWithSample(incomingSample: StrokeSample?) -> Bool {
if let sampleAfter = self.sampleAfter {
self.sampleBefore = fromSample
self.fromSample = toSample
self.toSample = sampleAfter
self.sampleAfter = incomingSample
self.fromSampleIndex += 1
return true
}
return false
}
}
class StrokeSegmentIterator: IteratorProtocol {
private let stroke: Stroke
private var nextIndex: Int
private let sampleCount: Int
private let predictedSampleCount: Int
private var segment: StrokeSegment!
init(stroke: Stroke) {
self.stroke = stroke
nextIndex = 1
sampleCount = stroke.samples.count
predictedSampleCount = stroke.predictedSamples.count
if (predictedSampleCount + sampleCount) > 1 {
segment = StrokeSegment(sample: sampleAt(0)!)
segment.advanceWithSample(incomingSample: sampleAt(1))
}
}
func sampleAt(_ index: Int) -> StrokeSample? {
if index < sampleCount {
return stroke.samples[index]
}
let predictedIndex = index - sampleCount
if predictedIndex < predictedSampleCount {
return stroke.predictedSamples[predictedIndex]
} else {
return nil
}
}
func next() -> StrokeSegment? {
nextIndex += 1
if let segment = self.segment {
if segment.advanceWithSample(incomingSample: sampleAt(nextIndex)) {
return segment
}
}
return nil
}
}
例如 true 25 秒,应用程序显示总时间为 20 秒。
A Timer
不是计算经过时间的东西。它是一种用于在经过一段时间后触发执行的工具。但是只是 "after" 过去了一段时间,而不是 "exactly after" 过去了一段时间。因此,例如做类似的事情:
var secondsElapsed: TimeInterval = 0.0
let timeInitiated = Date()
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
secondsElapsed += 1
print("\(secondsElapsed) seconds should have passed but in reality \(Date().timeIntervalSince(timeInitiated)) second have passed")
}
你会发现两者并不相同,但非常接近。但是一旦我像这样添加一些额外的工作:
var secondsElapsed:TimeInterval = 0.0
让 timeInitiated = Date()
func countTo(_ end: Int) {
var string = ""
for i in 1...end {
string += String(i)
}
print("Just counted to string of lenght \(string.count)")
}
Timer.scheduledTimer(withTimeInterval: 1.0/60.0, repeats: true) { _ in
countTo(100000)
}
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
secondsElapsed += 1
print("\(secondsElapsed) seconds should have passed but in reality \(Date().timeIntervalSince(timeInitiated)) second have passed")
}
我们遇到类似“14.0 秒应该过去但实际上已经过去 19.17617702484131 秒”的情况。
我们让应用程序很忙,所以它没有时间正确计数。
在您的情况下,您需要使用以下两种解决方案之一:
- 如果您对经过的时间感兴趣,只需使用
timeIntervalSince
,如第一个代码片段中所示。
- 如果你需要确保每
N
秒触发一次,你应该优化你的代码,考虑多线程......但主要记住你只能接近 "every N
seconds",它不应该可以保证每 N
秒执行一次。
我在一些朋友的帮助下制作了这个应用程序。我真的不知道代码是如何工作的。
它基本上使用苹果铅笔记录数据(平板电脑上的时间、苹果铅笔的速度、笔划数等)。然而,随着时间的流逝和绘图的增多,计时器与实际时间不同步。
这个应用程序的目的是用于痴呆症研究,我让患者在平板电脑上画画,然后我收集相关信息。如果计时器发臭,我就无法进行研究了。
我试过禁用所有计时器,但延迟仍然一样。我有一种感觉,它与笔画的采样方式有关。我只需要一个笔画计数,我不需要它来显示每分钟的笔画(这是它目前正在做的)。我认为中风计数器可能是原因???
这是程序: https://drive.google.com/open?id=1lwzKwG7NLcX1qmE5yoxsdq5HICV2TNHm
class StrokeSegment {
var sampleBefore: StrokeSample?
var fromSample: StrokeSample!
var toSample: StrokeSample!
var sampleAfter: StrokeSample?
var fromSampleIndex: Int
var segmentUnitNormal: CGVector {
return segmentStrokeVector.normal!.normalized!
}
var fromSampleUnitNormal: CGVector {
return interpolatedNormalUnitVector(between: previousSegmentStrokeVector, and: segmentStrokeVector)
}
var toSampleUnitNormal: CGVector {
return interpolatedNormalUnitVector(between: segmentStrokeVector, and: nextSegmentStrokeVector)
}
var previousSegmentStrokeVector: CGVector {
if let sampleBefore = self.sampleBefore {
return fromSample.location - sampleBefore.location
} else {
return segmentStrokeVector
}
}
var segmentStrokeVector: CGVector {
return toSample.location - fromSample.location
}
var nextSegmentStrokeVector: CGVector {
if let sampleAfter = self.sampleAfter {
return sampleAfter.location - toSample.location
} else {
return segmentStrokeVector
}
}
init(sample: StrokeSample) {
self.sampleAfter = sample
self.fromSampleIndex = -2
}
@discardableResult
func advanceWithSample(incomingSample: StrokeSample?) -> Bool {
if let sampleAfter = self.sampleAfter {
self.sampleBefore = fromSample
self.fromSample = toSample
self.toSample = sampleAfter
self.sampleAfter = incomingSample
self.fromSampleIndex += 1
return true
}
return false
}
}
class StrokeSegmentIterator: IteratorProtocol {
private let stroke: Stroke
private var nextIndex: Int
private let sampleCount: Int
private let predictedSampleCount: Int
private var segment: StrokeSegment!
init(stroke: Stroke) {
self.stroke = stroke
nextIndex = 1
sampleCount = stroke.samples.count
predictedSampleCount = stroke.predictedSamples.count
if (predictedSampleCount + sampleCount) > 1 {
segment = StrokeSegment(sample: sampleAt(0)!)
segment.advanceWithSample(incomingSample: sampleAt(1))
}
}
func sampleAt(_ index: Int) -> StrokeSample? {
if index < sampleCount {
return stroke.samples[index]
}
let predictedIndex = index - sampleCount
if predictedIndex < predictedSampleCount {
return stroke.predictedSamples[predictedIndex]
} else {
return nil
}
}
func next() -> StrokeSegment? {
nextIndex += 1
if let segment = self.segment {
if segment.advanceWithSample(incomingSample: sampleAt(nextIndex)) {
return segment
}
}
return nil
}
}
例如 true 25 秒,应用程序显示总时间为 20 秒。
A Timer
不是计算经过时间的东西。它是一种用于在经过一段时间后触发执行的工具。但是只是 "after" 过去了一段时间,而不是 "exactly after" 过去了一段时间。因此,例如做类似的事情:
var secondsElapsed: TimeInterval = 0.0
let timeInitiated = Date()
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
secondsElapsed += 1
print("\(secondsElapsed) seconds should have passed but in reality \(Date().timeIntervalSince(timeInitiated)) second have passed")
}
你会发现两者并不相同,但非常接近。但是一旦我像这样添加一些额外的工作:
var secondsElapsed:TimeInterval = 0.0 让 timeInitiated = Date()
func countTo(_ end: Int) {
var string = ""
for i in 1...end {
string += String(i)
}
print("Just counted to string of lenght \(string.count)")
}
Timer.scheduledTimer(withTimeInterval: 1.0/60.0, repeats: true) { _ in
countTo(100000)
}
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
secondsElapsed += 1
print("\(secondsElapsed) seconds should have passed but in reality \(Date().timeIntervalSince(timeInitiated)) second have passed")
}
我们遇到类似“14.0 秒应该过去但实际上已经过去 19.17617702484131 秒”的情况。
我们让应用程序很忙,所以它没有时间正确计数。
在您的情况下,您需要使用以下两种解决方案之一:
- 如果您对经过的时间感兴趣,只需使用
timeIntervalSince
,如第一个代码片段中所示。 - 如果你需要确保每
N
秒触发一次,你应该优化你的代码,考虑多线程......但主要记住你只能接近 "everyN
seconds",它不应该可以保证每N
秒执行一次。