Как обновить экран, когда я рисую линию для данных в реальном времени

В моей текущей программе swift одна функция отображает данные ускорения в реальном времени на экране в виде линии. Поэтому я использовал класс drawRect, В результате, график ускорения может быть нарисован, но не в режиме реального времени каждый раз, когда я обновляю его (выключите приложение и снова откройте). Я знаю, что я должен использовать какой-то метод, такой как setNeedsDisplay() перерисовать это. Но это было бесполезно. Возможно я написал это неправильно. Вот мой код:

import UIKit

import CoreMotion

class draw: UIView, UIAccelerometerDelegate {

     var motionManager = CMMotionManager()

     override func drawRect(rect: CGRect) {

         motionManager.deviceMotionUpdateInterval = 0.1

        var acc_x: Double = 0.0

        var temp_x: Double = 0.0

        var i: CGFloat = 0

        var accLine_x = UIGraphicsGetCurrentContext()

        if(motionManager.deviceMotionAvailable) {

            var queue = NSOperationQueue.mainQueue()

            motionManager.startDeviceMotionUpdatesToQueue(queue, withHandler: {
                (deviceMotion: CMDeviceMotion!, error: NSError!) in

                temp_x = acc_x

                acc_x = deviceMotion.userAcceleration.x

                CGContextSetLineWidth(accLine_x, 2)
                CGContextSetStrokeColorWithColor(accLine_x, UIColor.redColor().CGColor)
                CGContextMoveToPoint(accLine_x, i + 10, self.screenHeight * 436 + CGFloat(temp_x * 100))
                CGContextAddLineToPoint(accLine_x, i + 13, self.screenHeight * 436 + CGFloat(acc_x * 100))
                CGContextStrokePath(accLine_x)

                i = (i + 3) % 320
            })

        }
    }   
}

2 ответа

Решение

Хорошо, вот некоторый переписанный код... важно отметить, что вы должны изолировать код чертежа от обновлений:

var acc_x : Double = 0.0
var temp_x : Double = 0.0
var i: CGFloat = 0

func startMonitoring() {

    motionManager.deviceMotionUpdateInterval = 0.1
    if(motionManager.deviceMotionAvailable) {

        var queue = NSOperationQueue.mainQueue()

        motionManager.startDeviceMotionUpdatesToQueue(queue, withHandler: {
            (deviceMotion: CMDeviceMotion!, error: NSError!) in

            temp_x = acc_x
            acc_x = deviceMotion.userAcceleration.x

            // update things here
            self.setNeedsDisplay()
        })

    }

}

override func drawRect(rect: CGRect) {

    var accLine_x = UIGraphicsGetCurrentContext()

    CGContextSetLineWidth(accLine_x, 2)
    CGContextSetStrokeColorWithColor(accLine_x, UIColor.redColor().CGColor)
    CGContextMoveToPoint(accLine_x, i + 10, self.screenHeight * 436 + CGFloat(temp_x * 100))
    CGContextAddLineToPoint(accLine_x, i + 13, self.screenHeight * 436 + CGFloat(acc_x * 100))
    CGContextStrokePath(accLine_x)

    i = (i + 3) % 320
}   

Обратите внимание, что я сделал это очень быстро, но убедитесь, что вы вызываете функцию "startMonitoring", которая должна затем получать обновления от акселерометра, сохранять пару соответствующих переменных (которые вы использовали) и затем вызывать setNeedsDisplay. И в какой-то момент будет вызываться drawRect и использовать переменные, которые вы сохранили, для правильного рисования.

Метод drawRect вызывается в результате того, что вы вызвали вызов setNeedsDisplay. SetNeedsDisplay сообщает системе, что вы хотите обновить чертеж, и в какой-то момент в будущем система вызовет метод drawRect (для этого обновления).

Поэтому, если у вас есть подпрограмма, которая вызывается при изменении базовых данных, ТОГДА выполните вызов setNeedsDisplay.

Другие вопросы по тегам