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 3 快照中使用 C 可变参数函数?