UIView 绘制函数 Swift 的可变参数

Posted

技术标签:

【中文标题】UIView 绘制函数 Swift 的可变参数【英文标题】:Variable Parameter for UIView draw function Swift 【发布时间】:2015-05-06 22:34:19 【问题描述】:

我的应用功能如下:

一天中的时间从 NSDate 中提取,并在我的 ViewController.swift 中的 updateTime 函数中分成组件:

import UIKit
import Foundation



class ViewController: UIViewController 



    func updateTime() 

        var date:NSDate = NSDate()
        var calendar:NSCalendar = NSCalendar.currentCalendar()
        var components:NSDateComponents = calendar.components(NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitSecond, fromDate: date)
        var hour = components.hour
        var minute = components.minute
        var seconds = components.second

        var time = "\(hour) : \(minute) : \(seconds)"
        println("\(hour)")




    


    override func viewDidLoad() 
        super.viewDidLoad()



        var timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)        




    



    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    



在 viewDidLoad 上,计时器开始,调用函数 updateTime() 来拉取 NSDate 并将其分成小时、分钟和秒部分。

使用应用程序 PaintCode 创建 Core Graphics 绘制方法,然后我创建了一个钟面,它绘制了 12 个单独的圆圈 - 最初的 12 个圆圈是 EMPTY 绘图。使用 NSDate 小时组件,我的系统试图确定需要用核心图形填充的 12 个空圆圈中有多少。使用计时器,我希望每秒更新此数据,以使核心图形绘制小时 UIView 指示器在用户在其屏幕上打开应用程序时保持最新。稍后我将对分钟和秒做同样的事情。

在我的应用程序设计中,每个小时、分钟和秒都会绘制一个额外的图形。我的想法(我可能想多了)导致我使用枚举根据 NSDate 报告的小时数绘制每个小时的圆圈,并携带该“HH”值以与订购绘图的个别情况相对应。分钟和秒刻度标记也是如此。

下面的这段代码 sn-p 来自我称之为 ClockFace01 的 UIView 文件,View Controller 中的 UIView 归入该文件。在函数 drawCanvas 中,我试图每秒从 updateTime() 函数的 component.hour 中获取一个整数变量,并以某种方式更新 drawRect 方法以使 UIView 时钟面保持最新。

    import UIKit



@IBDesignable
class ClockFace01: UIView 

    func updateTime() 

        func drawCanvas(canvas:Int) 
            switch canvas 

            case 00:




                //// EMPTY1 Drawing
                var eMPTY1Path = UIBezierPath(ovalInRect: CGRectMake(127, 49.47, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY1Path.lineWidth = 1
                eMPTY1Path.stroke()


                //// EMPTY2 Drawing
                var eMPTY2Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 71.98, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY2Path.lineWidth = 1
                eMPTY2Path.stroke()


                //// EMPTY3 Drawing
                var eMPTY3Path = UIBezierPath(ovalInRect: CGRectMake(157.75, 102.73, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY3Path.lineWidth = 1
                eMPTY3Path.stroke()


                //// EMPTY4 Drawing
                var eMPTY4Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 133.48, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY4Path.lineWidth = 1
                eMPTY4Path.stroke()


                //// EMPTY5 Drawing
                var eMPTY5Path = UIBezierPath(ovalInRect: CGRectMake(127, 155.99, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY5Path.lineWidth = 1
                eMPTY5Path.stroke()


                //// EMPTY6 Drawing
                var eMPTY6Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 164.23, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY6Path.lineWidth = 1
                eMPTY6Path.stroke()


                //// EMPTY7 Drawing
                var eMPTY7Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 155.99, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY7Path.lineWidth = 1
                eMPTY7Path.stroke()


                //// EMPTY8 Drawing
                var eMPTY8Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 133.48, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY8Path.lineWidth = 1
                eMPTY8Path.stroke()


                //// EMPTY9 Drawing
                var eMPTY9Path = UIBezierPath(ovalInRect: CGRectMake(34.75, 102.73, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY9Path.lineWidth = 1
                eMPTY9Path.stroke()


                //// EMPTY10 Drawing
                var eMPTY10Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 71.98, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY10Path.lineWidth = 1
                eMPTY10Path.stroke()


                //// EMPTY11 Drawing
                var eMPTY11Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 49.47, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY11Path.lineWidth = 1
                eMPTY11Path.stroke()

                //// EMPTY12 Drawing
                var eMPTY12Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 41.23, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY12Path.lineWidth = 1
                eMPTY12Path.stroke()

            case 01, 13:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR1 Drawing
                var hOUR1Path = UIBezierPath(ovalInRect: CGRectMake(127, 49.47, 24, 24))
                color0.setFill()
                hOUR1Path.fill()

            case 02, 14:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR2 Drawing
                var hOUR2Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 71.98, 24, 24))
                color0.setFill()
                hOUR2Path.fill()

            case 03, 15:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR3 Drawing
                var hOUR3Path = UIBezierPath(ovalInRect: CGRectMake(157.75, 102.73, 24, 24))
                color0.setFill()
                hOUR3Path.fill()

            case 04, 16:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR4 Drawing
                var hOUR4Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 133.48, 24, 24))
                color0.setFill()
                hOUR4Path.fill()

            case 05, 17:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR5 Drawing
                var hOUR5Path = UIBezierPath(ovalInRect: CGRectMake(127, 155.99, 24, 24))
                color0.setFill()
                hOUR5Path.fill()

            case 06, 18:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR6 Drawing
                var hOUR6Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 164.23, 24, 24))
                color0.setFill()
                hOUR6Path.fill()

            case 07, 19:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR7 Drawing
                var hOUR7Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 155.99, 24, 24))
                color0.setFill()
                hOUR7Path.fill()

            case 08, 20:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR8 Drawing
                var hOUR8Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 133.48, 24, 24))
                color0.setFill()
                hOUR8Path.fill()

            case 09, 21:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR9 Drawing
                var hOUR9Path = UIBezierPath(ovalInRect: CGRectMake(34.75, 102.73, 24, 24))
                color0.setFill()
                hOUR9Path.fill()

            case 10, 22:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR10 Drawing
                var hOUR10Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 71.98, 24, 24))
                color0.setFill()
                hOUR10Path.fill()

            case 11, 23:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR11 Drawing
                var hOUR11Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 49.47, 24, 24))
                color0.setFill()
                hOUR11Path.fill()

            case 12, 24:

                //// Color Declarations
                let color0 = UIColor(red: 0.894, green: 0.000, blue: 0.476, alpha: 1.000)

                //// HOUR12 Drawing
                var hOUR12Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 41.23, 24, 24))
                color0.setFill()
                hOUR12Path.fill()

            default:
                //// EMPTY12 Drawing
                var eMPTY12Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 41.23, 24, 24))
                ClockStyleKit.color1.setStroke()
                eMPTY12Path.lineWidth = 1
                eMPTY12Path.stroke()


            
        

        var date:NSDate = NSDate()
        var calendar:NSCalendar = NSCalendar.currentCalendar()
        var components:NSDateComponents = calendar.components(NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitSecond, fromDate: date)
        var hour = components.hour
        var minute = components.minute
        var seconds = components.second

        var time = "\(hour) : \(minute) : \(seconds)"
        println("\(hour)")



    


    override func drawRect(rect: CGRect) 

        var timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)



        //// EMPTY12 Drawing
        var eMPTY12Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 41.23, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY12Path.lineWidth = 1
        eMPTY12Path.stroke()


        //// EMPTY1 Drawing
        var eMPTY1Path = UIBezierPath(ovalInRect: CGRectMake(127, 49.47, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY1Path.lineWidth = 1
        eMPTY1Path.stroke()


        //// EMPTY2 Drawing
        var eMPTY2Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 71.98, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY2Path.lineWidth = 1
        eMPTY2Path.stroke()


        //// EMPTY3 Drawing
        var eMPTY3Path = UIBezierPath(ovalInRect: CGRectMake(157.75, 102.73, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY3Path.lineWidth = 1
        eMPTY3Path.stroke()


        //// EMPTY4 Drawing
        var eMPTY4Path = UIBezierPath(ovalInRect: CGRectMake(149.51, 133.48, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY4Path.lineWidth = 1
        eMPTY4Path.stroke()


        //// EMPTY5 Drawing
        var eMPTY5Path = UIBezierPath(ovalInRect: CGRectMake(127, 155.99, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY5Path.lineWidth = 1
        eMPTY5Path.stroke()


        //// EMPTY6 Drawing
        var eMPTY6Path = UIBezierPath(ovalInRect: CGRectMake(96.25, 164.23, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY6Path.lineWidth = 1
        eMPTY6Path.stroke()


        //// EMPTY7 Drawing
        var eMPTY7Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 155.99, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY7Path.lineWidth = 1
        eMPTY7Path.stroke()


        //// EMPTY8 Drawing
        var eMPTY8Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 133.48, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY8Path.lineWidth = 1
        eMPTY8Path.stroke()


        //// EMPTY9 Drawing
        var eMPTY9Path = UIBezierPath(ovalInRect: CGRectMake(34.75, 102.73, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY9Path.lineWidth = 1
        eMPTY9Path.stroke()


        //// EMPTY10 Drawing
        var eMPTY10Path = UIBezierPath(ovalInRect: CGRectMake(42.99, 71.98, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY10Path.lineWidth = 1
        eMPTY10Path.stroke()


        //// EMPTY11 Drawing
        var eMPTY11Path = UIBezierPath(ovalInRect: CGRectMake(65.5, 49.47, 24, 24))
        ClockStyleKit.color1.setStroke()
        eMPTY11Path.lineWidth = 1
        eMPTY11Path.stroke()
    

在上面

【问题讨论】:

你的程序“不喜欢那样”是什么意思?您是否收到编译器错误?崩溃?或者它只是没有像您期望的那样绘制? 第二次@Cadin 的评论:您确实需要提供更多信息。究竟发生了什么或没有发生什么不应该/不应该发生? 【参考方案1】:

当系统调用drawRect() 时,系统会告诉UIView 绘制系统。你是从drawRect() 调用你的drawCanvas() 方法还是直接从其他地方调用它(比如你的updateTime() 方法)?

如果您由于(系统)调用drawRect() 而没有绘图,那是您的问题。要么在drawRect() 内绘图,要么通过从drawRect() 实现中调用的方法。你告诉系统你的视图是“脏的”,当它需要重绘时发送setNeedsDisplay()到你的视图,让系统在方便的时候调用你的视图的drawRect()

提示:系统比您更清楚何时重绘视图或视图的一部分实际上是最好的,尤其是因为它可能需要将透明/半透明部分与“后面的视图”混合”或“在它前面”。系统知道标记自己进行重绘的所有视图的哪些区域(全部或子矩形)并优化重绘它们,以便它可以正确混合而无需要求所有视图(脏或不脏)重绘自己。跟踪所有这些不是您的工作(也不是您的业务);让您的自定义视图尽可能高效地绘制自身只是您的工作。为此,您可能只想将某个矩形标记为需要显示(通过setNeedsDisplayInRect()),如果整个事物不需要重绘等。但绝对避免与系统发生冲突。使用适当的绘图挂钩和标记。

在您的情况下,您可能希望在 updateTime() 方法结束时调用 setNeedsDisplay()

基于 cmets 的更新

我想我看到了你的问题。

    不要从您的drawRect() 方法触发更多绘图(通过创建计时器)。 您的updateTime() 方法只应该这样做:更新时间。分解当前日期并在计时器触发时更新视图的内部状态(调用您的方法),然后通过setNeedsDisplay() 标记显示。就是这样。 完全摆脱您的drawCanvas() 方法;这只是令人困惑的事情。将其内容移动到drawRect() 并保留在那里,除非您有充分的理由将其划分为子例程。它足够短,现在你不需要。 设置您的计时器一次。 所有这些都在您的视图类中。

【讨论】:

这基本上就是我卡住的地方。当我在我的覆盖 drawRect() 方法中放置绘图方法时,它可以工作 - 我在我的 UIView 中获取图像。我想根据我从 updateTime() 方法收集的时间变量在我的 UIView 中绘制更多图像。我希望它每 1 秒更新一次,使用我的 NSTimer。每小时、每分钟和每秒钟将代表一组不同的绘制图像,以直观地表示时间。 所以回到您的问题中的 cmets:我们需要更多信息。不应该发生的事情,或者不应该发生的事情?你是说计时器永远不会触发? 您确实需要提供尽可能多的详细信息,否则您的问题可能会被否决。 我的主要困惑是在哪里放置“var timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTime"), userInfo: nil, repeats: true)”与 updateTime() 方法相关的行。计时器和 updateTime() 方法是否属于附加到我的 UIView 的 UIView 类?现在,每当我尝试使用 drawCanvas(hour) 传递那个小时整数时,我都会收到很多无效的上下文错误。我的 drawCanvas(canvas:Int) 函数是否需要嵌套在我的 updateTime() 函数中、类的顶层或其他地方? 错误示例:5 月 7 日 18:33:18 Alexs-Mac-Pro.home NookaTime[8315] :CGContextDrawPath:无效上下文 0x0。这是一个严重的错误。此应用程序或它使用的库正在使用无效的上下文,从而导致系统稳定性和可靠性的整体下降。此通知是出于礼貌:请解决此问题。这将成为即将到来的更新中的致命错误。

以上是关于UIView 绘制函数 Swift 的可变参数的主要内容,如果未能解决你的问题,请参考以下文章

swift中函数可变参数的使用

有没有办法在最新的 Swift 3 快照中使用 C 可变参数函数?

iOS开发:Swift 调用 Objective-C 的可变参数函数

带有可变参数的 Swift 和 C 回调

Swift 错误 - 不可变值 '' 可能不会传入输出

Swift基础知识碎片