Hapus semua batasan yang memengaruhi UIView

90

Saya memiliki UIView yang ditempatkan di layar melalui beberapa kendala. Beberapa batasan dimiliki oleh superview, yang lainnya dimiliki oleh leluhur lain (misalnya, mungkin properti tampilan dari UIViewController).

Saya ingin menghapus semua batasan lama ini, dan menempatkannya di tempat baru menggunakan batasan baru.

Bagaimana saya bisa melakukan ini tanpa membuat IBOutlet untuk setiap batasan dan harus mengingat tampilan mana yang memiliki batasan tersebut?

Untuk menguraikan, pendekatan naif akan membuat sekelompok IBOutlet untuk setiap batasan, dan kemudian akan melibatkan kode panggilan seperti:

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

Masalah dengan kode ini adalah bahwa bahkan dalam kasus yang paling sederhana, saya perlu membuat 2 IBOutlets. Untuk tata letak yang kompleks, ini dapat dengan mudah mencapai 4 atau 8 IBOutlet yang diperlukan. Selain itu, saya perlu memastikan bahwa panggilan saya untuk menghapus batasan dipanggil pada tampilan yang tepat. Misalnya, bayangkan yang myViewsLeftConstraintdimiliki olehviewA . Jika saya tidak sengaja menelepon [self.view removeConstraint:self.myViewsLeftConstraint], tidak akan terjadi apa-apa.

Catatan: Metode constraintsAffectingLayoutForAxis terlihat menjanjikan, tetapi dimaksudkan untuk tujuan debug saja.


Update: Banyak jawaban saya menerima kesepakatan dengan self.constraints, self.superview.constraintsatau beberapa varian dari mereka. Solusi ini tidak akan berfungsi karena metode tersebut hanya mengembalikan batasan yang dimiliki oleh tampilan, bukan yang memengaruhi tampilan.

Untuk memperjelas masalah dengan solusi ini, pertimbangkan hierarki tampilan ini:

  • Kakek
    • Ayah
      • Saya
        • Putra
        • Putri
      • Saudara
    • Paman

Sekarang bayangkan kita membuat batasan berikut, dan selalu melampirkannya ke leluhur terdekat yang terdekat:

  • C0: Aku: sama dengan Anak (milik Aku)
  • C1: Me: width = 100 (milik Me)
  • C2: Aku: sama tingginya dengan Kakak (milik Ayah)
  • C3: Saya: sama dengan Paman (milik Kakek)
  • C4: Saya: kiri sama dengan Kakek (milik Kakek)
  • C5: Kakak: kiri sama dengan Ayah (milik Ayah)
  • C6: Paman: kiri sama dengan Kakek (milik Kakek)
  • C7: Putra: kiri sama dengan Putri (milik Saya)

Sekarang bayangkan kita ingin menghapus semua kendala yang mempengaruhi Me. Solusi yang tepat harus dihapus [C0,C1,C2,C3,C4]dan tidak ada yang lain.

Jika Aku menggunakan self.constraints(di mana diri adalah Aku), aku akan mendapatkannya [C0,C1,C7], karena hanya itu kendala yang dimiliki oleh-Ku. Jelas itu tidak akan cukup untuk menghapus ini karena hilang [C2,C3,C4]. Selain itu, menghapus secara C7tidak perlu.

Jika saya pakai self.superview.constraints(di mana diri adalah Aku), saya akan dapatkan [C2,C5], karena itu adalah kendala yang dimiliki oleh Bapa. Jelas kami tidak dapat menghapus semua ini karena C5sama sekali tidak terkait dengan Me.

Jika saya menggunakan grandfather.constraints, saya akan mendapatkan [C3,C4,C6]. Sekali lagi, kami tidak dapat menghapus semua ini karena C6harus tetap utuh.

Pendekatan kekerasan adalah untuk loop atas setiap nenek moyang pandangan (termasuk dirinya sendiri), dan melihat apakah firstItematau secondItemadalah pandangan sendiri; jika demikian, hilangkan batasan itu. Ini akan mengarah pada solusi yang benar, kembali [C0,C1,C2,C3,C4], dan hanya kendala itu.

Namun, saya berharap ada solusi yang lebih elegan daripada harus menelusuri seluruh daftar leluhur.

Senseful
sumber
Bagaimana kalau Anda menempatkan pengenal untuk semua kendala yang ingin Anda hapus? Dengan cara ini Anda tidak perlu menyimpan jalan keluar untuk mereka.
nsuinteger

Jawaban:

71

Pendekatan ini berhasil untuk saya:

@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

Setelah selesai mengeksekusi tampilan Anda tetap di tempatnya karena itu menciptakan batasan autoresisasi. Jika saya tidak melakukan ini, pemandangan biasanya menghilang. Selain itu, ini tidak hanya menghapus batasan dari superview tetapi juga melintasi seluruhnya karena mungkin ada batasan yang mempengaruhinya dalam tampilan leluhur.


Versi 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
sumber
3
Ini harus menjadi jawaban resmi.
Jason Crocker
mengapa Anda memiliki self.translatesAutoresizingMaskIntoConstraints = YES; ? Anda benar-benar tidak pernah menginginkan ini untuk tampilan yang Anda siapkan dengan kendala?
lensovet
4
Saya menghapus batasan, jadi saya ingin menggunakan batasan ukuran otomatis setelah saya menghapus batasan lain untuk menahannya, tanpa baris itu di kode saya tampilan akan hilang
marchinram
Saya perlu mencatat semua batasan pada tampilan untuk tujuan debugging dan saya dapat mengubah jawaban ini sedikit untuk melakukannya. +1
cabaiNUT
Ini akan salah menghapus C7. Namun, ini akan mudah diperbaiki jika Anda menghapus [self removeConstraints:self.constraints];dan mengubahnya UIView *superview = self.superview;ke UIView *superview = self;.
Senseful
50

Satu-satunya solusi yang saya temukan sejauh ini adalah menghapus tampilan dari superview-nya:

[view removeFromSuperview]

Sepertinya ini menghapus semua batasan yang memengaruhi tata letaknya dan siap ditambahkan ke superview dan memasang batasan baru. Namun, ini juga akan menghapus subview dari hierarki dengan benar, dan menghapusnya dengan [C7]tidak benar.

Senseful
sumber
Anda bisa menggunakan properti firstItem dan secondItem dari batasan untuk memeriksa apakah mereka berlaku untuk tampilan Anda dan memutar melalui hierarki tampilan untuk menemukan semuanya. Saya pikir menghapus dan menambahkan kembali adalah solusi yang lebih baik. Saya tertarik untuk melihat kasus penggunaan Anda karena sepertinya hal ini sangat buruk untuk dilakukan. Batasan Anda bisa dengan mudah menjadi tidak valid karena tampilan lain mungkin mengandalkan batasan tersebut untuk menata dengan benar.
bjtitus
@bjtitus: Poin yang bagus. Namun, dalam kasus khusus ini, saya mengubah posisi tampilan yang tidak bergantung padanya. Ia menggunakan pandangan lain untuk mengetahui di mana harus ditempatkan, dan tidak ada pandangan yang menggunakannya untuk mengetahui di mana harus ditempatkan.
Penuh perasaan
Bukan satu-satunya solusi, tapi sangat sederhana. Dalam kasus penggunaan saya, saya baru saja menghapus tampilan dari superview dan kemudian menambahkannya kembali nanti.
Marián Černý
49

Anda dapat menghapus semua batasan dalam satu tampilan dengan melakukan ini:

self.removeConstraints(self.constraints)

EDIT: Untuk menghapus batasan semua subview, gunakan ekstensi berikut di Swift:

extension UIView {
    func clearConstraints() {
        for subview in self.subviews {
            subview.clearConstraints()
        }
        self.removeConstraints(self.constraints)
    }
}
emdog4
sumber
22
Masalah dengan solusi ini adalah ia hanya menghilangkan kendala yang dimiliki tampilan ini (misalnya lebar dan tinggi). Itu tidak menghapus hal-hal seperti kendala utama dan teratas.
Masuk akal
2
Saya belum memverifikasi komentar Anda di atas. Namun, saya yakin ini akan bekerja sama atau lebih baik daripada di atas, [NSLayoutConstraint deactivateConstraints: self.constraints];
emdog4
2
Itu akan mengalami masalah yang sama dengan solusi aslinya. self.constraintshanya mengembalikan batasan yang selfdimiliki, tidak semua batasan yang mempengaruhi self.
Masuk akal
1
Saya mengerti apa yang Anda katakan sekarang. Dalam jawaban saya , saya menghapus batasan dari contentView UITableViewCell. Metode updateConstraints kemudian akan menambahkan batasan untuk semua subview dan mengatur ulang tata letak. Dalam komentar pertama saya di atas, saya seharusnya mengetik self.view.constraints. Self.view dan self.contentView berada di bagian atas hierarki tampilan. Menetapkan translatesAutoresizingMasksToConstraints = YA di self.view atau self.contentView adalah ide yang buruk. ;-). Saya tidak suka panggilan ke addSubview: dalam metode updateConstraints saya, menghapus tampilan dari hierarki tampaknya tidak perlu.
emdog4
Saya baru saja memperbarui pertanyaan untuk menunjukkan mengapa solusi seperti ini tidak berfungsi untuk apa yang ingin saya lakukan. Dengan asumsi Anda berada dalam UITableViewCell, konten yang setara dengan contentView adalah Grandfather. Oleh karena itu solusi Anda akan salah menghapus [C6], dan salah tidak menghapus [C0,C1,C2].
Masuk akal
20

Ada dua cara bagaimana mencapai itu menurut Dokumentasi Pengembang Apple

1. NSLayoutConstraint.deactivateConstraints

Ini adalah metode praktis yang menyediakan cara mudah untuk menonaktifkan sekumpulan batasan dengan satu panggilan. Efek dari metode ini sama dengan menyetel properti isActive dari setiap batasan ke false. Biasanya, menggunakan metode ini lebih efisien daripada menonaktifkan setiap batasan secara individual.

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

// Usage
NSLayoutConstraint.deactivate(yourView.constraints)

2. UIView.removeConstraints(Tidak digunakan lagi untuk> = iOS 8.0)

Saat mengembangkan untuk iOS 8.0 atau yang lebih baru, gunakan metode deactivateConstraint: kelas NSLayoutConstraint daripada memanggil metode removeConstraints: secara langsung. Metode deactivateConstraints: secara otomatis menghapus batasan dari tampilan yang benar.

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

// Usage
yourView.removeConstraints(yourView.constraints)

Tips

Menggunakan Storyboards atau XIBs bisa sangat merepotkan dalam mengonfigurasi batasan seperti yang disebutkan pada skenario Anda, Anda harus membuat IBOutlet untuk setiap yang ingin Anda hapus. Meski begitu, sebagian besar waktu Interface Buildermenciptakan lebih banyak masalah daripada menyelesaikannya.

Oleh karena itu, ketika memiliki konten yang sangat dinamis dan keadaan tampilan yang berbeda, saya akan menyarankan:

  1. Membuat tampilan Anda secara terprogram
  2. Tata letak mereka dan gunakan NSLayoutAnchor
  3. Tambahkan setiap batasan yang mungkin dihapus nanti ke larik
  4. Hapus mereka setiap kali sebelum menerapkan status baru

Kode Sederhana

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

Referensi

  1. NSLayoutConstraint
  2. UIView
E-Riddie
sumber
2
Hati-hati. Tampilan yang menentukan ukuran konten intrinsik akan ditambahkan NSContentSizeLayoutConstraint secara otomatis oleh iOS. Menghapus ini dengan mengakses properti yourView.constraints normal akan merusak autolayout pada tampilan tersebut.
TigerCoding
Masalah dengan solusi ini adalah ia hanya menghilangkan kendala yang dimiliki tampilan ini (misalnya lebar dan tinggi). Itu tidak menghapus hal-hal seperti kendala utama dan teratas.
Berasa
Ya, apa yang Senseful katakan. Meskipun metode ini benar-benar ada, metode ini tidak dengan sendirinya memecahkan masalah yang sebenarnya ditanyakan.
GSnyder
18

Di 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
sumber
Ini akan macet jika tampilan Anda tidak memiliki superview di 'superview!'. Harap bungkus bagian tersebut menjadi 'if let superview = superview' :)
Bersaelor
1
Ini tidak akan menghilangkan semua batasan. Batasan mengambil induk terdekat dari 2 tampilan yang terpengaruh, jadi jika Anda membuat batasan yang tidak membagikan superview dari tampilan ini, batasan itu tidak akan dihapus ...
vrwim
2
mungkin yang lebih tepat adalah membandingkan identitas if c.firstItem === selfdaripada mentransmisikan as? UIViewdan memeriksa kesetaraan dengan==
pengguna1244109
Mungkin sebaiknya tidak menggunakan removeConstraints: from apple doc: // Metode removeConstraints tidak akan digunakan lagi di rilis mendatang dan harus dihindari. Sebagai gantinya gunakan + [NSLayoutConstraint deactivateConstraints:].
eonist
@eonist jawabannya 3 tahun yang lalu. Alih-alih kritik, Anda harus mengeditnya.
Alexander Volkov
5

Detail

  • Xcode 10.2.1 (10E1001), Swift 5

Larutan

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

Pemakaian

print("constraints: \(view.getAllConstraints().count), subviews: \(view.getAllSubviews().count)")
view.deactivateAllConstraints()
Bodnarchuk dengan mudah
sumber
1
Cukup bagus.
eonist
2

Solusi Cepat:

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

Penting untuk membahas semua orang tua, karena batasan antara dua elemen dipegang oleh nenek moyang yang sama, jadi menghapus superview seperti yang dijelaskan dalam jawaban ini tidak cukup baik, dan Anda mungkin akan mendapatkan kejutan buruk di kemudian hari.

Guig
sumber
2

Berdasarkan jawaban sebelumnya (swift 4)

Anda dapat menggunakan segeraConstraints jika tidak ingin merayapi seluruh hierarki.

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
}
}
eonist
sumber
2

Saya menggunakan metode berikut untuk menghapus semua kendala dari tampilan:

file .h:

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

file .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]];
    }
}

Anda juga dapat membaca posting ini di blog saya untuk lebih memahami cara kerjanya di balik terpal.

Jika Anda memerlukan kontrol yang lebih terperinci, saya sangat menyarankan untuk beralih ke Masonry , kelas kerangka kerja yang kuat yang dapat Anda gunakan kapan pun Anda perlu menangani batasan secara terprogram dengan benar.

Darkseal
sumber
2

Pendekatan yang lebih mudah dan efisien adalah menghapus tampilan dari superView dan menambahkan kembali sebagai subview lagi. ini menyebabkan semua batasan subview dihapus secara otomatis.😉

Hashem Aboonajmi
sumber
1

Dengan objektifC

[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
sumber
0

Anda bisa menggunakan sesuatu seperti ini:

[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];

Pada dasarnya, ini menyebutkan semua batasan pada superview viewA dan menghapus semua batasan yang terkait dengan viewA.

Kemudian, bagian kedua menghilangkan batasan dari viewA menggunakan larik batasan viewA.

Tristan
sumber
1
Masalah dengan solusi ini adalah ia hanya menghilangkan kendala yang dimiliki oleh superview. Itu tidak menghapus semua batasan yang mempengaruhi tampilan. (Misalnya, Anda dapat dengan mudah mengatur batasan pada
superview superview
Saya baru saja memperbarui pertanyaan untuk menunjukkan mengapa solusi ini tidak akan berhasil. Ini paling mendekati benar, karena paling dekat dengan solusi brute force yang saya sebutkan di atas. Namun, solusi ini salah akan menghapus [C7]dan salah tidak akan menghapus [C3,C4].
Masuk akal
Anda dapat mendesain metode untuk merayapi hierarki. Tetapi solusi ini cukup baik, karena Anda harus menambahkan batasan di atas segera superview. IMO
eonist
0

(Per 31 Juli 2017)

SWIFT 3

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

Tujuan C

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

Ini adalah cara termudah untuk dengan cepat menghapus semua kendala yang ada di UIView. Pastikan untuk menambahkan UIView kembali dengan batasan baru atau bingkai baru setelahnya =)

BennyTheNerd
sumber
0

Menggunakan Urutan yang Dapat Digunakan Kembali

Saya memutuskan untuk melakukan pendekatan ini dengan cara yang lebih 'dapat digunakan kembali'. Karena menemukan semua batasan yang memengaruhi tampilan adalah dasar untuk semua hal di atas, saya memutuskan untuk menerapkan urutan khusus yang mengembalikan semuanya untuk saya, bersama dengan tampilan yang dimiliki.

Hal pertama yang harus dilakukan adalah menentukan perpanjangan Arraysdari NSLayoutConstraintyang kembali semua elemen yang mempengaruhi pandangan tertentu.

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

Kami kemudian menggunakan ekstensi itu dalam urutan kustom yang mengembalikan semua batasan yang memengaruhi tampilan tersebut, bersama dengan tampilan yang benar-benar memilikinya (yang bisa berada di mana saja di atas hierarki tampilan)

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

Akhirnya kami mendeklarasikan ekstensi on UIViewuntuk mengekspos semua batasan yang mempengaruhinya dalam properti sederhana yang dapat Anda akses dengan sintaks sederhana untuk setiap.

extension UIView {

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

Sekarang kita dapat mengulangi semua batasan yang memengaruhi tampilan dan melakukan apa yang kita inginkan dengannya ...

Cantumkan pengenal mereka ...

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

Nonaktifkan mereka ...

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

Atau hapus seluruhnya ...

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

Nikmati!

Mark A. Donohoe
sumber
0

Cepat

Mengikuti Ekstensi UIView akan menghapus semua batasan Edge dari sebuah tampilan:

extension UIView {
    func removeAllConstraints() {
        if let _superview = self.superview {
            self.removeFromSuperview()
            _superview.addSubview(self)
        }
    }
}
Gurjit Singh
sumber
-1

Ini adalah cara untuk menonaktifkan semua kendala dari tampilan tertentu

 NSLayoutConstraint.deactivate(myView.constraints)
pengguna2501116
sumber
Masalah dengan solusi ini adalah ia hanya menghilangkan kendala yang dimiliki tampilan ini (misalnya lebar dan tinggi). Itu tidak menghapus hal-hal seperti kendala utama dan teratas.
Masuk akal