Làm cách nào để xóa tất cả các lượt xem của chế độ xem trong Swift?


176

Tôi đang tìm kiếm một phương pháp đơn giản để loại bỏ ngay lập tức tất cả các cuộc phỏng vấn khỏi một giám sát thay vì loại bỏ từng cái một.

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

Tôi đang thiếu gì?

CẬP NHẬT

Ứng dụng của tôi có một chính container_view. Tôi phải thêm các chế độ xem khác nhau dưới dạng các cuộc phỏng vấn container_viewđể cung cấp một loại điều hướng.

Vì vậy, khi nhấp vào nút để "mở" một trang cụ thể, tôi cần xóa tất cả các bản xem trước và thêm trang mới.

CẬP NHẬT 2 - Một giải pháp làm việc (OS X)

Tôi đoán Apple đã sửa nó.

Bây giờ nó dễ dàng hơn bao giờ hết, chỉ cần gọi:

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

2
Tôi muốn chỉ ra rằng câu trả lời của @ sulthan, trong khi bị chôn vùi bởi giẻ rách, là câu trả lời vượt trội: stackoverflow.com/questions/24312760/ Lỗi
Christopher Swasey

@ChristopherSwasey Swift 4 báo lỗi: Không thể gán cho thuộc tính: 'subview' là thuộc tính chỉ nhận được. :
William T. Mallard

2
@ WilliamT.Mallard phải lặp đi lặp lại bao nhiêu lần rằng phương pháp và câu hỏi này là về MacOS chứ không phải iOS?
Sương mù

Câu trả lời:


358

EDIT: (cảm ơn Jeremiah / Rollo)

Cho đến nay, cách tốt nhất để làm điều này trong Swift cho iOS là:

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

^^ Những tính năng này rất thú vị!

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

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

//// KẾT THÚC KẾT THÚC

Chỉ cần làm điều này:

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

Hoặc nếu bạn đang tìm kiếm một lớp học cụ thể

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

Trong Xcode 7.0 beta 6, điều này tạo ra một cảnh báo: "kết quả của cuộc gọi đến 'bản đồ' không được sử dụng". Tôi hy vọng điều này sẽ được sửa trong phiên bản cuối cùng.
Ferschae Naej

Tôi cũng nhận thấy điều đó! Tôi sẽ cập nhật bài đăng khi Xcode hết beta và vấn đề vẫn còn.
Bseaborn

8
Cảnh báo, result of call to 'map' is unused không phải là một lỗi. Array.maptrong hầu hết các ngôn ngữ sẽ trả về mảng đã sửa đổi. Phương thức tương đương không trả về một mảng sẽ là view.subviews.forEach.
Rollo

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

Tôi sẽ lập luận rằng đây là "Cách tốt nhất để làm điều này trong Swift", xem stackoverflow.com/a/24314054/1974224
Cristik

41

Đối với iOS / Swift, để loại bỏ tất cả các cuộc phỏng vấn tôi sử dụng:

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

để thoát khỏi tất cả các cuộc phỏng vấn của một lớp cụ thể (như UILabel) tôi sử dụng:

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

31

Mã có thể được viết đơn giản hơn như sau.

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

18

Đây phải là giải pháp đơn giản nhất.

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

(xem Xóa tất cả các cuộc phỏng vấn? cho các phương pháp khác)


Lưu ý đây là câu hỏi về MacOS và câu trả lời này chỉ hoạt động với MacOS . Nó không hoạt động trên iOS.


Đây chắc chắn là cách đơn giản nhất ... removeFromSuperview được tự động gọi cho mỗi chế độ xem không còn trong mảng xem trước.
Christopher Swasey

2
@datayeah Họ không nhưng có một sự khác biệt lớn giữa NSView(OS X) và UIView(iOS).
Sulthan

@Sulthan bạn nói đúng. Tôi đến đây để trả lời Swift cho UIView và đã không đọc toàn bộ đoạn mã của bạn;)
datayeah

1
Swift 4 đưa ra lỗi: Không thể gán cho thuộc tính: 'subview' là thuộc tính chỉ nhận. :(
William T. Mallard

1
@AmrAngry Một lần nữa, tôi nhắc lại, đây luôn là câu hỏi của Mac OS NSView, không phải cho iOS và UIView. Chỉ mọi người không quan tâm để đọc câu hỏi và thẻ do đó nó chứa đầy câu trả lời của iOS.
Sulthan

10

Tôi không biết liệu bạn có giải quyết được vấn đề này không nhưng gần đây tôi đã gặp phải một vấn đề tương tự khi vòng lặp For để lại một lượt xem mỗi lần. Tôi thấy điều này là do các self.subview bị đột biến (có thể) khi removeFromSuperview () được gọi.

Để khắc phục điều này tôi đã làm:

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

Bằng cách thực hiện .copy (), tôi có thể thực hiện loại bỏ từng khung nhìn phụ trong khi thay đổi mảng self.subview. Điều này là do mảng được sao chép (subViews) chứa tất cả các tham chiếu đến các đối tượng và không bị đột biến.

EDIT: Trong trường hợp của bạn, tôi nghĩ bạn sẽ sử dụng:

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

Hoạt động tốt! Cảm ơn
Alberto Bellini

Xin chào, hãy thử cách sau đây mặc dù có lẽ có một cách thanh lịch hơn nhiều để làm điều này: let subViewsArray: Array = (parentView.subviews as NSArray).copy() as Array<NSView>
Adam Richards

9

Thử cái này:

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

9

Mở rộng để loại bỏ tất cả các cuộc phỏng vấn, nó nhanh chóng được gỡ bỏ.

import Foundation
import UIKit

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

}

1
Tại sao bản đồ? có thể thuyết minh? subview.forEach {$ 0.removeFromSuperview ()}
Zaporozhunn Oleksandr

1
Có bạn đúng @Aleksandr tôi nghĩ khi tôi viết bài này, tôi đã không uống cà phê của mình
YannSteph

6

Thử cái này:

var subViews = parentView.subviews as Array<UIView>

      for someView in subViews
      {
          someView.removeFromSuperview()
      }

CẬP NHẬT : Nếu bạn cảm thấy thích phiêu lưu thì bạn có thể thực hiện một tiện ích mở rộng trên UIView như dưới đây:

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

}

Và gọi nó như thế này:

parentView.removeAllSubViews()

2 điều nhỏ: Tôi đang làm việc trên osx, vì vậy nó sẽ là <NSView> phải không? Sau đó, tôi nhận được "lỗi nghiêm trọng: Chỉ số mảng nằm ngoài phạm vi": /
Alberto Bellini

Vâng, tôi nghĩ trên OSX đó là NSView. Nơi nào bạn nhận được lỗi nghiêm trọng?
azamsharp

Bạn có chắc chắn rằng chế độ xem cha mẹ của bạn có các yếu tố con?
azamsharp

Vâng ! Nếu tôi thực hiện một bản in (ParentView.subview), tôi nhận được 1
Alberto Bellini

Điều đó lạ thật! Thông thường nằm ngoài phạm vi có nghĩa là bạn đang truy cập vào một chỉ mục không tồn tại và thông thường tôi tin rằng đó là do sử dụng vòng lặp for với các chỉ mục như i ++.
azamsharp

5

Trong xcodebeta6, điều này đã làm việc.

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

Đó là iOS. Tôi cần một giải pháp cho OS X
Alberto Bellini

Giải pháp tuyệt vời cho iOS +1
inVINCEable

3

Tôi đã viết phần mở rộng này:

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

Vì vậy, bạn có thể sử dụng self.view.lf_remove ALLSubview trong UIViewControll. Tôi sẽ đưa nó vào phiên bản nhanh chóng của https://github.com/superarts/LFramework của tôi sau này, khi tôi có nhiều kinh nghiệm hơn về swift (cho đến nay là 1 ngày, và vâng, đối với API tôi đã từ bỏ dấu gạch dưới).


3

Swift 3

Nếu bạn thêm một thẻ vào chế độ xem của mình, bạn có thể xóa chế độ xem cụ thể.

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

tại sao không view.subviews.filter({$0.tag != 321}).forEach({$0.removeFromSuperview()})?
AlexanderZ

3

Swift 5

Tôi tạo 2 phương pháp khác nhau để loại bỏ subview. Và nó dễ sử dụng hơn nhiều nếu chúng ta đặt chúng vàoextension

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

Cú pháp của bạn hơi bị tắt. Hãy chắc chắn rằng bạn đúc rõ ràng.

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

@David Có, tôi sẽ cố giữ nó càng gần mã ban đầu của FoxNos càng tốt.
Jack

2

Bạn phải cố gắng này

func clearAllScrollSubView ()
{
    let theSubviews = itemsScrollView.subviews

    for (var view) in theSubviews
    {

        if view is UIView
        {
            view.removeFromSuperview()
        }

    }
}

Đó là UI không NS. Ở đây chúng ta đang nói về OS X. Nếu điều đó hoạt động ngay cả với nó bằng cách thay thế UI bằng NS, thì thật tệ, bạn đã đúng :)
Alberto Bellini

1

Để xóa chỉ các cuộc phỏng vấn của một lớp cụ thể - đây là mã Swift duy nhất hoạt động với tôi trong Xcode6.1.1. Giả sử các cuộc phỏng vấn duy nhất bạn muốn xóa là loại UIButton ...

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

1

Lót:

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

Tôi nghĩ rằng cách tiếp cận này dễ đọc hơn so với "một lớp" bằng cách sử dụng bản đồ hoặc forEach . Foreach tay ngắn và bản đồ có thể khó hiểu, vì logic trừu tượng hơn.


1

Dành cho Swift 3

Tôi đã làm như sau bởi vì chỉ cần loại bỏ khỏi giám sát đã không xóa các nút khỏi mảng.

    for k in 0..<buttons.count {

      buttons[k].removeFromSuperview()

    }


    buttons.removeAll()

1

Hãy thử nó, tôi đã thử nghiệm điều này:

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

1

Dành cho Swift 4.+

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

}

tôi hy vọng điều này được sử dụng đầy đủ cho bạn.


-2

bạn đã thử một cái gì đó như

for o : AnyObject in self.subviews {
     if let v = o as? NSView {
         v.removeFromSuperview()
     }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.