Usuń wszystkie ograniczenia wpływające na UIView

90

Mam UIView, który jest umieszczony na ekranie z kilkoma ograniczeniami. Właścicielem niektórych ograniczeń jest superview, inne należą do innych przodków (np. Być może właściwość widoku UIViewController).

Chcę usunąć wszystkie te stare ograniczenia i umieścić je w nowym miejscu, używając nowych ograniczeń.

Jak mogę to zrobić bez tworzenia IBOutlet dla każdego pojedynczego ograniczenia i konieczności zapamiętywania, który widok jest właścicielem tego ograniczenia?

Aby rozwinąć, naiwnym podejściem byłoby utworzenie grupy IBOutletów dla każdego z ograniczeń, a następnie wywołanie kodu takiego jak:

[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];

Problem z tym kodem polega na tym, że nawet w najprostszym przypadku musiałbym stworzyć 2 IBOutlety. W przypadku złożonych układów może to łatwo osiągnąć 4 lub 8 wymaganych IBOutletów. Ponadto musiałbym upewnić się, że moje wezwanie do usunięcia ograniczenia jest wywoływane z właściwego punktu widzenia. Na przykład wyobraź sobie, że myViewsLeftConstraintjest własnością viewA. Gdybym przypadkowo zadzwonił [self.view removeConstraint:self.myViewsLeftConstraint], nic by się nie stało.

Uwaga: metoda constraintsAffectingLayoutForAxis wygląda obiecująco, ale jest przeznaczona tylko do debugowania.


Aktualizacja: Wiele odpowiedzi jestem otrzymujących kontrakt z self.constraints, self.superview.constraintslub jakiegoś wariantu tych. Te rozwiązania nie będą działać, ponieważ te metody zwracają tylko ograniczenia należące do widoku, a nie te, które mają wpływ na widok.

Aby wyjaśnić problem z tymi rozwiązaniami, rozważ następującą hierarchię widoków:

  • Dziadek
    • Ojciec
      • Mnie
        • Syn
        • Córka
      • Brat
    • Wujek

Teraz wyobraź sobie, że tworzymy następujące ograniczenia i zawsze dołączamy je do ich najbliższego wspólnego przodka:

  • C0: Me: ten sam top co Son (należący do mnie)
  • C1: Me: width = 100 (należące do mnie)
  • C2: Ja: taki sam wzrost jak brat (własność ojca)
  • C3: Me: ten sam top co Uncle (właściciel Dziadka)
  • C4: Ja: to samo co dziadek (własność dziadka)
  • C5: Brat: ten sam lewy co ojciec (własność ojca)
  • C6: Wujek: to samo lewe co dziadek (własność dziadka)
  • C7: Syn: to samo lewe co córka (należące do mnie)

Teraz wyobraź sobie, że chcemy usunąć wszystkie wpływające ograniczenia Me. Każde właściwe rozwiązanie powinno usunąć [C0,C1,C2,C3,C4]i nic więcej.

Jeśli użyję self.constraints(gdzie jaźń jest mną), dostanę [C0,C1,C7], ponieważ są to jedyne ograniczenia, które są moją własnością. Oczywiście nie wystarczyłoby to usunąć, ponieważ go brakuje [C2,C3,C4]. Ponadto usuwa C7niepotrzebnie.

Jeśli użyję self.superview.constraints(gdzie ja jest mną), dostanę [C2,C5], ponieważ są to ograniczenia należące do Ojca. Oczywiście nie możemy ich wszystkich usunąć, ponieważ C5jest to całkowicie niezwiązane z Me.

Jeśli użyję grandfather.constraints, dostanę [C3,C4,C6]. Ponownie, nie możemy ich wszystkich usunąć, ponieważ C6powinny pozostać nienaruszone.

Podejście brutalnej siły polega na zapętleniu nad każdym z przodków widoku (łącznie z nim samym) i sprawdzeniu, firstItemczy secondItemsam widok jest, czy też jest; jeśli tak, usuń to ograniczenie. Doprowadzi to do prawidłowego rozwiązania, powrotu [C0,C1,C2,C3,C4]i tylko tych ograniczeń.

Mam jednak nadzieję, że istnieje bardziej eleganckie rozwiązanie niż konieczność przeglądania całej listy przodków.

Rozsądne
źródło
Co powiesz na umieszczenie identyfikatora dla wszystkich ograniczeń, które chcesz usunąć? W ten sposób nie musisz mieć dla nich ujścia.
nsuinteger

Odpowiedzi:

71

To podejście zadziałało dla mnie:

@interface UIView (RemoveConstraints)

- (void)removeAllConstraints;

@end


@implementation UIView (RemoveConstraints)

- (void)removeAllConstraints
{
    UIView *superview = self.superview;
    while (superview != nil) {
        for (NSLayoutConstraint *c in superview.constraints) {
            if (c.firstItem == self || c.secondItem == self) {
                [superview removeConstraint:c];
            }
        }
        superview = superview.superview;
    }

    [self removeConstraints:self.constraints];
    self.translatesAutoresizingMaskIntoConstraints = YES;
}

@end

Po zakończeniu wykonywanie widoku pozostaje tam, gdzie było, ponieważ tworzy ograniczenia autorezyzacji. Kiedy tego nie robię, widok zazwyczaj znika. Ponadto nie tylko usuwa ograniczenia z superwizji, ale przechodzi całą drogę w górę, ponieważ mogą istnieć ograniczenia wpływające na to w widokach przodków.


Wersja Swift 4

extension UIView {
    
    public func removeAllConstraints() {
        var _superview = self.superview
        
        while let superview = _superview {
            for constraint in superview.constraints {
                
                if let first = constraint.firstItem as? UIView, first == self {
                    superview.removeConstraint(constraint)
                }
                
                if let second = constraint.secondItem as? UIView, second == self {
                    superview.removeConstraint(constraint)
                }
            }
            
            _superview = superview.superview
        }
        
        self.removeConstraints(self.constraints)
        self.translatesAutoresizingMaskIntoConstraints = true
    }
}
marchinram
źródło
3
To powinna być oficjalna odpowiedź.
Jason Crocker
dlaczego masz self.translatesAutoresizingMaskIntoConstraints = YES; ? dosłownie nigdy nie chcesz tego w przypadku widoków, które konfigurujesz z ograniczeniami?
lensovet
4
Usuwam ograniczenia, więc chcę użyć ograniczeń autoresize po usunięciu innych ograniczeń, aby utrzymać go na miejscu, bez tej linii w moim kodzie widok
zniknąłby
Musiałem zarejestrować wszystkie ograniczenia w widoku w celu debugowania i mogłem nieznacznie zmodyfikować tę odpowiedź, aby to zrobić. +1
chiliNUT
Spowodowałoby to nieprawidłowe usunięcie C7. Jednak powinno być łatwe do naprawienia, jeśli usuniesz [self removeConstraints:self.constraints];i zmienisz UIView *superview = self.superview;na UIView *superview = self;.
Senseful
50

Jedynym rozwiązaniem, które do tej pory znalazłem, jest usunięcie widoku z jego superviewu:

[view removeFromSuperview]

Wygląda na to, że usuwa wszystkie ograniczenia wpływające na jego układ i jest gotowy do dodania do nadzoru i dołączenia nowych ograniczeń. Jednak spowoduje to niepoprawne usunięcie wszystkich podglądów podrzędnych z hierarchii i usunięcie [C7]nieprawidłowo.

Rozsądne
źródło
Możesz użyć właściwości firstItem i secondItem ograniczeń, aby sprawdzić, czy mają one zastosowanie do Twojego widoku i zapętlić hierarchię widoków, aby znaleźć je wszystkie. Myślę, że usunięcie i ponowne dodanie jest lepszym rozwiązaniem. Byłbym zainteresowany, aby zobaczyć Twój przypadek użycia, ponieważ wydaje się, że jest to bardzo zła rzecz. Twoje ograniczenia mogą łatwo stać się całkowicie nieważne, ponieważ inne widoki mogą polegać na tych ograniczeniach, aby się poprawnie rozłożyć.
bjtitus,
@bjtitus: Słuszna uwaga. Jednak w tym konkretnym przypadku zmieniam położenie widoku, który nie jest od niego zależny. Używa innych widoków, aby wiedzieć, gdzie ma zostać umieszczony, i nie ma widoków, które używają go, aby wiedzieć, gdzie ma zostać umieszczony.
Senseful
Nie jedyne rozwiązanie, ale bardzo proste. W moim przypadku właśnie usunąłem widok z superviewu, a później dodałem go ponownie.
Marián Černý
49

Możesz usunąć wszystkie ograniczenia w widoku, wykonując następujące czynności:

self.removeConstraints(self.constraints)

EDYCJA: Aby usunąć ograniczenia wszystkich podglądów podrzędnych, użyj następującego rozszerzenia w Swift:

extension UIView {
    func clearConstraints() {
        for subview in self.subviews {
            subview.clearConstraints()
        }
        self.removeConstraints(self.constraints)
    }
}
emdog4
źródło
22
Problem z tym rozwiązaniem polega na tym, że usuwa ono tylko ograniczenia, które posiada ten widok (np. Jego szerokość i wysokość). Nie usuwa takich rzeczy, jak ograniczenia wiodące i górne.
Senseful
2
Nie zweryfikowałem twojego komentarza powyżej. Uważam jednak, że działałoby to tak samo lub lepiej niż powyżej, [NSLayoutConstraint dezivateConstraints: self.constraints];
emdog4
2
To cierpiałoby na ten sam problem, co oryginalne rozwiązanie. self.constraintszwraca tylko ograniczenia, które są selfwłaścicielem, a nie wszystkie ograniczenia, które mają wpływ self.
Senseful
1
Rozumiem, co teraz mówisz. W mojej odpowiedzi usuwam ograniczenia z contentView UITableViewCell. Metoda updateConstraints dodałaby następnie ograniczenia dla wszystkich widoków podrzędnych i zresetowała układ. W moim pierwszym komentarzu powyżej powinienem wpisać self.view.constraints. Zarówno self.view, jak i self.contentView znajdują się na szczycie hierarchii widoków. Ustawienie translatesAutoresizingMasksToConstraints = YES na self.view lub self.contentView to zły pomysł. ;-). Nie lubię wywołań addSubview: w mojej metodzie updateConstraints usuwanie widoku z hierarchii wydaje mi się niepotrzebne.
emdog4
Właśnie zaktualizowałem pytanie, aby pokazać, dlaczego takie rozwiązanie nie będzie działać w przypadku tego, co chcę zrobić. Zakładając, że znajdujesz się w UITableViewCell, odpowiednikiem contentView jest Grandfather. Dlatego twoje rozwiązanie nieprawidłowo usuwałoby [C6], a nieprawidłowo nie usuwało [C0,C1,C2].
Senseful
20

Istnieją dwa sposoby, jak to osiągnąć, zgodnie z dokumentacją programisty Apple

1. NSLayoutConstraint.deactivateConstraints

Jest to wygodna metoda, która zapewnia łatwy sposób dezaktywacji zestawu ograniczeń jednym wywołaniem. Efekt tej metody jest taki sam, jak ustawienie właściwości isActive każdego ograniczenia na false. Zazwyczaj użycie tej metody jest bardziej wydajne niż osobne dezaktywowanie każdego ograniczenia.

// Declaration
class func deactivate(_ constraints: [NSLayoutConstraint])

// Usage
NSLayoutConstraint.deactivate(yourView.constraints)

2. UIView.removeConstraints(Przestarzałe dla> = iOS 8.0)

Podczas tworzenia aplikacji dla systemu iOS 8.0 lub nowszego należy użyć metody uninstallConstraints: klasy NSLayoutConstraint zamiast bezpośrednio wywoływać metodę removeConstraints:. Metoda uninstallConstraints: automatycznie usuwa ograniczenia z poprawnych widoków.

// Declaration
func removeConstraints(_ constraints: [NSLayoutConstraint])`

// Usage
yourView.removeConstraints(yourView.constraints)

Porady

Używanie Storyboards lub XIBs może być tak uciążliwe przy konfigurowaniu ograniczeń, jak wspomniano w twoim scenariuszu, musisz utworzyć IBOutlety dla każdego z nich, które chcesz usunąć. Mimo to przez większość czasuInterface Builder stwarza więcej problemów niż rozwiązuje.

Dlatego mając bardzo dynamiczną treść i różne stany widoku, sugerowałbym:

  1. Programowe tworzenie widoków
  2. Ułóż je i użyj NSLayoutAnchor
  3. Dołącz każde ograniczenie, które może zostać usunięte później, do tablicy
  4. Wyczyść je za każdym razem przed zastosowaniem nowego stanu

Prosty kod

private var customConstraints = [NSLayoutConstraint]()

private func activate(constraints: [NSLayoutConstraint]) {
    customConstraints.append(contentsOf: constraints)
    customConstraints.forEach { $0.isActive = true }
}

private func clearConstraints() {
    customConstraints.forEach { $0.isActive = false }
    customConstraints.removeAll()
}

private func updateViewState() {
    clearConstraints()

    let constraints = [
        view.leadingAnchor.constraint(equalTo: parentView.leadingAnchor),
        view.trailingAnchor.constraint(equalTo: parentView.trailingAnchor),
        view.topAnchor.constraint(equalTo: parentView.topAnchor),
        view.bottomAnchor.constraint(equalTo: parentView.bottomAnchor)
    ]

    activate(constraints: constraints)

    view.layoutIfNeeded()
}

Bibliografia

  1. NSLayoutConstraint
  2. UIView
E-Riddie
źródło
2
Bądź ostrożny. Widoki, które określają wewnętrzny rozmiar zawartości, będą miały NSContentSizeLayoutConstraint dodane automatycznie przez iOS. Usunięcie tego przez dostęp do zwykłej właściwości yourView.constraints spowoduje przerwanie automatycznego układu w tych widokach.
TigerCoding
Problem z tym rozwiązaniem polega na tym, że usuwa ono tylko ograniczenia, które posiada ten widok (np. Jego szerokość i wysokość). Nie usuwa takich rzeczy, jak ograniczenia wiodące i górne.
Senseful
Tak, co powiedział Senseful. Chociaż te metody istnieją, same nie rozwiązują problemu, o który w rzeczywistości chodzi.
GSnyder
18

W Swift:

import UIKit

extension UIView {

    /**
     Removes all constrains for this view
     */
    func removeConstraints() {

        let constraints = self.superview?.constraints.filter{
            $0.firstItem as? UIView == self || $0.secondItem as? UIView == self
        } ?? []

        self.superview?.removeConstraints(constraints)
        self.removeConstraints(self.constraints)
    }
}
Alexander Volkov
źródło
Spowoduje to awarię, jeśli twój widok nie ma nadzoru w „superview!”. Proszę zawiń część w „if let superview = superview” :)
Bersaelor
1
Nie usunie to wszystkich ograniczeń. Ograniczenia obejmują najbliższego rodzica 2 widoków, na które ma to wpływ, więc jeśli
utworzysz
2
być może bardziej poprawne byłoby porównanie tożsamości if c.firstItem === selfzamiast rzutowania as? UIViewi sprawdzenie równości z==
user1244109
Prawdopodobnie nie należy używać removeConstraints: from apple doc: // Metoda removeConstraints zostanie wycofana w przyszłej wersji i należy jej unikać. Zamiast tego użyj + [NSLayoutConstraint dezaktywuj ograniczenia:].
eonista
@eonist, odpowiedź brzmi: 3 lata temu. Zamiast krytykować, powinieneś go edytować.
Alexander Volkov
5

Detale

  • Xcode 10.2.1 (10E1001), Swift 5

Rozwiązanie

import UIKit

extension UIView {

    func removeConstraints() { removeConstraints(constraints) }
    func deactivateAllConstraints() { NSLayoutConstraint.deactivate(getAllConstraints()) }
    func getAllSubviews() -> [UIView] { return UIView.getAllSubviews(view: self) }

    func getAllConstraints() -> [NSLayoutConstraint] {
        var subviewsConstraints = getAllSubviews().flatMap { $0.constraints }
        if let superview = self.superview {
            subviewsConstraints += superview.constraints.compactMap { (constraint) -> NSLayoutConstraint? in
                if let view = constraint.firstItem as? UIView, view == self { return constraint }
                return nil
            }
        }
        return subviewsConstraints + constraints
    }

    class func getAllSubviews(view: UIView) -> [UIView] {
        return view.subviews.flatMap { [$0] + getAllSubviews(view: $0) }
    }
}

Stosowanie

print("constraints: \(view.getAllConstraints().count), subviews: \(view.getAllSubviews().count)")
view.deactivateAllConstraints()
Wasilij Bodnarczuk
źródło
1
To całkiem miłe.
eonista
2

Szybkie rozwiązanie:

extension UIView {
  func removeAllConstraints() {
    var view: UIView? = self
    while let currentView = view {
      currentView.removeConstraints(currentView.constraints.filter {
        return $0.firstItem as? UIView == self || $0.secondItem as? UIView == self
      })
      view = view?.superview
    }
  }
}

Ważne jest, aby przejść przez wszystkich rodziców, ponieważ ograniczenia między dwoma elementami są utrzymywane przez wspólnych przodków, więc samo wyczyszczenie superwizji, jak opisano w tej odpowiedzi, nie jest wystarczająco dobre, a później możesz mieć złą niespodziankę.

Guig
źródło
2

Na podstawie wcześniejszych odpowiedzi (szybki 4)

Możesz użyć directConstraints, jeśli nie chcesz przeszukiwać całych hierarchii.

extension UIView {
/**
 * Deactivates immediate constraints that target this view (self + superview)
 */
func deactivateImmediateConstraints(){
    NSLayoutConstraint.deactivate(self.immediateConstraints)
}
/**
 * Deactivates all constrains that target this view
 */
func deactiveAllConstraints(){
    NSLayoutConstraint.deactivate(self.allConstraints)
}
/**
 * Gets self.constraints + superview?.constraints for this particular view
 */
var immediateConstraints:[NSLayoutConstraint]{
    let constraints = self.superview?.constraints.filter{
        $0.firstItem as? UIView === self || $0.secondItem as? UIView === self
        } ?? []
    return self.constraints + constraints
}
/**
 * Crawls up superview hierarchy and gets all constraints that affect this view
 */
var allConstraints:[NSLayoutConstraint] {
    var view: UIView? = self
    var constraints:[NSLayoutConstraint] = []
    while let currentView = view {
        constraints += currentView.constraints.filter {
            return $0.firstItem as? UIView === self || $0.secondItem as? UIView === self
        }
        view = view?.superview
    }
    return constraints
}
}
eonista
źródło
2

Używam następującej metody, aby usunąć wszystkie ograniczenia z widoku:

plik .h:

+ (void)RemoveContraintsFromView:(UIView*)view 
    removeParentConstraints:(bool)parent 
    removeChildConstraints:(bool)child;

plik .m:

+ (void)RemoveContraintsFromView:(UIView *)view 
    removeParentConstraints:(bool)parent 
    removeChildConstraints:(bool)child
{
    if (parent) {
        // Remove constraints between view and its parent.
        UIView *superview = view.superview;
        [view removeFromSuperview];
        [superview addSubview:view];
    }

    if (child) {
        // Remove constraints between view and its children.
        [view removeConstraints:[view constraints]];
    }
}

Możesz również przeczytać ten post na moim blogu, aby lepiej zrozumieć, jak to działa za maską.

Jeśli potrzebujesz bardziej szczegółowej kontroli, zdecydowanie radzę przejść na Masonry , potężną klasę frameworkową, której możesz użyć, gdy potrzebujesz poprawnie obsługiwać ograniczenia programowo.

Darkseal
źródło
2

Łatwiejszym i skuteczniejszym podejściem jest usunięcie widoku z superView i ponowne dodanie jako podglądu podrzędnego. to powoduje, że wszystkie ograniczenia podglądu są usuwane automagicznie

Hashem Aboonajmi
źródło
1

Z celem C.

[self.superview.constraints enumerateObjectsUsingBlock:^(__kindof NSLayoutConstraint * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLayoutConstraint *constraint = (NSLayoutConstraint *)obj;
        if (constraint.firstItem == self || constraint.secondItem == self) {
            [self.superview removeConstraint:constraint];
        }
    }];
    [self removeConstraints:self.constraints];
}
Giang
źródło
0

Możesz użyć czegoś takiego:

[viewA.superview.constraints enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLayoutConstraint *constraint = (NSLayoutConstraint *)obj;
    if (constraint.firstItem == viewA || constraint.secondItem == viewA) {
        [viewA.superview removeConstraint:constraint];
    }
}];

[viewA removeConstraints:viewA.constraints];

Zasadniczo, to wylicza wszystkie ograniczenia superwizji widoku A i usuwa wszystkie ograniczenia, które są związane z widokiem A.

Następnie druga część usuwa ograniczenia z widoku A przy użyciu tablicy ograniczeń widoku A.

Tristan
źródło
1
Problem z tym rozwiązaniem polega na tym, że usuwa ono tylko ograniczenia, których właścicielem jest superview. Nie usuwa wszystkich ograniczeń wpływających na widok. (Np.
Równie
Właśnie zaktualizowałem pytanie, aby pokazać, dlaczego to rozwiązanie nie zadziała. Jest to najbliższe poprawności, ponieważ jest najbliższe rozwiązaniu brutalnej siły, o którym wspomniałem powyżej. Jednak to rozwiązanie nieprawidłowo usunie [C7]i nieprawidłowo nie usunie [C3,C4].
Senseful
możesz zaprojektować metodę przeszukiwania hierarchii. Ale to rozwiązanie jest wystarczająco dobre, ponieważ i tak powinieneś dodać ograniczenia powyżej bezpośredniego nadzoru. IMO
eonista
0

(Stan na 31 lipca 2017 r.)

SWIFT 3

self.yourCustomView.removeFromSuperview()
self.yourCustomViewParentView.addSubview(self.yourCustomView)

Cel C

[self.yourCustomView removeFromSuperview];
[self.yourCustomViewParentView addSubview:self.yourCustomView];

Jest to najłatwiejszy sposób na szybkie usunięcie wszystkich ograniczeń istniejących w UIView. Po prostu pamiętaj, aby dodać UIView z powrotem z nowymi ograniczeniami lub później nową ramką =)

BennyTheNerd
źródło
0

Korzystanie z sekwencji wielokrotnego użytku

Postanowiłem podejść do tego w sposób bardziej „wielokrotnego użytku”. Ponieważ znalezienie wszystkich ograniczeń wpływających na widok jest podstawą wszystkich powyższych, zdecydowałem się zaimplementować niestandardową sekwencję, która zwraca je wszystkie za mnie, wraz z widokami będącymi właścicielami.

Pierwszą rzeczą do zrobienia jest zdefiniowanie na przedłużenie Arrayso NSLayoutConstrainttym, że wszystkie elementy wpływające zwrotów widok konkretnego.

public extension Array where Element == NSLayoutConstraint {

    func affectingView(_ targetView:UIView) -> [NSLayoutConstraint] {

        return self.filter{

            if let firstView = $0.firstItem as? UIView,
                firstView == targetView {
                return true
            }

            if let secondView = $0.secondItem as? UIView,
                secondView == targetView {
                return true
            }

            return false
        }
    }
}

Następnie używamy tego rozszerzenia w niestandardowej sekwencji, która zwraca wszystkie ograniczenia wpływające na ten widok, wraz z widokami, które faktycznie je posiadają (które mogą znajdować się w dowolnym miejscu w hierarchii widoków)

public struct AllConstraintsSequence : Sequence {

    public init(view:UIView){
        self.view = view
    }

    public let view:UIView

    public func makeIterator() -> Iterator {
        return Iterator(view:view)
    }

    public struct Iterator : IteratorProtocol {

        public typealias Element = (constraint:NSLayoutConstraint, owningView:UIView)

        init(view:UIView){
            targetView  = view
            currentView = view
            currentViewConstraintsAffectingTargetView = currentView.constraints.affectingView(targetView)
        }

        private let targetView  : UIView
        private var currentView : UIView
        private var currentViewConstraintsAffectingTargetView:[NSLayoutConstraint] = []
        private var nextConstraintIndex = 0

        mutating public func next() -> Element? {

            while(true){

                if nextConstraintIndex < currentViewConstraintsAffectingTargetView.count {
                    defer{nextConstraintIndex += 1}
                    return (currentViewConstraintsAffectingTargetView[nextConstraintIndex], currentView)
                }

                nextConstraintIndex = 0

                guard let superview = currentView.superview else { return nil }

                self.currentView = superview
                self.currentViewConstraintsAffectingTargetView = currentView.constraints.affectingView(targetView)
            }
        }
    }
}

Na koniec deklarujemy rozszerzenie, UIViewaby uwidocznić wszystkie ograniczenia wpływające na to w prostej właściwości, do której można uzyskać dostęp za pomocą prostej składni for-each.

extension UIView {

    var constraintsAffectingView:AllConstraintsSequence {
        return AllConstraintsSequence(view:self)
    }
}

Teraz możemy iterować wszystkie ograniczenia wpływające na widok i robić z nimi, co chcemy ...

Wymień ich identyfikatory ...

for (constraint, _) in someView.constraintsAffectingView{
    print(constraint.identifier ?? "No identifier")
}

Dezaktywuj je ...

for (constraint, _) in someView.constraintsAffectingView{
    constraint.isActive = false
}

Lub usuń je całkowicie ...

for (constraint, owningView) in someView.constraintsAffectingView{
    owningView.removeConstraints([constraint])
}

Cieszyć się!

Mark A. Donohoe
źródło
0

Szybki

Następujące rozszerzenie UIView usunie wszystkie ograniczenia krawędzi widoku:

extension UIView {
    func removeAllConstraints() {
        if let _superview = self.superview {
            self.removeFromSuperview()
            _superview.addSubview(self)
        }
    }
}
Gurjit Singh
źródło
-1

Jest to sposób na wyłączenie wszystkich ograniczeń z określonego widoku

 NSLayoutConstraint.deactivate(myView.constraints)
user2501116
źródło
Problem z tym rozwiązaniem polega na tym, że usuwa ono tylko ograniczenia, które posiada ten widok (np. Jego szerokość i wysokość). Nie usuwa takich rzeczy, jak ograniczenia wiodące i górne.
Senseful