UIStackView: Ist es wirklich notwendig, sowohl removeFromSuperView als auch removeArrangedSubview aufzurufen, um eine Unteransicht zu entfernen?


71

Aus der UIStackView-Klassenreferenz

In removeArrangedSubview:

Um zu verhindern, dass die Ansicht nach dem Aufrufen der Methode removeArrangedSubview: des Stapels auf dem Bildschirm angezeigt wird, entfernen Sie die Ansicht explizit aus dem Array subviews, indem Sie die Methode removeFromSuperview der Ansicht aufrufen.

In arrangierter Unteransicht:

Immer wenn die removeFromSuperview-Methode einer angeordneten Ansicht aufgerufen wird, entfernt die Stapelansicht die Ansicht aus ihrem arrangierten Subview-Array

Von diesen scheint es, dass das Aufrufen von removeFromSuperview ausreicht, um eine Unteransicht zu entfernen, und ich habe sie ohne Probleme so verwendet. Ich habe das Verhalten auch bestätigt, indem ich die Anzahl der arrangierten Subviews-Arrays protokolliert habe, wenn removeFromSuperview aufgerufen wird.

Viele Tutorials und Kommentare hier zu S / O sagen jedoch, beide anzurufen. Gibt es einen Grund dafür? Oder machen die Leute das einfach, weil es in der Dokumentation steht?


4
Keine richtige Antwort für Sie, aber eine Anekdote: Ich habe nur angerufen, removeArrangedSubviewohne zu wissen , dass ich auch anrufen sollte removeFromSuperview, und es hat zwar die Sicht geklärt, arrangedSubviewsaber die Sicht hat immer noch subviewsalle Arten von verwirrendem Bruch verursacht. Durch Hinzufügen des removeFromSuperviewAnrufs (sobald ich diese Frage gesehen habe!) Wurde das Problem behoben.
Aehlke

Ich kenne die Antwort auch nicht. Ich hatte jedoch ein Problem, bei dem nicht alle meine Unteransichten nach Verwendung von RemoveArrangedSubview entfernt wurden. Nachdem ich diesen Beitrag gesehen habe, habe ich removeFromSuperview-Aufrufe hinzugefügt und jetzt funktioniert es wie erwartet.
CleverPatrick

1
Die Dokumentation scheint darauf hinzudeuten, dass Sie nur anrufen müssen removeFromSuperview. Ich rufe nur removeFromSuperviewohne Probleme an.
Adam Johns

Anscheinend gibt es ein Problem mit IOS12, wenn Sie nur removeArrangedSubview aufrufen. Die Ansicht wird nicht richtig entfernt. Das Aufrufen von removeFromSuperview funktioniert.
Seeler99

Antworten:


78

Nein, ruf einfach an subview.removeFromSuperview()

/* Removes a subview from the list of arranged subviews without removing it as
 a subview of the receiver.
    To remove the view as a subview, send it -removeFromSuperview as usual;
 the relevant UIStackView will remove it from its arrangedSubviews list
 automatically.
 */
open func removeArrangedSubview(_ view: UIView)

1
Eigentlich ist das eine falsche Interpretation. Nur die Verwendung removeFromSuperView()scheint zu funktionieren, kann jedoch zu seltsamen Abstürzen führen, wenn Sie viele Ansichten hinzufügen und entfernen. Wenn Sie den Diskussionsteil der Dokumente lesen, ist es ziemlich klar, dass Sie beide anrufen müssen.
Drekka

4
@drekka kannst du deine Quelle zitieren oder einen Link bereitstellen? Dem Dokument scheint klar zu sein, dass nicht beide Anrufe erforderlich sind.
Graham Perks

Ich kann dies bestätigen. Ich habe Absturzberichte von meiner App, wenn ich nur anrufe removeFromSuperview(). Ich werde in Kürze ein Update veröffentlichen, das auch hinzufügt removeArrangedSubview()und darüber berichtet, ob dies das Problem behebt!
Simonthumper

1
@ Simonthumper hat es behoben?
Gil Birman

Ich habe 2 Schaltflächen mit removeArrangedSubview aus stackView entfernt und hatte sie nach dem Entfernen immer noch (nur der Rahmen wurde geändert). nach der Verwendung von func removeArrangedView (_ view: UIView) {removeArrangedSubview (view) view.removeFromSuperview ()} ist alles gut :)
Deryck Lucian

31

In iOS 12.0 müssen Sie verwenden

stackView.arrangedSubviews[index].removeFromSuperview()

Wenn Sie verwenden removeArrangedSubview, gibt es einen Fehler, bei dem die Ansicht am angegebenen Index entfernt wurde, die Ansicht, die ich löschen möchte, jedoch unter angezeigt wird CGPoint(x: 0, y: 0).

Hoffe das hilft jemandem.


Dieses Problem haben 2. Wo ist das große Protokoll dafür?
H2wk

10

Hacking With Swift bietet ein ziemlich gutes Beispiel und eine Erklärung, in diesem Fall die Verwendung von Webansichten.

Der Grund dafür ist, dass Sie etwas aus der angeordneten Unteransichtsliste einer Stapelansicht entfernen und später erneut hinzufügen können, ohne es jedes Mal neu erstellen zu müssen - es wurde ausgeblendet und nicht zerstört. Wir möchten keinen Speicherverlust, daher möchten wir gelöschte Webansichten vollständig entfernen. Wenn Sie feststellen, dass Ihre Speichernutzung im Ballon aufsteigt, haben Sie diesen Schritt wahrscheinlich vergessen!

https://www.hackingwithswift.com/read/31/4/removing-views-from-a-uistackview-with-removearrangedsubview


2
hackingwithswift wurde aktualisiert, um auch nur zu empfehlenremoveFromSuperview
Joachim Kurz

8

Sie haben Recht, nur der Anruf bei removeFromSuperviewreicht aus, um die Ansicht vollständig zu entfernen.

Ich vermute, der Grund, warum Leute beide setzen, ist, dass sie auf die removeArrangedSubviewDokumentation stoßen, was zu sagen scheint, dass beide benötigt werden. (Und tatsächlich sind sie es, wenn Sie anrufen removeArrangedSubviewund wollen, dass die Aussicht wirklich weg ist.)

Das zusätzliche Dokument arrangedSubviewswird von so vielen nicht gesehen, sodass sie nicht erkennen removeArrangedSubview, dass es in diesem Fall optional ist.


Wie ich oben in einem Kommentar sagte, scheint es zu funktionieren, kann aber Abstürze auslösen. Es removeFromSuperview()wird also nicht empfohlen, nur zu verwenden.
Drekka

7

Eine angeordnete Unteransicht aus einer Stapelansicht zu entfernen ist

// To remove it from the view hierarchy
   subView.removeFromSuperview()

removeFromSuperview()ist laut Apples Dokumentation ausreichend und man kann sich auch leicht selbst testen. removeArrangedSubview()ist einfach nicht nötig.
Joachim Kurz

3

Zum Entfernen benutze ich diese Erweiterung. Ich weiß nicht wirklich, ob es notwendig ist, Einschränkungen zu entfernen. Aber vielleicht würde es helfen.

extension UIStackView {
    func removeAllArrangedSubviews() {
        let removedSubviews = arrangedSubviews.reduce([]) { (allSubviews, subview) -> [UIView] in
            self.removeArrangedSubview(subview)
            return allSubviews + [subview]
        }

        for v in removedSubviews {
            if v.superview != nil {
                NSLayoutConstraint.deactivate(v.constraints)
                v.removeFromSuperview()
            }
        }
    }
}

1
Dies ist in Ordnung, solange die entfernte Ansicht sofort zerstört wird. Aber es gibt einen möglichen Fehler, wenn es wiederverwendet wird - alle internen Einschränkungen wurden entfernt, so dass es wahrscheinlich nicht richtig angelegt wird
Rich Tolley

2

Nein, um eine bestimmte Ansicht zu entfernen.

func removeArrangedSubview (_ view: UIView)

So entfernen Sie alle Unteransichten

stackView.arrangedSubviews.forEach {$ 0.removeFromSuperview ()}


0

Ich werde vorschlagen, arrangierte Unteransichten zu bekommen und diese dann wie unten beschrieben zu entfernen.

for view in self.stackView.arrangedSubviews{
      self.stackView.removeArrangedSubview(view)
      view.removeFromSuperview()
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.