Swift'te bir görünümün tüm alt görünümleri nasıl kaldırılır?


176

Tek seferde kaldırmak yerine bir denetimden tüm alt görünümleri kaldırmak için basit bir yöntem arıyorum.

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

Neyi kaçırdım?

GÜNCELLEME

Uygulamamın bir ana özelliği var container_view. container_viewBir tür gezinme sağlamak için alt görünüm olarak farklı görünümler eklemeliyim .

Bu nedenle, belirli bir sayfayı "açmak" için düğmeyi tıkladığınızda, tüm alt görünümleri kaldırmam ve yenisini eklemem gerekir.

GÜNCELLEME 2 - Çalışan bir çözüm (OS X)

Sanırım Apple düzeltti.

Şimdi her zamankinden daha kolay, sadece ara:

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

2
@ Sulthan'ın paçavralarla gömülü iken cevabının en üstün cevap olduğunu belirtmek isterim: stackoverflow.com/questions/24312760/…
Christopher Swasey

@ChristopherSwasey Swift 4 hata veriyor: Mülke atanamıyor: 'alt görünümler' yalnızca özellikli bir özelliktir. :(
William T. Mallard

2
@ WilliamT.Mallard Bu yöntem ve sorunun iOS değil MacOS ile ilgili olduğu kaç kez tekrarlanmalıdır?
Fogmeister

Yanıtlar:


358

EDIT: (teşekkürler Jeremiah / Rollo)

İOS için Swift'te bunu yapmanın en iyi yolu:

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

^^ Bu özellikler eğlencelidir!

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

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

//// SON DÜZENLEME

Sadece bunu yap:

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

Veya belirli bir sınıf arıyorsanız

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

Xcode 7.0 beta 6'da bu bir uyarı oluşturur: "'map' çağrısı sonucu kullanılmıyor". Umarım bu son sürümde giderilir.
Ferschae Naej

Bunu ben de fark ettim! Xcode beta sürümünden çıktığında ve sorun devam edince gönderiyi güncelleyeceğim.
Bseaborn

8
Uyarısı, result of call to 'map' is unused bir hata değildir. Array.mapçoğu dilde değiştirilmiş diziyi döndürür. Dizi döndürmeyen eşdeğer yöntem olacaktır view.subviews.forEach.
Rollo

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

Bunun "Swift'te bunu yapmanın en iyi yolu" olduğunu iddia ediyorum, bkz. Stackoverflow.com/a/24314054/1974224
Cristik

41

İOS / Swift için, kullandığım tüm alt görünümlerden kurtulmak için:

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

(UILabel gibi) belirli bir sınıfın tüm alt görünümlerinden kurtulmak için:

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

31

Kod aşağıdaki gibi daha basit yazılabilir.

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

18

Bu en basit çözüm olmalı.

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

( diğer yöntemler için bkz. Tüm alt görünümler kaldırılsın mı? )


Bunun bir MacOS sorusu olduğunu ve bu cevabın yalnızca MacOS için çalıştığını unutmayın . İOS'ta çalışmaz.


Bu kesinlikle en basit yoldur ... removeFromSuperview, artık alt görünümler dizisinde olmayan her görünüm için otomatik olarak çağrılır.
Christopher Swasey

2
@datayeah Öyle değiller ama NSView(OS X) ve UIView(iOS) arasında büyük bir fark var .
Sulthan

@ Haklısın haklısın. Buraya UIView için Swift cevabı için geldim ve tüm kod snippet'inizi
okumadım

1
Swift 4 bir hata veriyor: Özelliğe atanamıyor: 'alt görünümler' salt bir özelliktir. :(
William T. Mallard

1
@AmrAngry Tekrar ediyorum, bu her zaman bir Mac OS sorusuydu, NSViewiOS ve değil UIView. Sadece insanlar soruyu ve etiketleri okumayı umursamıyor, bu yüzden iOS cevaplarıyla doluydu.
Sulthan

10

Bunu çözmeyi başarabildiğinizi bilmiyorum ama son zamanlarda For döngüsünün her seferinde bir görünüm bıraktığı benzer bir sorun yaşadım. Bunu removeFromSuperview () çağrıldığında self.subviews mutasyona uğramış (belki) olduğu için buldum.

Bunu düzeltmek için yaptım:

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

.Copy () yaparak self.subviews dizisini değiştirirken her alt görünümün kaldırılmasını gerçekleştirebilirim. Bunun nedeni, kopyalanan dizinin (subViews) nesnelere yapılan tüm başvuruları içermesi ve değiştirilmemesidir.

EDIT: Senin durumunda ben kullanacağını düşünüyorum:

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

Sadece iyi çalışıyor! Teşekkürler
Alberto Bellini

Merhaba, muhtemelen bunu yapmanın çok daha zarif bir yolu olmasına rağmen aşağıdakileri deneyin: let subViewsArray: Array = (parentView.subviews as NSArray).copy() as Array<NSView>
Adam Richards

9

Bunu dene:

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

9

Uzantı tüm alt görünümleri kaldırmak için, hızlı bir şekilde kaldırılır.

import Foundation
import UIKit

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

}

1
neden harita? belki foreach? subviews.forEach {$ 0.removeFromSuperview ()}
Zaporozhchenko Oleksandr

1
Evet haklısın @Aleksandr Sanırım bunu yazarken
kahvemi almadım

6

Bunu dene:

var subViews = parentView.subviews as Array<UIView>

      for someView in subViews
      {
          someView.removeFromSuperview()
      }

GÜNCELLEME : Maceracı hissediyorsanız, UIView'de aşağıda gösterildiği gibi bir uzantı yapabilirsiniz:

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

}

Ve şöyle deyin:

parentView.removeAllSubViews()

2 küçük şey: osx üzerinde çalışıyorum, bu yüzden <NSView> olurdu değil mi? Sonra, "ölümcül hata: Dizi dizini aralık dışında" alıyorum: /
Alberto Bellini

Evet, OSX'te NSView olduğunu düşünüyorum. Ölümcül hatayı nereden alıyorsunuz?
azamsharp

Üst görünümünüzde alt öğeler bulunduğundan emin misiniz?
azamsharp

Evet! Eğer bir println (parentView.subviews) yaparsam 1
Alberto Bellini

Bu garip! Genellikle aralık dışı, var olmayan bir dizine eriştiğiniz anlamına gelir ve genellikle i ++ gibi dizinlerle bir for döngüsü kullanmanın neden olduğuna inanıyorum.
azamsharp

5

Xcodebeta6'da bu işe yaradı.

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

Bu iOS. OS X için bir çözüme ihtiyacım var
Alberto Bellini

IOS +1 için Harika Çözüm
inVINCEable

3

Bu uzantıyı yazdım:

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

Böylece bir UIViewController içinde self.view.lf_removeAllSubviews kullanabilirsiniz. Bunu daha hızlı bir deneyimim olduğunda https://github.com/superarts/LFramework'umun hızlı sürümüne koyacağım (şimdiye kadar 1 günlük exp ve evet, API için alt çizgiden vazgeçtim).


3

Hızlı 3

Görünümünüze bir etiket eklerseniz belirli bir görünümü kaldırabilirsiniz.

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

neden olmasın view.subviews.filter({$0.tag != 321}).forEach({$0.removeFromSuperview()})?
AlexanderZ

3

Hızlı 5

Alt görünümü kaldırmak için 2 farklı yöntem oluşturuyorum. Ve onları koyarsak kullanmak çok daha kolayextension

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

Sözdiziminiz biraz kapalı. Açıkça yayınladığınızdan emin olun.

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

@David Evet, FoxNos'un ilk koduna olabildiğince yakın tutmaya çalıştım.
Jack

2

bunu denemelisin

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}

Bu UI NS değil. Burada OS X'den bahsediyoruz. Bu, UI'yi NS ile değiştirerek bile işe yarıyorsa, benim hatam, haklısın :)
Alberto Bellini

1

Belirli bir sınıfın yalnızca alt görüntülerini kaldırmak için - bu Xcode6.1.1'de benim için çalışan tek Swift koduydu. Kaldırmak istediğiniz yalnızca alt görünümlerin UIButton türünde olduğunu varsayarsak ...

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

1

Tek astarı:

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

Bence bu yaklaşım, map veya forEach kullanarak "one-liners" den daha okunabilir . Mantık daha soyut olduğu için kısa el foreach ve haritasının anlaşılması zor olabilir.


1

Swift 3 için

Aşağıdaki gibi yaptım çünkü sadece denetlemeden kaldırma dizideki düğmeleri silmedi.

    for k in 0..<buttons.count {

      buttons[k].removeFromSuperview()

    }


    buttons.removeAll()

1

Bunu deneyin, bunu test ettim:

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

1

İçin Swift 4.+

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

}

Umarım bu sizin için tam kullanımdır.


-2

gibi bir şey denedin mi

for o : AnyObject in self.subviews {
     if let v = o as? NSView {
         v.removeFromSuperview()
     }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.