ios - 如何使用 NSTimer 在 UIView 中绘图

标签 ios swift uiview nstimer

我正在尝试开发的应用程序的一个部分需要显示一组图像,而用户在显示周期期间无需与手机交互。用户开始显示序列,但不需要告诉手机何时停止。该应用程序还需要能够在每个显示周期之间捕获图像。我的意思是手机显示一张图像,然后拍摄照片并保存,然后显示下一张图像,如此循环下去。

我对图像捕获部分有很好的理解,但我正在努力解决如何以上述方式显示我的图像集。据我所知,实现这一点的困难之一是 iPhone 在一个显示周期上更新 View 并在执行时编译所有代码,因此很难让两者相互等待。

我尝试使用 NSTimer 调用 UIView 来更新我的特定图像,但图像无法正确绘制。我正在使用 Core Graphics 以越来越频繁的频率绘制条形或白色和黑色。我认为创建和播放具有正确图案序列的影片不会起作用,因为我还需要能够告诉 iPhone 在每次显示图案时捕获图像。

非常感谢任何想法或建议!

我的 UIViewController:

import UIKit

class ViewController: UIViewController, UINavigationControllerDelegate {

// MARK: Properties
var orientation = "Vertical"
var numberOfBarPairs = UInt64(1)
var maximumNumberOfBarPairs = UInt64()
var binaryPattern = BinaryPattern()
var timer = NSTimer()

// Hide the status bar so the image displayed is full screen
var statusBarIsHidden = true

override func viewDidLoad() {
    super.viewDidLoad()
}

// MARK: Actions
@IBAction func displayBinaryPattern(sender: UIButton) {
    // Initiate the phase display

    // Capture the view's frame size and location
    let viewWidth = view.frame.width
    let viewHeight = view.frame.height
    //let viewSize = CGFloat(20)
    let viewOrigin = view.frame.origin

    // Set the frame that displays the binary patterns
    let frame = CGRectMake(viewOrigin.x, viewOrigin.y, viewWidth, viewHeight)

    // Set maximum number of bar pairs based on frame size
    maximumNumberOfBarPairs = 128 //Int(viewSize)/2

    // Instance a binary pattern and add it as a subview to the main view
    binaryPattern = BinaryPattern(frame: frame)

    // set display interval
    let displayInterval = 5.0

    // Set a timer to call drawBarPairs every interval
    timer = NSTimer.scheduledTimerWithTimeInterval(displayInterval, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)
}

func updateView() {
    numberOfBarPairs = numberOfBarPairs*2
    print("\(orientation), \(numberOfBarPairs)")

    view.addSubview(binaryPattern)

    // Cal the draw view
    binaryPattern.orientation = orientation
    binaryPattern.numberOfBarPairs = numberOfBarPairs

    // Stop the display when we reach a termination condition
    if numberOfBarPairs == maximumNumberOfBarPairs && orientation == "Horizontal" {
        // Stop the timer
        timer.invalidate()
    }

    // Change the orientaiton of the bar pairs when the number counter reaches the maximum
    if numberOfBarPairs == maximumNumberOfBarPairs && orientation == "Vertical" {
        orientation = "Horizontal"
        numberOfBarPairs = 0
    }
  }
}

我的 UIView 绘制图案:

import UIKit

class BinaryPattern: UIView {

// MARK: Properties
var numberOfBarPairs: UInt64 {
    didSet {
        print("Bars Set")
        setNeedsDisplay()
    }
}

var orientation: String {
    didSet {
        print("orientation set")
        setNeedsDisplay()
    }
}

override init(frame: CGRect) {
    self.numberOfBarPairs = 1
    self.orientation = "Vertical"
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
    self.numberOfBarPairs = 1
    self.orientation = "Vertical"
    super.init(coder: aDecoder)!
}

override func drawRect(rect: CGRect) {

    // Obtains the current graphics context. Think of a graphics context as a canvas. In this case, the canvas is the View that we will be working with, but there are other types of contexts, such as an offscreen buffer that we later turn into an image. Note that contexts are stateful, or a value will remain that value until it is set with a method.
    let context = UIGraphicsGetCurrentContext()

    // Disable anti-aliasing, so pixel boundarys are shown jagged
    CGContextSetShouldAntialias(context, false)

    // Query the view frame size to draw the binary pattern within
    let frameHeight: CGFloat = 256
    let frameWidth: CGFloat = 256

    // Define white and black colors
    let blackColor: UIColor = UIColor.blackColor()
    let whiteColor: UIColor = UIColor.whiteColor()

    // Determine if bars should be vertical or horizontal
    if self.orientation == "Horizontal" {
        let barWidth = frameWidth
        let barHeight = frameHeight/CGFloat(2*self.numberOfBarPairs)

        // Generate the bar pairs and fill them with appropriate colors
     //   for bar in 1...self.numberOfBarPairs {
     //       let yOrigin1 = 2*(CGFloat(bar)-1)*barHeight
     //       let yOrigin2 = (2*CGFloat(bar)-1)*barHeight
     //       let xOrigin: CGFloat = 0

        let xOrigin: CGFloat = 0
        let yOrigin1: CGFloat = barHeight
        let yOrigin2: CGFloat = 0

            CGContextSetFillColorWithColor(context, blackColor.CGColor)
            CGContextFillRect(context, CGRectMake(xOrigin, yOrigin1, barWidth, barHeight))

            CGContextSetFillColorWithColor(context, whiteColor.CGColor)
            CGContextFillRect(context, CGRectMake(xOrigin, yOrigin2, barWidth, barHeight))
       // }
    }
    else {
        // Calculate the width of each bar by dividing the outer frame width by twice the number of bar pairs
        let barWidth = frameWidth/CGFloat(2*self.numberOfBarPairs)
        let barHeight = frameHeight

        print("Bar Width: \(barWidth), Bar Height: \(barHeight)\n")

        // Generate the bar pairs and fill them with appropriate colors
        for bar in 1...self.numberOfBarPairs {
        //    let xOrigin1 = 2*(CGFloat(bar)-1)*barWidth
            let xOrigin2 = (2*CGFloat(bar)-1)*barWidth
            let yOrigin: CGFloat = 0

            print("x Origin: \(xOrigin2)")

        //let xOrigin1 = barWidth
        //let xOrigin2: CGFloat = 50
        //let yOrigin: CGFloat = 0
            //CGContextSetFillColorWithColor(context, blackColor.CGColor)
            //CGContextFillRect(context, CGRectMake(xOrigin1, yOrigin, barWidth, barHeight))

            CGContextSetFillColorWithColor(context, whiteColor.CGColor)

            CGContextFillRect(context, CGRectMake(xOrigin2, yOrigin, barWidth, barHeight))

        }
    }
  }
}

最佳答案

计时器应该调用 View 的 setNeedsDisplay。然后 View 的drawRect将绘制 View 的当前状态。

关于ios - 如何使用 NSTimer 在 UIView 中绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34494792/

相关文章:

ios - NSOperationQueue添加后台线程操作

ios - 如何更改 iOS 7 中的 UISearchBar

ios - Mapbox 注释标注

iphone - UIImageView 单元格 contentView 的 View 之一未与其父 View 一起扩展

ios - 如何在 Objective-C/iOS 中的客户端上创建虚拟 JSON 数据?

ios - 计时器不重复(Grand Central Dispatch)

ios - UiTextfield-首字母必须为0

swift - 设置自定义字体而不使用属性文本

objective-c - UIViewController 中的 UIView 或更好的方法吗?

ios - 更改父(UIView)大小时布局不会更改