Terminal
Terminal

Reputation: 123

Swift 3 - How to remove all Subviews from Superview as well as Array

I currently have a double for-loop that creates an X by Y grid of UIView CGRect squares. The loop also adds each UIView/Square of the grid to a 2D array allowing me to access each Cell of the grid and alter color/positioning by the index values of the loop.

The loop seems to work fine and displays the Cells/Squares perfectly, however after a while I want to remove all of the squares and also empty the array (but not entirely delete) to make room for a new next grid (which may be of a different size). I created a function to remove all the views from the superview.

This is how I am creating each "Cell" of the grid and placing each into the 2D array:

let xStart = Int(size.width/2/2) - ((gridSizeX * gridScale)/2)
let yStart = Int(size.height/2/2) - ((gridSizeY * gridScale)/2)

let cell : UIView!
cell = UIView(frame: CGRect(x: xStart + (xPos * gridScale), y:yStart + (yPos * gridScale), width:gridScale, height:gridScale))

cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor(red:0.00, green:0.00, blue:0.00, alpha:0.02).cgColor
cell.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:0)

cell.tag = 100

self.view?.addSubview(cell)

gridArray[xPos][yPos] = cell

The 2D array is being created on application load like so:

gridArray = Array(repeating: Array(repeating: nil, count: gridSizeY), count: gridSizeX)

I have tried to search for a solution to remove the UIViews from the superview however all answers from other Questions don't seem to work for me. I have tried to add cell.tag = 100 to each UIView and then remove all UIViews with the Tag Value of 100 like:

for subview in (self.view?.subviews)! {
    if (subview.tag == 100) {
        subview.removeFromSuperview()
    }
}

However no luck. I have also tried to use this method:

self.view?.subviews.forEach({
    $0.removeConstraints($0.constraints)
    $0.removeFromSuperview()
})

The main differences I notice in my code compared to other peoples answers is that I have "?" and "!" at places in the code. I researched about what they mean and understood most of it however I still do not know how to fix my code because if it, and feel as though that is the issue. All I know is that the attempts to remove the UIViews from the superview does not work, and without the "?" and "!"s the code doesn't run at all.

Upvotes: 2

Views: 4254

Answers (2)

DonMag
DonMag

Reputation: 77476

You might be overlooking a much, much simpler way to do this...

You have built a 2D Array containing references to the "cells" as you populated your view. So, just use that Array to remove them.

// when you're ready to remove them
for subArray in gridArray {
    for cell in subArray {
        cell.removeFromSuperview()
    }
}

// clear out the Array
gridArray = Array<Array<UIView>>()

Upvotes: 1

Oleg Gordiichuk
Oleg Gordiichuk

Reputation: 15512

How about to create tag for each cell you are using for example:

    //Init value for for the tag.
    var n = 0

    func prepareCell() -> UIView {
             let xStart = Int(size.width/2/2) - ((gridSizeX * gridScale)/2)
             let yStart = Int(size.height/2/2) - ((gridSizeY * gridScale)/2)

         let cell : UIView!
         cell = UIView(frame: CGRect(x: xStart + (xPos * gridScale), y:yStart + (yPos * gridScale), width:gridScale, height:gridScale))

         cell.layer.borderWidth = 1
         cell.layer.borderColor = UIColor(red:0.00, green:0.00, blue:0.00, alpha:0.02).cgColor
         cell.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:0)

        cell.tag = n

        //Each cell should have new value
        n += 1

        return cell
}

And now remove required views.

func removeViews() {
    for z in 0...n {
        if let viewWithTag = self.view.viewWithTag(z) {
           viewWithTag.removeFromSuperview()
        }
        else {
           print("tag not found")
        }
    }
}

Example that is working in the playground:

var n = 0

let mainView = UIView()

func createView() -> UIView {
    let view = UIView()
    view.tag = n
    n += 1
    return view
}

for i in 0...16 {
    mainView.addSubview(createView())
}

func removeViews() {
    for z in 0...n {
        if let viewWithTag = mainView.viewWithTag(z) {
            viewWithTag.removeFromSuperview()
             print("removed")
        }
        else {
            print("tag not found")
        }
    }
}

Upvotes: 3

Related Questions