在for循环中将子视图设置为nil

时间:2015-10-02 08:18:57

标签: ios swift for-loop swift2

我正在尝试从超视图中删除子视图和视图,并将它们设置为nil。我注意到方法removeFromSuperview没有将它们设置为nil,这不是我想要的。我得到的错误是在loadingViewSubviews[i] = nil行。它说:无法通过下标分配,loadingViewSubviews是不可变的。我怎么能克服这个?

这是我在viewDidDisappear

中使用的代码
override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    var loadingViewSubviews = loadingView.subviews
    if loadingView != nil{
        for var i = 0; i < loadingViewSubviews.count; ++i{
            loadingViewSubviews[i].removeFromSuperview()
            loadingViewSubviews[i] = nil
        }
        loadingView.removeFromSuperview()
        loadingView = nil
    }
}

编辑:此代码创建loadingView及其子视图

var activityIndicator: UIActivityIndicatorView!
var activityLabel:UILabel!
var loadingView: UIView!




func processingIAP() {
        if loadingView == nil{
            activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
            activityIndicator.hidesWhenStopped = true
            let labelRect = CGRectMake(activityIndicator.frame.width+6, 0, 200, activityIndicator.frame.height+12)
            activityLabel = UILabel(frame: labelRect)
            activityLabel.text = "Accessing store..."
            activityLabel.textColor = UIColor.whiteColor()
            activityLabel.adjustsFontSizeToFitWidth = true
            activityLabel.textAlignment = NSTextAlignment.Center
            let rect = CGRectMake(sceneView.frame.width/2.0-(activityIndicator.frame.width/2.0 + activityLabel.frame.width/2.0+12), sceneView.frame.height/2.0-(activityIndicator.frame.height/2.0), activityIndicator.frame.width + activityLabel.frame.width+24, activityIndicator.frame.height+12)
            loadingView = UIView(frame: rect)
            loadingView.backgroundColor = UIColor.blackColor()
            self.sceneView.addSubview(loadingView)
            loadingView.addSubview(activityIndicator)
            loadingView.addSubview(activityLabel)
            loadingView.layer.cornerRadius = 3
            loadingView.layer.borderWidth = 3
            loadingView.layer.borderColor = UIColor.whiteColor().CGColor
            activityIndicator.frame.origin = CGPointMake(6, (loadingView.frame.height-activityIndicator.frame.height)/2.0)
            activityIndicator.startAnimating()
        }else{
            activityLabel.text = "Accessing store..."
            activityIndicator.startAnimating()
            activityLabel.frame.origin.x += activityIndicator.frame.width
            activityLabel.frame.size.width -= activityIndicator.frame.width
        }

    }

4 个答案:

答案 0 :(得分:2)

如果从superview中删除loadingview,那么它的所有子视图也会被释放。无需遍历所有子视图:

for subview:UIView in self.view.subviews {
    subview.removeFromSuperview()
}

答案 1 :(得分:2)

如果你有对你的子视图的引用,它甚至不会从superview中删除自己。

你可以这样做,但在目标c:

while (self.subviews.count > 0) {
   id view = [self.subviews lastObject];
   [view removeFromSuperview];
   view = nil;
}

答案 2 :(得分:1)

您不需要将它们设置为零,因为loadingViewSubviews[i].removeFromSuperview()已经从superView中删除了该子视图。

一个例子:

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var loadingView: UIView!
    @IBOutlet weak var l1: UILabel!
    @IBOutlet weak var l2: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        var loadingViewSubviews = loadingView.subviews

        if loadingView != nil{

            for var i = 0; i < loadingViewSubviews.count; ++i{
                loadingViewSubviews[i].removeFromSuperview()
            }
            loadingView.removeFromSuperview()
            loadingView = nil
        }
        // Do any additional setup after loading the view, typically from a nib.
    }
    @IBAction func button(sender: AnyObject) {
        print(l1)
        print(l2)
    }
}

在上面的示例中,所有标签都会在loadingViewSubviews[i].removeFromSuperview()处删除,现在当您按下按钮时,您将收到崩溃错误,如:

  

致命错误:在解包可选值时意外发现nil

在线:

print(l1)

因为该标签在视图中不再可用,因为它已从开始删除。

答案 3 :(得分:1)

如果您在viewDidDisappear中,则无需手动删除所有子视图。这应该自动发生。如果没有,那么你在某处有一个强大的圆柱体。正确的方法是修复这个强大的循环。

您可能会创建一个点:

  1. 您的一个观点包含您的控制器的属性。如果是,请将此属性设置为弱 例: Settings() : goodInput(false) {}
  2. 您在一个区块中调用控制器,此块未完成。如果发生这种情况,请使用
  3. 进行修复
  4. 您以观察者的身份观察与控制者的通知。如果是这样,您可以通过删除deinit函数中的obserer来修复它
  5. 示例:

    weak var controller : Controller

    示例:

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    

    要检查你有一个强大的参考,只需编写deinit函数并记录一些东西:

    aFunctionThatHasABlock() { [weak self] parameterOfSomethingIfThere in
        guard let s = self else { return } // or the controller property
        s.doSomething() // If s is not there it will dont do it :)
    }