无法获取UIView的子类来停止显示[swift]

时间:2016-03-12 16:55:19

标签: ios xcode swift uiview swift2

我想在我的代码中为某个事件举行庆祝活动。所以我从GitHub(https://github.com/sudeepag/SAConfettiView)采取了一个快速的纸屑叠加,并试图在我的项目中使用它。基本上,如果发生某个事件,它会启动NSTimer。我还定义了showAlertdismissAlert,用于在UIAlertView上弹出无按钮消息,说Congrats!。当计时器第一次勾选confettitime(从0开始)时,它开始五彩纸屑覆盖(成功)。然后,在第三个刻度,它激活showAlert。弹出消息。它在计时器的第七个刻度处成功解除dismissAlert。但我不能让隐藏/五彩纸屑消失。根据GitHub项目中的说明,我打电话给confettiView.stopConfetti()让它停下来!但它只是继续显示五彩纸屑,冻结我的UI。我试过删除通知(没有效果),显着改变五彩纸屑代码(没有效果),我只是找不到隐藏叠加五彩纸屑视图的方法。

我按照GitHub项目中的Manual Installation指示,将图像资源和SAConfettiView.swift添加到我的Swift XCode项目中。我不得不更改几个代码位,因为它们崩溃了(就像这条评论说:https://github.com/sudeepag/SAConfettiView/pull/6),所以也许这会影响它?

这是SAConfettiView的代码,它是GitHub项目的产物:

import UIKit
import QuartzCore

public class SAConfettiView: UIView {

public enum ConfettiType {
    case Confetti
    case Triangle
    case Star
    case Diamond
    case Image(UIImage)
}

var emitter: CAEmitterLayer!
public var colors: [UIColor]!
public var intensity: Float!
public var type: ConfettiType!
private var active :Bool!

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

public override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}

func setup() {
    colors = [UIColor(red:0.95, green:0.40, blue:0.27, alpha:1.0),
        UIColor(red:1.00, green:0.78, blue:0.36, alpha:1.0),
        UIColor(red:0.48, green:0.78, blue:0.64, alpha:1.0),
        UIColor(red:0.30, green:0.76, blue:0.85, alpha:1.0),
        UIColor(red:0.58, green:0.39, blue:0.55, alpha:1.0)]
    intensity = 0.5
    type = .Confetti
    active = false
}

public func startConfetti() {
    emitter = CAEmitterLayer()

    emitter.emitterPosition = CGPoint(x: frame.size.width / 2.0, y: 0)
    emitter.emitterShape = kCAEmitterLayerLine
    emitter.emitterSize = CGSize(width: frame.size.width, height: 1)

    var cells = [CAEmitterCell]()
    for color in colors {
        cells.append(confettiWithColor(color))
    }

    emitter.emitterCells = cells
    layer.addSublayer(emitter)
    active = true
}

public func stopConfetti() {
    emitter?.birthRate = 0
    active = false
}

func imageForType(type: ConfettiType) -> UIImage? {
    print(type)

    var fileName: String!

    switch type {
    case .Confetti:
        fileName = "Confetti"
    case .Triangle:
        fileName = "triangle"
    case .Star:
        fileName = "star"
    case .Diamond:
        fileName = "diamond"
    case let .Image(customImage):
        return customImage
    }

    print(type)


    return UIImage(imageLiteral: "\(type)")
}

func confettiWithColor(color: UIColor) -> CAEmitterCell {
    let confetti = CAEmitterCell()
    confetti.birthRate = 6.0 * intensity
    confetti.lifetime = 14.0 * intensity
    confetti.lifetimeRange = 0
    confetti.color = color.CGColor
    confetti.velocity = CGFloat(350.0 * intensity)
    confetti.velocityRange = CGFloat(80.0 * intensity)
    confetti.emissionLongitude = CGFloat(M_PI)
    confetti.emissionRange = CGFloat(M_PI_4)
    confetti.spin = CGFloat(3.5 * intensity)
    confetti.spinRange = CGFloat(4.0 * intensity)
    confetti.scaleRange = CGFloat(intensity)
    confetti.scaleSpeed = CGFloat(-0.1 * intensity)
    confetti.contents = imageForType(type)!.CGImage
    return confetti
}

public func isActive() -> Bool {
    return self.active
}
}

这是我项目中的相关代码,我称之为五彩纸屑:

var confettitimer = NSTimer()
var confettitime = 0
var alreadyconfettied = false

func confetti() {
confettitime++ 
let confettiView = SAConfettiView(frame: self.view.bounds)
self.view.addSubview(confettiView)
if confettitime == 1 {
   confettiView.type = .Confetti
   confettiView.startConfetti()
   alreadyconfettied = true
 }
if confettitime == 3 {
   showAlert2()
 }
if confettitime == 7 {
   dismissAlert2()
}
if confettitime == 10 {
   confettiView.stopConfetti()
   lp.confettitimer.invalidate()
   lp.confettitime = 0
}
}

if event == true && alreadyconfettied == false {
    confettitimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "confetti", userInfo: nil, repeats: true)
    alreadyconfettied = true
 }

很抱歉所有的代码!如果你能告诉我如何让这个五彩纸屑叠加停下来会非常有用!

更新1(仍未解决):

所以我需要让ConfettiView创建在与.startConfetti().stopConfetti()相同的功能中进行!使用计时器无法做到这一点,因为当两者都在同一个函数内时,计时器无法调用函数(参见此处:https://stackoverflow.com/a/25839597/5700898)。现在,当某个事件发生时,它会调用confetti()函数......

    func confetti() { // called once and only once when the event is triggered.
        let confettiView = SAConfettiView(frame: self.view.bounds)
        self.view.addSubview(confettiView)
    var confettitimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "confettisub", userInfo: nil, repeats: true)

   func confettisubfunction() {
            lp.confettitime++
            print(lp.confettitime)
    if confettitime == 1 {
       confettiView.type = .Confetti
       confettiView.startConfetti()
       alreadyconfettied = true
     }
    if confettitime == 3 {
       showAlert2()
     }
    if confettitime == 7 {
       dismissAlert2()
    }
    if confettitime == 10 {
       confettiView.stopConfetti()
       confettitimer.invalidate()
       confettitime = 0
    }
    }
    }

但是,正如我上面所说,这引发了灾难性的错误。基本上,这种设置是不可能的,因为视图的声明不能与我用.startConfetti()调用它的函数相同,并且它不能是全局变量/声明: - 如果我在let confettiView = SAConfettiView(frame: self.view.bounds) self.view.addSubview(confettiView)之前class ViewController: UIViewController {,那么它不知道自己是什么,并给出错误“顶层不允许表达”。 - 如果我使用相同的代码在视图控制器的声明中定义我的Confetti UIView ,它会显示“预期声明”。

那么我怎样才能解决这个问题,并在某个事件发生时让五彩纸屑下雨,如何在一个计时器的帮助下停止所述五彩纸屑(或者任何可行的东西?)

提前感谢您的帮助!

更新2(差不多已解决):

在我的全球范围内,我基本上是这样做的,每次庆祝时我都会致电initconfetti()一次。这让我只有一个五彩纸屑视图,我打电话给startConfetti()stopConfetti(),让我实际上再次停止五彩纸屑!!

var confettiView = SAConfettiView()

func initconfetti() {
    confettiView = SAConfettiView(frame: self.view.bounds)
    self.view.addSubview(confettiView)
}

现在我有一个问题:我无法回到点击原始视图(我的视图控制器)!我如何杀死五彩纸屑视图?也许我的界限是0,0?我必须努力解决这个问题(我还是喜欢一些建议)。

当五彩纸屑结束时,我正在调用这一系列命令(我真的不知道它们的含义):

 confettiView.removeFromSuperview()
    confettiView = SAConfettiView(frame: CGRect(
            origin: CGPoint(x: 0, y: 0),
            size: CGSize(width: 0, height: 0)))
    view.becomeFirstResponder()
    self.view.becomeFirstResponder()

但是我的View Controller仍然没有响应任何地方的点击,没有任何事情发生!怎么办?是否有一个功能可以让我的旧视图再次出现在前台?

谢谢!

2 个答案:

答案 0 :(得分:3)

每次输入confetti功能时,您都会创建一个新SAConfettiView并将其添加到控制器的视图中。我没有遵循所有if声明,但我认为可以肯定地说,您正在调用的stopConfetti视图与您用于startConfetti的视图不同。< / p>

我建议在计时器例程之外创建视图,并仅通过计时器控制它。

答案 1 :(得分:0)

查看以下关于所有内容的其他答案的评论,并在下面了解如何仅创建一次子视图:

首先,请务必只拨打一次!在全局范围内执行此操作,就在整个class ViewController : UIViewController {之下。

var confettiView = SAConfettiView()

func initconfetti() {
confettiView = SAConfettiView(frame: self.view.bounds)
self.view.addSubview(confettiView)
}
func deinitconfetti() {
confettiView.removeFromSuperview()
}

这就是全部。现在在NSTimer的帮助下调用它们。