Swiftでビューのすべてのサブビューを削除する方法は?


176

サブビューを1つずつ削除するのではなく、スーパービューから一度にすべてのサブビューを削除する簡単な方法を探しています。

//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)

Appleが修正したと思います。

今では、これまでになく簡単です。電話をかけるだけです。

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

2
:私はぼろを埋めながら、優れた答えは、その@ sulthanの答えを指摘したいと思いますstackoverflow.com/questions/24312760/...
クリストファーSwasey

@ChristopherSwasey Swift 4はエラーを出します:プロパティに割り当てることができません: 'subviews'は取得専用のプロパティです。:(
ウィリアムT.マラード

2
@ WilliamT.Mallardこの方法と質問がiOSではなくMacOSに関するものであることを何回繰り返す必要がありますか?
Fogmeister

回答:


358

編集:(Jeremiah / Rolloに感謝)

Swift for iOSでこれを行うための最善の方法は次のとおりです。

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 2015

私もそれに気づきました!Xcodeのベータ版がリリースされても問題が解決しない場合は、投稿を更新します。
Bseaborn、2015

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 2015年

なるほど、これは「圧倒的にスウィフトでこれを行うための最善の方法」であることを主張するだろう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 = []

(他の方法については、すべてのサブビュー削除しますか?を参照してください)


これはMacOSの質問であり、この回答はMacOSでのみ機能することに注意してください。iOSでは動作しません。


これは間違いなく最も簡単な方法です... removeFromSuperviewは、subviews配列に存在しない各ビューに対して自動的に呼び出されます。
Christopher Swasey

2
@datayeahそうではありませんが、NSView(OS X)とUIView(iOS)の間には大きな違いがあります。
スルタン

@Sulthanは正しい。UIViewのSwift回答のためにここに来て、コードスニペット全体を読みませんでした;)
datayeah

1
Swift 4はエラーを出します:プロパティに割り当てることができません: 'subviews'は取得専用のプロパティです。:(
ウィリアムT.マラード

1
@AmrAngry繰り返しますが、これは常にMac OSの質問NSViewでした。iOSとではありませんUIView。質問とタグを読むのを気にしない人だけなので、iOSの回答でいっぱいになりました。
スルタン2018年

10

あなたがこれを何とか解決したかどうかはわかりませんが、最近、Forループが毎回1つのビューを残すという同様の問題が発生しました。これは、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 2014

これを行うにははるかにエレガントな方法は、おそらくあるもののこんにちは、次のことを試してください: 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私はこれを書いているときに私はコーヒーを飲んでいませんでした
YannSteph

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 '19年

はい、OSXではNSViewだと思います。どこで致命的なエラーが発生しますか?
azamsharp 2014年

親ビューに子要素があることを確認してください。
azamsharp 2014年

うん!println(parentView.subviews)を作成すると、1が返されます
Alberto Bellini

それ、変だよ!通常、範囲外とは、存在しないインデックスにアクセスしていることを意味し、通常、i ++のようなインデックスでforループを使用したことが原因であると考えています。
azamsharp 2014年

5

xcodebeta6ではこれがうまくいきました。

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

それがiOSです。OS X向けのソリューションが必要
Alberto Bellini

IOS +1の
優れた

3

私はこの拡張機能を書きました:

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

そのため、UIViewControllerでself.view.lf_removeAllSubviewsを使用できます。これを後でhttps://github.com/superarts/LFrameworkの Swiftバージョンに追加します。Swiftの経験が豊富になった時点で(これまでの1日間の経験と、はい、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

サブビューを削除する2つの異なるメソッドを作成します。そして、それらを入れればはるかに使いやすくなります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です。ここでOS Xについて説明します。UIをNSに置き換えることでそれでも機能する場合は、私の方が正解でした:)
Alberto Bellini 14年

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を使用した「ワンライナー」よりも読みやすいと思います。ロジックがより抽象的なので、短いforeachmapは理解するのが難しい場合があります。


1

Swift 3の場合

スーパービューから削除しただけではボタンが配列から消去されなかったため、次のようにしました。

    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() })

}

私はこれがあなたのためにいっぱいになることを望みます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.