简体   繁体   中英

How to refresh the screen when I draw a line for realtime data

In my current swift program, one function display real time acceleration data on screen with line. So I used class drawRect . As a result, the acceleration figure can be drawn, but not real time everytime I refresh it (turn down the App and reopen). I know that I should use some method such as setNeedsDisplay() to redraw it. But it was no use. Maybe I wrote it in a wrong way. Here is my code:

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
            })

        }
    }   
}

OK, here's some rewritten code... the important point here is that you have to isolate your drawing code from the updates:

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
}   

Please note I did this very quickly but make sure that you call the function "startMonitoring" which should then get the updates from the accelerometer, save a couple of relevant variables (that you were using) and then call setNeedsDisplay. And at some point, drawRect will be called and use the variables that you have saved to correctly draw.

The drawRect method is called as a result of you issuing a setNeedsDisplay call. The setNeedsDisplay tell the system that you want to update the drawing and at some point in the future, the system will then call the drawRect method (to do that update).

So if you have a routine that gets called when your underlying data is changed, THEN issue the setNeedsDisplay call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM