1

Oddly, there is no command for removing all of a view’s subviews at once. However, a view’s subviews array is an immutable copy of the internal list of subviews, so it is legal to cycle through it and remove each subview one at a time:

for v in myView.subviews as [UIView] {
    v.removeFromSuperview()
 }

This content is in the Programming IOS 8,if the copy is immutable copy ,why it can change?

Jincy Sam
  • 421
  • 2
  • 11
lolita
  • 459
  • 1
  • 4
  • 9

2 Answers2

5

I don't think you are a really asking about immutable arrays here as you aren't invoking any methods on the array itself, so it's mutability cannot be an issue. The immutable attribute of the subviews array is how the view has decided to present the list to you. It's got nothing to do with how sub-views interact with parent views.

You appear to be confused about why a subview can remove itself from the parent view and you cannot; this is simply because the subview is a UIView-subclass and the parent view is a UIView-subclass and therefore the subview has access to all of the internal variables of the parent and can do whatever it likes to the parent. You cannot. This is deliberate as you don't know the intricacies of the view hierarchy (and don't want to), where as the UIView obviously does.

Another interesting aspect of the code you posted is that often getting an element in an array to remove itself from the array while you are enumerating it, will cause an exception. In this particular case, however the subviews array you receive from the view is a copy of the original (an immutable copy) and therefore getting the subview to remove itself from the parent view will not affect this array and the enumeration will not falter. Thanks to Christopher Kevin Howell for pointing this out, as I missed it completely, first time round.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • This code it's I read from the book of Programming IOS 8, i do not comprehend, he said the subviews is immutable copy of the internal list,but why he can remove element of it when iterator the subviews. – lolita Dec 17 '15 at 09:33
  • I prefer standard for-in loops in Swift: for subview in subviews { subview.removeFromSuperview() } – Christopher Kevin Howell Dec 17 '15 at 09:33
  • @user2687943 It's because the sub-view is itself a `UIView`-subclass and therefore has special access to its parent (also a `UIView`-subclass). You don't have this access and that's by design. – trojanfoe Dec 17 '15 at 09:37
1

The subviews array is immutable, so you can't change it. For example, you can't remove an element of the array yourself, or overwrite it with a completely new array.

However, there's nothing stopping the internal implementation of the class from changing it by overwriting it internally.

In this case though, the subviews array that is returned is a copy of the actual subviews array.

  • +1 Hmmm, I missed the `copy` attribute on the `subviews` property; rendering half of my answer as invalid :-|. I will attempt to reduce the damage. – trojanfoe Dec 17 '15 at 09:44
  • As far as I know I think the `copy` attribute only determines how the object is set (hence why I edited my answer!). I think Apple purposefully override the `subviews` getter method to return a copy, as many people probably come across crashes trying to remove subviews. Either way, it's a good question by @user2687943! – Christopher Kevin Howell Dec 17 '15 at 09:48
  • My understanding is that the `copy` attribute affects both the getter and the setter. – trojanfoe Dec 17 '15 at 09:55