Ios 按下按钮,使用数组中的值更改CGRect的颜色。如何做到这一点?
你好,Stack Overflow社区 我正在使用Swift 3.0进行Xcode 8.0中的一个项目。我正在尝试开发的应用程序是一个生命计数器,用于我班期末专题的聚会。第一个图像是当用户从应用程序的主屏幕导航到life counter屏幕时屏幕上显示的图像 下面是一个图像,显示用户从应用程序主屏幕导航到此视图时看到的内容 您将在照片中看到,有一个名为lifeCounterViewController的视图控制器,该视图控制器内还有两个其他视图。这些视图分别命名为player1View和player2View 在这些视图中的每个视图中都绘制了一个矩形。它是CGRect类的成员。以下代码来自cocoa touch swift文件。它包含覆盖draw函数的代码Ios 按下按钮,使用数组中的值更改CGRect的颜色。如何做到这一点?,ios,arrays,swift,cocoa,xcode8,Ios,Arrays,Swift,Cocoa,Xcode8,你好,Stack Overflow社区 我正在使用Swift 3.0进行Xcode 8.0中的一个项目。我正在尝试开发的应用程序是一个生命计数器,用于我班期末专题的聚会。第一个图像是当用户从应用程序的主屏幕导航到life counter屏幕时屏幕上显示的图像 下面是一个图像,显示用户从应用程序主屏幕导航到此视图时看到的内容 您将在照片中看到,有一个名为lifeCounterViewController的视图控制器,该视图控制器内还有两个其他视图。这些视图分别命名为player1View和play
//
// player1LifeCounterDrawing.swift
import UIKit
class player1LifeCounterDrawing: UIView {
let MagicRed = UIColor.init(red: 247.0/255.0, green: 170.0/255.0, blue: 146.0/255.0, alpha: 1.0)
let Purple = UIColor.init(red: 102.0/255.0, green: 0.0/255.0, blue: 204.0/255.0, alpha: 1.0)
let Magenta = UIColor.init(red: 102.0/255.0, green: 0.0/255.0, blue: 51.0/255.0, alpha: 1.0)
let Orange = UIColor.init(red: 255.0/255.0, green: 166.0/255.0, blue: 0.0/255.0, alpha: 1.0)
let Plum = UIColor.init(red: 179.0/255.0, green: 0.0/255.0, blue: 89.0/255.0, alpha: 1.0)
let Emerald = UIColor.init(red: 0.0/255.0, green: 204.0/255.0, blue: 102.0/255.0, alpha: 1.0)
let Teal = UIColor.init(red: 0.0/255.0, green: 153.0/255.0, blue: 153.0/255.0, alpha: 1.0)
let SlateBlue = UIColor.init(red: 0.0/255.0, green: 153.0/255.0, blue: 255.0/255.0, alpha: 1.0)
let Forest = UIColor.init(red: 51.0/255.0, green: 153.0/255.0, blue: 51.0/255.0, alpha: 1.0)
let NavyBlue = UIColor.init(red: 51.0/255.0, green: 102.0/255.0, blue: 153.0/255.0, alpha: 1.0)
let MagicBlue = UIColor.init(red: 157.0/255.0, green: 216.0/255.0, blue: 255.0/255.0, alpha: 1.0)
let MagicBlack = UIColor.init(red: 194.0/255.0, green: 179.0/255.0, blue: 180.0/255.0, alpha: 1.0)
let MagicGreen = UIColor.init(red: 141.0/255.0, green: 203.0/255.0, blue: 158.0/255.0, alpha: 1.0)
var colorLibrary = [UIColor]()
var index = 0
func fillLibrary(library: [UIColor]) -> [UIColor]{
let capture = [UIColor](arrayLiteral: MagicRed, MagicBlue, MagicGreen, MagicBlack, Purple, Magenta, Orange, Plum, Emerald, Teal, SlateBlue, Forest, NavyBlue )
return capture
}
func calling(){
colorLibrary = fillLibrary(library: colorLibrary)
}
override func draw(_ rect: CGRect){
calling()
let lineWidth = CGFloat(3.0)
let rectangle = CGRect(
origin: CGPoint(x: 0, y: 0),
size: CGSize(width: bounds.maxX, height: bounds.maxY)
)
let rectPath = UIBezierPath(
roundedRect: rectangle,
byRoundingCorners: UIRectCorner(rawValue: 0),
cornerRadii: CGSize(width: 0, height: 0)
)
rectPath.lineWidth = lineWidth
rectPath.lineCapStyle = CGLineCap.square
if index >= colorLibrary.count{
index = 0
}
colorLibrary[index].setFill()
colorLibrary[index].setStroke()
index += 1
rectPath.stroke()
rectPath.fill()
}
}
现在这个解决方案是可行的,但它是丑陋的。正如您所看到的,每当调用draw函数时,都会重新初始化名为colorLibrary的数组
我担心这是一个巨大的内存浪费,我需要帮助找到一个解决方案,这样每当用户按下按钮时,就会调用setNeedsDisplay(),并且setStroke()和setFill()方法的颜色会改变,以反映在[index]的colorLibrary中表示的颜色
如何做到这一点
还要记住,建议的解决方案需要同时适用于player1View和player2View。我只在player1View中显示了代码,但在player2View中它是相同的,只是标识哪个视图已更改的编号
同样,在我看来,这是一个很大的内存浪费,我想在周二之前把它修好,因为那是我需要向全班同学提交申请的时候。如果到那时我还不能得到一个有效的解决方案,我就使用这个当前的解决方案。您已经设置好了所有内容,颜色数组的实例变量等,但是您在每个绘制周期都重新创建这个数组,而除了第一次可能不需要 考虑在draw(:)开始时更改对calling()函数的调用,以便可以重用以前的颜色数组。这不会节省任何内存,但会减少不必要的重复分配,显著提高效率。最好的
if colorLibrary.count == 0 {
calling()
}
更改绘图代码内部的索引将导致每次绘图时增加(设备旋转->重画,转到背景并再次打开->重画,…)。但你只想在按下按钮的时候做 我的建议是将颜色和索引功能提取到一个专门的类中(因为它是独立于ui的逻辑,视图应该只绘制一些东西,而不是更多)。您还可以使用延迟加载来避免创建太多的对象 e、 g:
final class ColorLibrary {
// increase index logic (including overflow handling)
private var currentIndex: Int = 0
func increaseIndex() {
if currentIndex == colors.count - 1 {
currentIndex = 0
} else {
currentIndex += 1
}
}
// lazy loading: color array will be created only once and only if needed
private var _colors: [UIColor]?
private var colors: [UIColor] {
if _colors == nil {
_colors = [
UIColor.init(red: 247.0/255.0, green: 170.0/255.0, blue: 146.0/255.0, alpha: 1.0),
UIColor.init(red: 102.0/255.0, green: 0.0/255.0, blue: 204.0/255.0, alpha: 1.0),
UIColor.init(red: 102.0/255.0, green: 0.0/255.0, blue: 51.0/255.0, alpha: 1.0),
UIColor.init(red: 255.0/255.0, green: 166.0/255.0, blue: 0.0/255.0, alpha: 1.0),
UIColor.init(red: 179.0/255.0, green: 0.0/255.0, blue: 89.0/255.0, alpha: 1.0),
UIColor.init(red: 0.0/255.0, green: 204.0/255.0, blue: 102.0/255.0, alpha: 1.0),
UIColor.init(red: 0.0/255.0, green: 153.0/255.0, blue: 153.0/255.0, alpha: 1.0),
UIColor.init(red: 0.0/255.0, green: 153.0/255.0, blue: 255.0/255.0, alpha: 1.0),
UIColor.init(red: 51.0/255.0, green: 153.0/255.0, blue: 51.0/255.0, alpha: 1.0),
UIColor.init(red: 51.0/255.0, green: 102.0/255.0, blue: 153.0/255.0, alpha: 1.0),
UIColor.init(red: 157.0/255.0, green: 216.0/255.0, blue: 255.0/255.0, alpha: 1.0),
UIColor.init(red: 194.0/255.0, green: 179.0/255.0, blue: 180.0/255.0, alpha: 1.0),
UIColor.init(red: 141.0/255.0, green: 203.0/255.0, blue: 158.0/255.0, alpha: 1.0)
]
}
return _colors!
}
var currentColor: UIColor {
get { return colors[currentIndex] }
}
}
现在可以通过以下方式在视图内部构造对象:
private(set) var colorLibrary: ColorLibrary = ColorLibrary()
访问绘图内部的颜色:
colorLibrary.currentColor.setFill()
按下按钮后,您现在可以呼叫:
cardView.colorLibrary.increaseIndex()
cardView.setNeedsLayout()
Swift支持惰性初始化,以避免您担心的重复。您可以将颜色库
替换为:
lazy var colorLibrary: [UIColor] = [self.MagicRed, self.MagicBlue, self.MagicGreen,
self.MagicBlack, self.Purple, self.Magenta,
self.Orange, self.Plum, self.Emerald, self.Teal,
self.SlateBlue, self.Forest, self.NavyBlue]
注意:这使用数组文字([
..]
)
现在,变量colorLibrary
将在首次使用时进行初始化,并保留其值
(准确地说,变量可以多次初始化,特别是在多线程情况下,但这不需要您担心。)
另一方面,您可以使用如下代码管理索引:
if index >= colorLibrary.count{
index = 0
}
// use index...
index += 1
管理这样的索引的常用方法是使用模块化算法;这是一个环绕的算术,在最大值上加一,得到最小值。(对于一个真实世界的例子,考虑到电表上的里程表或计数器,在达到这9个周期后,所有的0个周期)
可以使用mod运算符%
执行模运算,为此,可以将其视为返回除法的剩余部分。上述代码大纲变为:
// use index...
index = (index + 1) % colorLibrary.count
并且避免使用if
HTH我已将此标记为正确的解决方案。谢谢你抽出时间。我非常喜欢学习惰性初始化,以及如何对索引使用模数除法。与我班上的其他人分享了这个解决方案,他们认为它很棒!