Swift에서 뷰의 모든 하위 뷰를 제거하는 방법은 무엇입니까?


176

하위 뷰를 하나씩 제거하는 대신 슈퍼 뷰에서 모든 하위 뷰를 한 번에 제거하는 간단한 방법을 찾고 있습니다.

//I'm trying something like this, but is not working
let theSubviews : Array = container_view.subviews
for (view : NSView) in theSubviews {
    view.removeFromSuperview(container_view)
}

내가 무엇을 놓치고 있습니까?

최신 정보

내 앱에는 메인이 container_view있습니다. container_view일종의 탐색을 제공하기 위해 다른보기를 하위보기로 추가해야합니다 .

따라서 특정 페이지를 "열기"위해 단추를 클릭하면 모든 하위보기를 제거하고 새 페이지를 추가해야합니다.

업데이트 2-작동하는 솔루션 (OS X)

애플이 고쳤다 고 생각합니다.

이제는 그 어느 때보 다 쉬워졌습니다.

for view in containerView.subviews{
    view.removeFromSuperview()
}

2
: 나는 넝마와 함께 장사하면서, 우수한 대답은, 그 @의 sulthan의 답변을 지적하고 싶습니다 stackoverflow.com/questions/24312760/...
— 크리스토퍼 Swasey

@ChristopherSwasey Swift 4는 오류를 발생시킵니다 : 속성에 할당 할 수 없습니다 : 'subviews'는 가져 오기 전용 속성입니다. :(
— William T. Mallard

2
@ WilliamT.Mallard이 방법과 질문이 iOS가 아닌 MacOS에 관한 것이라는 점을 몇 번이나 반복해야합니까?
— Fogmeister

답변:


358

편집 : (예레미야 / 롤로 감사)

iOS 용 Swift에서이를 수행하는 가장 좋은 방법은 다음과 같습니다.

view.subviews.forEach({ $0.removeFromSuperview() }) // this gets things done
view.subviews.map({ $0.removeFromSuperview() }) // this returns modified array

^^이 기능은 재미 있습니다!

let funTimes = ["Awesome","Crazy","WTF"]
extension String { 
    func readIt() {
        print(self)
    }
}

funTimes.forEach({ $0.readIt() })

//// 편집 종료

그냥 이렇게 :

for view in self.view.subviews {
    view.removeFromSuperview()
}

또는 특정 수업을 찾고 있다면

for view:CustomViewClass! in self.view.subviews {
        if view.isKindOfClass(CustomViewClass) {
            view.doClassThing()
        }
    }

Xcode 7.0 베타 6에서는 "map '에 대한 호출 결과가 사용되지 않습니다"라는 경고가 생성됩니다. 이것이 최종 버전에서 수정되기를 바랍니다.
— Ferschae Naej

나는 또한 그것을 알아 차렸다! Xcode가 베타 버전에서 나오고 문제가 계속되면 게시물을 업데이트하겠습니다.
— Bseaborn

8
경고 result of call to 'map' is unused 는 오류가 아닙니다. Array.map대부분의 언어에서 수정 된 배열을 반환합니다. 배열을 반환하지 않는 동등한 방법은입니다 view.subviews.forEach.
— Rollo

for view:CustomViewClass! in self.view.subviews where view.isKindOfClass(CustomViewClass) { view.doClassThing() }
— iTSangar

나는 이것이 "Swift에서 이것을하는 가장 좋은 방법"이라고 주장 할 것이다. stackoverflow.com/a/24314054/1974224
— Cristik

41

iOS / Swift의 경우 내가 사용하는 모든 하위 뷰를 제거하려면 다음을 수행하십시오.

for v in view.subviews{
   v.removeFromSuperview()
}

UILabel과 같은 특정 클래스의 모든 하위 뷰를 제거하려면 다음을 사용하십시오.

for v in view.subviews{
   if v is UILabel{
      v.removeFromSuperview()
   }
}

31

코드는 다음과 같이 간단하게 작성할 수 있습니다.

view.subviews.forEach { $0.removeFromSuperview() }

18

이것이 가장 간단한 해결책이어야합니다.

let container_view: NSView = ...
container_view.subviews = []

( 다른 방법은 모든 하위 보기 제거? 를 참조 하십시오 )


이것은 참고 맥 OS 질문이 대답에 대해서만 작동 맥 OS . iOS에서는 작동하지 않습니다.


이것은 가장 간단한 방법입니다 ... removeFromSuperview는 더 이상 하위 뷰 배열에없는 각 뷰에 대해 자동으로 호출됩니다.
— Christopher Swasey 2016 년

2
@datayeah 그것들은 아니지만 NSView(OS X)와 UIView(iOS) 사이에는 큰 차이가 있습니다.
— Sulthan

@Sulthan 당신이 맞아요. UIView에 대한 Swift 답변을 보러 왔으며 전체 코드 스 니펫을 읽지
— 못했습니다

1
스위프트 4 오류 : 속성에 할당 할 수 없습니다 : 'subviews'는 get-only 속성입니다. :(
— William T. Mallard

1
@AmrAngry 다시 말씀 드리지만, 이것은 NSViewiOS 및에 대한 것이 아니라 항상 Mac OS 질문이었습니다 UIView. 사람들은 질문과 태그를 읽을 필요가 없으므로 iOS 답변으로 채워졌습니다.
— Sulthan

10

이 문제를 해결할 수 있었는지 모르겠지만 최근에 For 루프가 매번 하나의 뷰를 남겨 두는 비슷한 문제가 발생했습니다. removeFromSuperview ()가 호출되었을 때 self.subviews가 변경 되었기 때문일 수 있습니다.

이 문제를 해결하려면 다음을 수행하십시오.

let subViews: Array = self.subviews.copy()
for (var subview: NSView!) in subViews
{
    subview.removeFromSuperview()
}

.copy ()를 수행하면 self.subviews 배열을 변경하면서 각 하위보기를 제거 할 수 있습니다. 복사 된 배열 (subViews)에는 객체에 대한 모든 참조가 포함되어 있고 변경되지 않았기 때문입니다.

편집 : 귀하의 경우에는 다음을 사용한다고 생각합니다.

let theSubviews: Array = container_view.subviews.copy()
for (var view: NSView!) in theSubviews
{
    view.removeFromSuperview()
}

잘 작동합니다! 감사합니다
— Alberto Bellini

: 아마이 할 수있는 훨씬 더 우아한 방법이 있지만 안녕하세요, 다음을 시도 let subViewsArray: Array = (parentView.subviews as NSArray).copy() as Array<NSView>
— 아담 리차드

9

이 시도:

for view in container_view.subviews {
    view.removeFromSuperview()
}

9

모든 서브 뷰를 제거하기위한 확장 기능으로 빠르게 제거됩니다.

import Foundation
import UIKit

extension UIView {
    /// Remove allSubView in view
    func removeAllSubViews() {
        self.subviews.forEach({ $0.removeFromSuperview() })
    }

}

1
왜지도? 아마도? subviews.forEach {$ 0.removeFromSuperview ()}
— Zaporozhchenko Oleksandr

1
네 맞아요 @Aleksandr 저는이 글을 쓰고있을 때 커피를
— 먹지 않았다고

6

이 시도:

var subViews = parentView.subviews as Array<UIView>

      for someView in subViews
      {
          someView.removeFromSuperview()
      }

업데이트 : 모험적이라고 생각되면 UIView에서 다음과 같이 확장 할 수 있습니다.

extension UIView
{
    func removeAllSubViews()
    {
       for subView :AnyObject in self.subviews
       {
            subView.removeFromSuperview()
       }
    }

}

그리고 이것을 다음과 같이 부르십시오.

parentView.removeAllSubViews()

2 작은 것 : 나는 osx에서 일하고 있으므로 <NSView> 맞습니까? 그런 다음 "치명적인 오류 : 배열 인덱스가 범위를 벗어났습니다"가 표시
— Alberto Bellini

예, OSX에서는 NSView라고 생각합니다. 치명적인 오류는 어디에서 발생합니까?
— azamsharp

부모 뷰에 자식 요소가 있습니까?
— azamsharp

응! 나는 1 얻을에 println (parentView.subviews)를 한 경우
— 알베르토 벨리니

이상하다! 일반적으로 범위를 벗어남은 존재하지 않는 인덱스에 액세스하고 있음을 의미하며 일반적으로 인덱스가 i ++과 같은 for 루프를 사용하여 발생한다고 생각합니다.
— azamsharp

5

xcodebeta6에서는이 문제가 해결되었습니다.

    var subViews = self.parentView.subviews
    for subview in subViews as [UIView]   {
        subview.removeFromSuperview()
    }

그것은 iOS입니다. 나는 OS X에 대한 해결책이 필요
— 알베르토 벨리니

IOS +1위한 훌륭한 솔루션
— inVINCEable

3

나는이 확장을 썼다 :

extension UIView {
    func lf_removeAllSubviews() {
        for view in self.subviews {
            view.removeFromSuperview()
        }
    }
}

따라서 UIViewController에서 self.view.lf_removeAllSubviews를 사용할 수 있습니다. 나는 스위프트에 대한 더 많은 경험이있을 때 나중에 https://github.com/superarts/LFramework 의 스위프트 버전에 이것을 넣을 것입니다 (1 일 exp, API의 경우 밑줄을 포기했습니다).


3

스위프트 3

뷰에 태그를 추가하면 특정 뷰를 제거 할 수 있습니다.

for v in (view?.subviews)!
{
    if v.tag == 321
    {
         v.removeFromSuperview()
    }
 }

왜 안돼 view.subviews.filter({$0.tag != 321}).forEach({$0.removeFromSuperview()})?
— AlexanderZ

3

스위프트 5

하위보기를 제거하는 두 가지 방법을 만듭니다. 그리고 우리가 그것들을 넣으면 사용하기가 훨씬 쉽습니다.extension

extension UIView {
    /// Remove all subview
    func removeAllSubviews() {
        subviews.forEach { $0.removeFromSuperview() }
    }

    /// Remove all subview with specific type
    func removeAllSubviews<T: UIView>(type: T.Type) {
        subviews
            .filter { $0.isMember(of: type) }
            .forEach { $0.removeFromSuperview() }
    }
}

2

구문이 약간 벗어났습니다. 명시 적으로 캐스트하십시오.

 let theSubviews : Array<NSView> = container_view.subviews as Array<NSView>
 for view in theSubviews {
     view.removeFromSuperview()
 }

@David 예, FoxNos의 초기 코드에 최대한 가깝게 유지하려고 노력했습니다.
— Jack

2

당신은 이것을 시도해야

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}

NS가 아닌 UI입니다. 여기에서 우리는 NS로 UI를 대체하여 그것으로도 작동하는 OS X의 경우에 대해 얘기하고, 내 나쁜, 당신은 :) 옳았다
— 알베르토 벨리니

1

특정 클래스의 하위 뷰 만 제거하기 위해 이것은 Xcode6.1.1에서 나를 위해 일한 유일한 Swift 코드였습니다. 제거하려는 유일한 하위보기가 UIButton 유형이라고 가정합니다 ...

for subView in nameofmysuperview.subviews {
    if subView.isKindOfClass(UIButton) {
        subView.removeFromSuperview()
    }
}

1

짧막 한 농담:

while(view.subviews.count > 0) {(view.subviews[0] as NSView).removeFromSuperview()}

이 접근법은 map 또는 forEach를 사용하는 "한 줄짜리"보다 더 읽기 쉽다고 생각합니다 . 논리가 더 추상적이기 때문에 짧은 foreach 및 맵 을 이해하기 어려울 수 있습니다.


1

스위프트 3

superview에서 제거해도 배열에서 버튼이 지워지지 않기 때문에 다음과 같이했습니다.

    for k in 0..<buttons.count {

      buttons[k].removeFromSuperview()

    }


    buttons.removeAll()

1

이것을 시험해보십시오, 나는 이것을 시험했습니다 :

  let theSubviews = container_view.subviews
  for subview in theSubviews {
      subview.removeFromSuperview()
  }

1

에 대한 Swift 4.+

extension UIView {
     public func removeAllSubViews() {
          self.subviews.forEach({ $0.removeFromSuperview() })

}

나는 이것이 당신을 위해 전체 사용되기를 바랍니다.


-2

당신은 같은 것을 시도 했습니까

for o : AnyObject in self.subviews {
     if let v = o as? NSView {
         v.removeFromSuperview()
     }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.