Bir UIV görünümünü etkileyen tüm kısıtlamaları kaldırın


90

Birkaç kısıtlamayla ekrana yerleştirilen bir UIView'ım var. Kısıtlamaların bazıları süpervizyona aittir, diğerleri diğer atalara aittir (örneğin bir UIViewController'ın view özelliği).

Tüm bu eski kısıtlamaları kaldırmak ve yeni kısıtlamaları kullanarak yeni bir yere yerleştirmek istiyorum.

Bunu, her bir kısıtlama için bir IBOutlet oluşturmadan ve hangi görünümün söz konusu kısıtlamaya sahip olduğunu hatırlamak zorunda kalmadan nasıl yapabilirim?

Ayrıntılı olarak açıklamak gerekirse, naif yaklaşım, kısıtlamaların her biri için bir grup IBOutlet oluşturmak ve ardından aşağıdaki gibi kodu çağırmak olacaktır:

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

Bu kodla ilgili sorun, en basit durumda bile 2 IBOutlet oluşturmam gerekmesidir. Karmaşık düzenler için bu, 4 veya 8 gerekli IBOutlet'e kolayca ulaşabilir. Ayrıca, kısıtlamayı kaldırmak için çağrımın uygun görünümde çağrıldığından emin olmam gerekir. Örneğin, bunun myViewsLeftConstraintsahibi olduğunu hayal edinviewA . Yanlışlıkla ararsam [self.view removeConstraint:self.myViewsLeftConstraint]hiçbir şey olmaz.

Not: yöntemi constraintsAffectingLayoutForAxis umut verici görünüyor, ancak yalnızca hata ayıklama amaçlarına yöneliktir.


Güncelleme: Ben anlaşmak alıyorum cevaplar çoğu self.constraints, self.superview.constraintsbunlardan veya bazı varyant. Bu yöntemler , görünümü etkileyen kısıtlamaları değil, yalnızca görünüme ait kısıtlamaları döndürdüğünden, bu çözümler işe yaramaz .

Sorunu bu çözümlerle açıklığa kavuşturmak için şu görünüm hiyerarşisini göz önünde bulundurun:

  • Büyük baba
    • Baba
      • Ben mi
        • Oğul
        • Kız evlat
      • Erkek kardeş
    • Amca dayı

Şimdi aşağıdaki kısıtlamaları yarattığımızı ve bunları her zaman en yakın ortak atalarına bağladığımızı hayal edin:

  • C0: Ben: Son ile aynı üstte (bana ait)
  • C1: Me: genişlik = 100 (bana ait)
  • C2: Ben: Brother ile aynı boyda (babaya ait)
  • C3: Ben: Amca ile aynı (Büyükbabaya ait)
  • C4: Ben: Büyükbaba ile aynı kaldı (Büyükbabaya ait)
  • C5: Kardeş: Baba ile aynı kaldı (Babanın sahibi)
  • C6: Amca: Büyükbaba ile aynı kaldı (Büyükbabaya ait)
  • C7: Oğul: Kızımla aynı kaldı (bana ait)

Şimdi, etkileyen tüm kısıtlamaları kaldırmak istediğimizi hayal edin Me. Herhangi bir uygun çözüm kaldırılmalı [C0,C1,C2,C3,C4]ve başka hiçbir şey olmamalıdır .

Kullanırsam self.constraints(benliğin Ben olduğu yerde), elde ederim [C0,C1,C7], çünkü bunlar Benim sahip olduğum tek kısıtlamalardır. Açıkçası, eksik olduğu için bunu kaldırmak yeterli olmayacaktır [C2,C3,C4]. Üstelik C7gereksiz yere kaldırıyor .

Kullanırsam self.superview.constraints(benliğin Ben olduğu yerde), elde ederim [C2,C5], çünkü bunlar Babanın sahip olduğu kısıtlamalardır. Açıkçası C5, tamamen ilgisiz olduğu için tüm bunları kaldıramayız Me.

Kullanırsam grandfather.constraintsalırım [C3,C4,C6]. Yine, tüm bunların C6bozulmadan kalması gerektiğinden bunları kaldıramayız .

Ham kuvvet yaklaşımıdır (kendisi de dahil olmak üzere) görünümün atalarının her döngü gerçekleştirmek için ve görmesini firstItemya da secondItemgörünüşüdür kendisidir; eğer öyleyse, bu kısıtlamayı kaldırın. Bu, geri dönen doğru bir çözüme götürecektir.[C0,C1,C2,C3,C4] ve yalnızca bu kısıtlamalara .

Bununla birlikte, atalar listesinin tamamında dolaşmaktan daha zarif bir çözüm olduğunu umuyorum.


Kaldırmak istediğiniz tüm kısıtlamalara bir tanımlayıcı koymaya ne dersiniz? Bu şekilde onlar için bir priz tutmanıza gerek kalmaz.
nsuinteger

Yanıtlar:


71

Bu yaklaşım benim için çalıştı:

@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

Tamamlandıktan sonra, görünümünüz otomatik olarak yeniden boyutlandırma kısıtlamaları yarattığı için olduğu yerde kalır. Bunu yapmadığım zaman genellikle görüntü kayboluyor. Ek olarak, yalnızca denetimden kısıtlamaları kaldırmakla kalmaz, aynı zamanda ata görünümlerinde onu etkileyen kısıtlamalar olabileceğinden tüm yol boyunca çapraz geçiş yapar.


Swift 4 Sürümü

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

3
Bu resmi cevap olmalı.
Jason Crocker

self.translatesAutoresizingMaskIntoConstraints'in neden var = YES; ? Kısıtlamalarla oluşturduğunuz görünümler için kelimenin tam anlamıyla bunu asla istemez misiniz?
lensovet

4
Kısıtlamaları kaldırıyorum, bu yüzden diğer kısıtlamaları kaldırdıktan sonra
kodumdaki

Hata ayıklama amacıyla bir görünümdeki tüm kısıtlamaları günlüğe kaydetmem gerekiyordu ve bunu yapmak için bu yanıtı biraz değiştirebildim. +1
chiliNUT

Bu yanlış bir şekilde kaldırılır C7. Ancak, kaldırmak eğer düzeltmek kolay olmalı [self removeConstraints:self.constraints];değişim ve UIView *superview = self.superview;için UIView *superview = self;.
Duyarlı

50

Şimdiye kadar bulduğum tek çözüm, görünümü gözetim görünümünden kaldırmak:

[view removeFromSuperview]

Bu, düzenini etkileyen tüm kısıtlamaları kaldırdığı ve bir süpervizyona eklenmeye ve yeni kısıtlamalar eklenmeye hazır gibi görünüyor. Bununla birlikte, herhangi bir alt görüntülemeyi de hiyerarşiden yanlışlıkla kaldıracak ve yanlış bir şekilde ortadan kaldıracaktır [C7].


Kısıtlamaların firstItem ve secondItem özelliklerini, görünümünüze uygulanıp uygulanmadıklarını kontrol etmek ve tümünü bulmak için görünüm hiyerarşisi boyunca döngü yapmak için kullanabilirsiniz. Yine de kaldırıp yeniden eklemenin daha iyi bir çözüm olduğunu düşünüyorum. Bunu yapmak çok kötü bir şey gibi göründüğü için kullanım durumunuzu görmek isterim. Diğer görüşler düzgün bir şekilde düzenlenmesi için bu kısıtlamalara güveniyor olabileceğinden, kısıtlamalarınız kolayca tamamen geçersiz hale gelebilir.
bjtitus

@bjtitus: İyi nokta. Bununla birlikte, bu özel durumda, ona bağlı hiçbir şeyi olmayan bir görüşü yeniden konumlandırıyorum. Nereye yerleştirileceğini bilmek için başka görünümler kullanır ve nereye yerleştirileceğini bilmek için onu kullanan hiçbir görünüm yoktur.
Duyarlı

Tek çözüm değil, çok basit. Benim kullanım durumumda, görünümü sadece gözetimden kaldırdım ve daha sonra yeniden ekledim.
Marián Černý

49

Bunu yaparak bir görünümdeki tüm kısıtlamaları kaldırabilirsiniz:

self.removeConstraints(self.constraints)

DÜZENLEME: Tüm alt görünümlerin kısıtlamalarını kaldırmak için Swift'de aşağıdaki uzantıyı kullanın:

extension UIView {
    func clearConstraints() {
        for subview in self.subviews {
            subview.clearConstraints()
        }
        self.removeConstraints(self.constraints)
    }
}

22
Bu çözümle ilgili sorun, yalnızca bu görüşün sahip olduğu kısıtlamaları (örneğin genişliği ve yüksekliği) ortadan kaldırmasıdır. Baştaki ve en üstteki kısıtlamalar gibi şeyleri kaldırmaz.
2014

2
Yukarıdaki yorumunuzu doğrulamadım. Ancak, bunun yukarıdakiyle aynı veya daha iyi çalışacağına inanıyorum, [NSLayoutConstraint deactivateConstraints: self.constraints];
emdog4

2
Bu, orijinal çözümle aynı sorundan muzdariptir. self.constraintsYalnızca selfsahip olan kısıtlamaları döndürür, etkileyen tüm kısıtlamaları döndürmez self.
2014

1
Şimdi ne dediğini anlıyorum. Benim içinde cevap , ben UITableViewCell en contentView gelen sınırlarını kaldırmayı ediyorum. UpdateConstraints yöntemi daha sonra tüm alt görünümler için kısıtlamalar ekler ve düzeni sıfırlar. İlk olarak açıklama yukarıda, ben yazılan self.view.constraints sahip olmalıdır. Hem self.view hem de self.contentView, görünüm hiyerarşisinin en üstündedir. TranslatesAutoresizingMasksToConstraints = self.view veya self.contentView üzerinde YES ayarı kötü bir fikirdir. ;-). AddSubview çağrılarını sevmiyorum: updateConstraints yöntemimde görünümü hiyerarşiden kaldırmak gereksiz imo gibi görünüyor.
emdog4

Yapmak istediğim şey için neden böyle bir çözümün işe yaramayacağını göstermek için soruyu güncelledim. Bir UITableViewCell içinde olduğunuzu varsayarsak, contentView'in eşdeğeri Grandfather'dir. Bu nedenle, çözümünüz yanlış bir şekilde kaldırılır [C6]ve yanlış bir şekilde kaldırılmaz [C0,C1,C2].
Senseful

20

Apple Geliştirici Belgelerine göre bunu başarmanın iki yolu var.

1. NSLayoutConstraint.deactivateConstraints

Bu, bir dizi kısıtlamayı tek bir arama ile devre dışı bırakmanın kolay bir yolunu sağlayan kullanışlı bir yöntemdir. Bu yöntemin etkisi, her kısıtlamanın isActive özelliğini false olarak ayarlamakla aynıdır. Tipik olarak, bu yöntemi kullanmak, her kısıtlamayı tek tek devre dışı bırakmaktan daha etkilidir.

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

// Usage
NSLayoutConstraint.deactivate(yourView.constraints)

2. UIView.removeConstraints(> = iOS 8.0 için kullanımdan kaldırılmıştır)

İOS 8.0 veya üstü için geliştirme yaparken, doğrudan removeConstraints: yöntemini çağırmak yerine NSLayoutConstraint sınıfının deactivateConstraints: yöntemini kullanın. DeactivateConstraints: yöntemi, kısıtlamaları doğru görünümlerden otomatik olarak kaldırır.

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

// Usage
yourView.removeConstraints(yourView.constraints)

İpuçları

StoryboardS veya XIBs kullanmak , senaryonuzda bahsedildiği gibi kısıtlamaları yapılandırmada çok zor olabilir, kaldırmak istediğiniz her biri için IBOutlet'ler oluşturmanız gerekir. Öyle bile olsa, çoğu zaman Interface Builderçözdüğünden daha fazla sorun yaratır.

Bu nedenle, çok dinamik bir içeriğe ve farklı görüş durumlarına sahipken şunları öneririm:

  1. Görünümlerinizi programlı olarak oluşturma
  2. Onları düzenleyin ve NSLayoutAnchor kullanarak
  3. Daha sonra kaldırılabilecek her kısıtlamayı bir diziye ekleyin
  4. Yeni durumu uygulamadan önce her seferinde bunları temizleyin

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

Referanslar

  1. NSLayoutConstraint
  2. UIView

2
Dikkatli ol. İç içerik boyutunu belirten görünümlerde NSContentSizeLayoutConstraint, iOS tarafından otomatik olarak eklenir. Normal yourView.constraints özelliğine erişerek bunu kaldırmak, bu görünümler üzerindeki otomatik düzeni bozacaktır.
TigerCoding

Bu çözümle ilgili sorun, yalnızca bu görüşün sahip olduğu kısıtlamaları (örneğin genişliği ve yüksekliği) ortadan kaldırmasıdır. Baştaki ve en üstteki sınırlamalar gibi şeyleri kaldırmaz.
Senseful

Evet, Senseful ne dedi. Bu yöntemler var olmasına rağmen, sorunun aslında sorduğu sorunu kendi başlarına çözmezler.
GSnyder

18

Swift'de:

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

Görünümünüzün 'denetleme!' De denetim görüntüleme yoksa bu kilitlenir. Lütfen bölümü bir 'if let
supiew

1
Bu, tüm kısıtlamaları kaldırmayacaktır. Kısıtlamalar, etkilenen 2 görünümün en yakın ebeveynini alır, bu nedenle, bu görünümün
denetimini

2
belki de daha doğru if c.firstItem === self, oyuncu as? UIView==
seçimi

Muhtemelen removeConstraints kullanılmamalıdır: from apple doc: // removeConstraints yöntemi, gelecekteki bir sürümde kullanımdan kaldırılacaktır ve bundan kaçınılmalıdır. Bunun yerine + [NSLayoutConstraint deactivateConstraints:] kullanın.
eonist

@eonist cevap 3 yıl önce. Eleştiri yerine onu düzenlemelisiniz.
Alexander Volkov

5

Detaylar

  • Xcode 10.2.1 (10E1001), Swift 5

Çözüm

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

Kullanım

print("constraints: \(view.getAllConstraints().count), subviews: \(view.getAllSubviews().count)")
view.deactivateAllConstraints()

1
Oldukça güzel.
eonist

2

Hızlı bir çözüm:

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

İki öğe arasındaki kısıtlamalar ortak atalar tarafından tutulduğundan, tüm üst öğelerin üzerinden geçmek önemlidir, bu nedenle, bu cevapta yeterince iyi değildir ve daha sonra kötü bir sürprizle karşılaşabilirsiniz.


2

Önceki cevaplara göre (hızlı 4)

Tüm hiyerarşileri taramak istemediğinizde, instantConstraints'i kullanabilirsiniz.

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

2

Bir görünümden tüm kısıtlamaları kaldırmak için aşağıdaki yöntemi kullanıyorum:

.h dosyası:

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

.m dosyası:

+ (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]];
    }
}

Kaputun arkasında nasıl çalıştığını daha iyi anlamak için bu yazıyı blogumda da okuyabilirsiniz .

Daha ayrıntılı denetime ihtiyacınız varsa, programlı olarak kısıtlamaları düzgün bir şekilde işlemeniz gerektiğinde kullanabileceğiniz güçlü bir çerçeve sınıfı olan Masonry'ye geçmenizi şiddetle tavsiye ederim .


2

Daha kolay ve verimli yaklaşım, görünümü superView'den kaldırmak ve tekrar alt görünüm olarak eklemektir. bu, tüm alt görünüm kısıtlamalarının otomatik olarak kaldırılmasına neden olur.


1

ObjectC ile

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

0

Bunun gibi bir şey kullanabilirsiniz:

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

Temel olarak, bu, görünümA'nın denetimindeki tüm kısıtlamaları numaralandırır ve görünümA ile ilgili tüm kısıtlamaları kaldırır.

Daha sonra, ikinci kısım, viewA'nın kısıtlamalarını kullanarak kısıtlamaları viewA'dan kaldırır.


1
Bu çözümle ilgili sorun, yalnızca denetimin sahip olduğu kısıtlamaları kaldırmasıdır. Görünümü etkileyen tüm kısıtlamaları kaldırmaz. (Örneğin, bu çözüm kullanılarak kaldırılmayacak olan,
süpervizörün süpervizörünün süpervizasyonu

Bu çözümün neden işe yaramayacağını göstermek için soruyu güncelledim. Yukarıda bahsettiğim kaba kuvvet çözümüne en yakın olduğu için bu doğru olmaya en yakın olanıdır. Ancak bu çözüm yanlış bir şekilde kaldırılacak [C7]ve yanlış bir şekilde kaldırılmayacaktır [C3,C4].
Senseful

hiyerarşiyi taramak için bir yöntem tasarlayabilirsiniz. Ancak bu çözüm yeterince iyidir, çünkü her halükarda acil denetimin üzerine kısıtlamalar eklemeniz gerekir. IMO
eonist

0

(31 Temmuz 2017 itibariyle)

SWIFT 3

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

Hedef C

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

Bu, bir UIView'de bulunan tüm kısıtlamaları hızlı bir şekilde kaldırmanın en kolay yoludur. UIView'ı yeni kısıtlamalarla veya daha sonra yeni çerçeveyle geri eklediğinizden emin olun =)


0

Yeniden Kullanılabilir Bir Sıra Kullanma

Buna daha 'yeniden kullanılabilir' bir şekilde yaklaşmaya karar verdim. Bir görünümü etkileyen tüm kısıtlamaları bulmak yukarıdakilerin temelini oluşturduğundan, sahip olunan görünümlerle birlikte hepsini benim için döndüren özel bir sıra uygulamaya karar verdim.

Yapılacak ilk şey bir uzantı tanımlamak olduğu Arraysbir NSLayoutConstrainto iadeler belirli bir görünümünü etkileyen tüm unsurları.

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

Daha sonra, bu uzantıyı, o görünümü etkileyen tüm kısıtlamaları ve gerçekte onlara sahip olan görünümleri (görünüm hiyerarşisinin herhangi bir yerinde olabilir) döndüren özel bir dizide kullanırız.

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

Son olarak UIView, onu etkileyen tüm kısıtlamaları, her biri için basit bir sözdizimi ile erişebileceğiniz basit bir özellikte ortaya çıkarmak için bir uzantı bildiriyoruz.

extension UIView {

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

Artık bir görünümü etkileyen tüm kısıtlamaları yineleyebilir ve onlarla istediğimizi yapabiliriz ...

Tanımlayıcılarını listeleyin ...

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

Onları devre dışı bırakın ...

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

Veya tamamen kaldırın ...

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

Zevk almak!


0

Swift

UIView Uzantısının ardından bir görünümün tüm Edge kısıtlamaları kaldırılır:

extension UIView {
    func removeAllConstraints() {
        if let _superview = self.superview {
            self.removeFromSuperview()
            _superview.addSubview(self)
        }
    }
}

-1

Bu, belirli bir görünümden tüm kısıtlamaları devre dışı bırakmanın yoludur

 NSLayoutConstraint.deactivate(myView.constraints)

Bu çözümle ilgili sorun, yalnızca bu görüşün sahip olduğu kısıtlamaları (örneğin genişliği ve yüksekliği) ortadan kaldırmasıdır. Baştaki ve en üstteki sınırlamalar gibi şeyleri kaldırmaz.
Senseful
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.