Bagaimana cara menghapus semua subview tampilan dalam Swift?


176

Saya mencari metode sederhana untuk menghapus sekaligus semua subview dari superview daripada menghapusnya satu per satu.

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

Apa yang saya lewatkan?

MEMPERBARUI

Aplikasi saya memiliki utama container_view. Saya harus menambahkan berbagai tampilan lain sebagai subview container_viewuntuk menyediakan semacam navigasi.

Jadi, ketika mengklik tombol untuk "membuka" halaman tertentu, saya harus menghapus semua tampilan dan menambahkan yang baru.

UPDATE 2 - Solusi yang berfungsi (OS X)

Saya kira Apple memperbaikinya.

Sekarang lebih mudah dari sebelumnya, panggil saja:

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

2
Saya ingin menunjukkan bahwa jawaban @ sulthan, saat dikubur dengan kain, adalah jawaban yang unggul: stackoverflow.com/questions/24312760/…
Christopher Swasey

@ChristopherSwasey Swift 4 memberikan kesalahan: Tidak dapat menetapkan ke properti: 'subview' adalah properti get-only. :(
William T. Mallard

2
@ WilliamT.Mallard berapa kali harus diulang bahwa metode dan pertanyaan ini tentang MacOS dan bukan iOS?
Fogmeister

Jawaban:


358

EDIT: (terima kasih Jeremiah / Rollo)

Sejauh ini cara terbaik untuk melakukan ini di Swift untuk iOS adalah:

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

^^ Fitur-fitur ini menyenangkan!

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

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

//// AKHIR EDIT

Lakukan saja ini:

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

Atau jika Anda mencari kelas tertentu

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

Dalam Xcode 7.0 beta 6 ini menghasilkan peringatan: "hasil panggilan ke 'peta' tidak digunakan". Saya harap ini diperbaiki di versi final.
Ferschae Naej

Saya perhatikan itu juga! Saya akan memperbarui posting setelah Xcode keluar dari beta dan masalahnya masih berlanjut.
Bseaborn

8
Peringatan,, result of call to 'map' is unused bukan kesalahan. Array.mapdalam kebanyakan bahasa akan mengembalikan array yang dimodifikasi. Metode yang setara yang tidak mengembalikan array, adalah view.subviews.forEach.
Rollo

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

Saya berpendapat bahwa ini adalah "Sejauh ini cara terbaik untuk melakukan ini di Swift", lihat stackoverflow.com/a/24314054/1974224
Cristik

41

Untuk iOS / Swift, untuk menyingkirkan semua subview yang saya gunakan:

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

untuk menghilangkan semua subview dari kelas tertentu (seperti UILabel) saya menggunakan:

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

31

Kode dapat ditulis lebih sederhana sebagai berikut.

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

18

Ini harus menjadi solusi paling sederhana.

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

(lihat Hapus semua subview? untuk metode lain)


Perhatikan ini adalah pertanyaan MacOS dan jawaban ini hanya berfungsi untuk MacOS . Itu tidak berfungsi di iOS.


Ini jelas merupakan cara paling sederhana ... removeFromSuperview secara otomatis dipanggil untuk setiap tampilan yang tidak lagi ada dalam array subview.
Christopher Swasey

2
@dayayeah Mereka tidak tetapi ada perbedaan besar antara NSView(OS X) dan UIView(iOS).
Sulthan

@Sulthan kau benar. Saya datang ke sini untuk jawaban Swift untuk UIView dan tidak membaca seluruh cuplikan kode Anda;)
datayeah

1
Swift 4 memberikan kesalahan: Tidak dapat menetapkan ke properti: 'subview' adalah properti hanya-dapatkan. :(
William T. Mallard

1
@AmrAngry Sekali lagi, saya ulangi, ini selalu menjadi pertanyaan Mac OS, untuk NSView, bukan iOS dan UIView. Hanya orang yang tidak mau membaca pertanyaan dan tag karena itu dipenuhi dengan jawaban iOS.
Sulthan

10

Saya tidak tahu apakah Anda berhasil menyelesaikan ini, tetapi saya baru-baru ini mengalami masalah serupa di mana loop For meninggalkan satu tampilan setiap kali. Saya menemukan ini karena self.subviews dimutasi (mungkin) ketika removeFromSuperview () dipanggil.

Untuk memperbaiki ini saya lakukan:

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

Dengan melakukan .copy (), saya bisa menghapus setiap subview sambil memutasikan array self.subviews. Ini karena array yang disalin (subViews) berisi semua referensi ke objek dan tidak bermutasi.

EDIT: Dalam kasus Anda, saya pikir Anda akan menggunakan:

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

Bekerja dengan baik! Terima kasih
Alberto Bellini

Halo, coba yang berikut ini meskipun mungkin ada cara yang jauh lebih elegan untuk melakukan ini: let subViewsArray: Array = (parentView.subviews as NSArray).copy() as Array<NSView>
Adam Richards

9

Coba ini:

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

9

Ekstensi untuk menghapus semua subview, itu dengan cepat dihapus.

import Foundation
import UIKit

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

}

1
mengapa memetakan? foreach mungkin? subviews.forEach {$ 0.removeFromSuperview ()}
Zaporozhchenko Oleksandr

1
Ya Anda benar @ Avleksandr saya pikir ketika saya menulis ini, saya tidak perlu minum kopi
YannSteph

6

Coba ini:

var subViews = parentView.subviews as Array<UIView>

      for someView in subViews
      {
          someView.removeFromSuperview()
      }

UPDATE : Jika Anda merasa ingin bertualang maka Anda dapat membuat ekstensi pada UIView seperti yang ditunjukkan di bawah ini:

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

}

Dan menyebutnya seperti ini:

parentView.removeAllSubViews()

2 hal kecil: Saya sedang mengerjakan osx, karena itu <NSView> benar? Lalu, saya mendapatkan "kesalahan fatal: Array index out of range": /
Alberto Bellini

Ya, saya pikir pada OSX itu adalah NSView. Di mana Anda mendapatkan kesalahan fatal?
azamsharp

Apakah Anda yakin bahwa tampilan orang tua Anda memiliki elemen anak?
azamsharp

Ya! Jika saya membuat println (parentView.subviews) saya mendapatkan 1
Alberto Bellini

Itu aneh! Biasanya di luar jangkauan berarti bahwa Anda mengakses indeks yang tidak ada dan biasanya saya percaya itu disebabkan oleh penggunaan for loop dengan indeks seperti i ++.
azamsharp

5

Di xcodebeta6 ini berhasil.

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

Itu adalah iOS. Saya butuh solusi untuk OS X
Alberto Bellini

Solusi Hebat untuk iOS +1
inVINCEable

3

Saya menulis ekstensi ini:

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

Sehingga Anda dapat menggunakan self.view.lf_removeAllSubviews dalam UIViewController. Saya akan meletakkan ini dalam versi cepat https://github.com/superarts/LFramework nanti, ketika saya memiliki lebih banyak pengalaman dalam swift (exp 1 hari sejauh ini, dan ya, untuk API saya menyerah garis bawah).


3

Cepat 3

Jika Anda menambahkan tag ke tampilan Anda, Anda dapat menghapus tampilan tertentu.

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

mengapa tidak view.subviews.filter({$0.tag != 321}).forEach({$0.removeFromSuperview()})?
AlexanderZ

3

Cepat 5

Saya membuat 2 metode berbeda untuk menghapus subview. Dan itu jauh lebih mudah digunakan jika kita memasukkannyaextension

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

Sintaks Anda sedikit tidak aktif. Pastikan Anda melakukan casting secara eksplisit.

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

@ David Ya itu akan, saya mencoba untuk tetap sedekat mungkin dengan kode awal FoxNos.
Jack

2

Anda harus mencoba ini

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}

Itu UI bukan NS. Di sini kita berbicara tentang OS X. Jika itu bekerja dengan itu dengan mengganti UI dengan NS, saya buruk, Anda benar :)
Alberto Bellini

1

Untuk menghapus hanya subview dari kelas tertentu - ini adalah satu-satunya kode Swift yang berfungsi untuk saya di Xcode6.1.1. Dengan asumsi satu-satunya subview yang ingin Anda hapus adalah dari jenis UIButton ...

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

1

Satu-liner:

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

Saya pikir pendekatan ini lebih mudah dibaca daripada "one-liners" menggunakan peta atau forEach . Foreach tangan pendek dan peta bisa sulit dipahami, karena logikanya lebih abstrak.


1

Untuk Swift 3

Saya melakukan sebagai berikut karena hanya menghapus dari superview tidak menghapus tombol dari array.

    for k in 0..<buttons.count {

      buttons[k].removeFromSuperview()

    }


    buttons.removeAll()

1

Coba ini, saya menguji ini:

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

1

Untuk Swift 4.+

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

}

Saya harap ini digunakan penuh untuk Anda.


-2

apakah Anda mencoba sesuatu seperti

for o : AnyObject in self.subviews {
     if let v = o as? NSView {
         v.removeFromSuperview()
     }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.