Ios 按下按钮,使用数组中的值更改CGRect的颜色。如何做到这一点?

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

你好,Stack Overflow社区

我正在使用Swift 3.0进行Xcode 8.0中的一个项目。我正在尝试开发的应用程序是一个生命计数器,用于我班期末专题的聚会。第一个图像是当用户从应用程序的主屏幕导航到life counter屏幕时屏幕上显示的图像

下面是一个图像,显示用户从应用程序主屏幕导航到此视图时看到的内容

您将在照片中看到,有一个名为lifeCounterViewController的视图控制器,该视图控制器内还有两个其他视图。这些视图分别命名为player1View和player2View

在这些视图中的每个视图中都绘制了一个矩形。它是CGRect类的成员。以下代码来自cocoa touch swift文件。它包含覆盖draw函数的代码

//
//  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

我已将此标记为正确的解决方案。谢谢你抽出时间。我非常喜欢学习惰性初始化,以及如何对索引使用模数除法。与我班上的其他人分享了这个解决方案,他们认为它很棒!