UIView को प्रभावित करने वाली सभी बाधाओं को दूर करें


90

मेरे पास एक UIView है जिसे कई बाधाओं के माध्यम से स्क्रीन पर रखा गया है। कुछ बाधाओं का पर्यवेक्षण पर्यवेक्षक के स्वामित्व में है, अन्य अन्य पूर्वजों के स्वामित्व में हैं (उदाहरण के लिए शायद एक यूआईवाईवीसींट्रोलर की संपत्ति देखें)।

मैं इन सभी पुरानी बाधाओं को दूर करना चाहता हूं, और नए अवरोधों का उपयोग करके इसे कहीं नए स्थान पर रखना चाहता हूं।

मैं हर एक बाधा के लिए एक IBOutlet बनाए बिना यह कैसे कर सकता हूं और यह याद रखना चाहिए कि कौन सा दृश्य स्वामित्व कहा गया है।

विस्तृत करने के लिए, भोले दृष्टिकोण प्रत्येक बाधा के लिए IBOutlets का एक गुच्छा बनाने के लिए होगा, और फिर कॉलिंग कोड जैसे:

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

इस कोड के साथ समस्या यह है कि सबसे सरल मामले में भी, मुझे 2 IBOutlets बनाने की आवश्यकता होगी। जटिल लेआउट के लिए, यह आसानी से 4 या 8 आवश्यक IBOutlets तक पहुंच सकता है। इसके अलावा, मुझे यह सुनिश्चित करने की आवश्यकता होगी कि बाधा को दूर करने के लिए मेरा फोन उचित दृष्टिकोण पर बुलाया जा रहा है। उदाहरण के लिए, कल्पना करें कि myViewsLeftConstraintयह किसके स्वामित्व में है viewA। अगर मैं गलती से कॉल करता [self.view removeConstraint:self.myViewsLeftConstraint], तो कुछ नहीं होता।

नोट: विधि constraintsAffectingLayoutForAxis होनहार लग रही है, लेकिन केवल डिबगिंग उद्देश्यों के लिए अभिप्रेत है।


अपडेट: उत्तर मैं के साथ सौदा प्राप्त कर रहा से कई self.constraints, self.superview.constraints, या कुछ उन लोगों में से संस्करण। ये समाधान काम नहीं करेंगे क्योंकि ये विधियाँ केवल दृश्य के स्वामित्व वाली बाधाओं को लौटाती हैं, न कि दृश्य को प्रभावित करने वाले ।

इन समाधानों के साथ समस्या को स्पष्ट करने के लिए, इस दृश्य को पदानुक्रम मानें:

  • दादा
    • पिता
      • मुझे
        • बेटा
        • बेटी
      • भाई
    • चाचा

अब कल्पना करें कि हम निम्नलिखित बाधाओं का निर्माण करते हैं, और हमेशा उन्हें अपने निकटतम सामान्य पूर्वज से जोड़ते हैं:

  • C0: मी: सोन के रूप में एक ही शीर्ष (मेरे द्वारा स्वामित्व)
  • C1: Me: चौड़ाई = 100 (मेरे स्वामित्व में)
  • C2: मुझे: भाई के समान ऊंचाई (पिता के स्वामित्व में)
  • C3: मुझे: चाचा के रूप में एक ही शीर्ष (दादाजी के स्वामित्व में)
  • C4: मुझे: दादाजी के रूप में एक ही बचा है (दादाजी के स्वामित्व में)
  • C5: भाई: पिता के समान छोड़ दिया गया (पिता के स्वामित्व में)
  • C6: चाचा: दादाजी के रूप में एक ही छोड़ दिया (दादाजी के स्वामित्व में)
  • C7: बेटा: बेटी के समान ही (मेरे द्वारा स्वामित्व में)

अब कल्पना करें कि हम प्रभावित सभी बाधाओं को दूर करना चाहते हैं Me। कोई उचित समाधान निकालना चाहिए [C0,C1,C2,C3,C4]और कुछ नहीं।

यदि मैं उपयोग करता हूं self.constraints(जहां स्वयं मैं हूं), तो मुझे मिलेगा [C0,C1,C7], क्योंकि वे मेरे द्वारा स्वामित्व वाली एकमात्र बाधा हैं। जाहिर है कि इसे हटाने के लिए पर्याप्त नहीं होगा क्योंकि यह गायब है [C2,C3,C4]। इसके अलावा, यह C7अनावश्यक रूप से निकाल रहा है ।

यदि मैं उपयोग करता हूं self.superview.constraints(जहां स्वयं मैं हूं), तो मुझे मिलेगा [C2,C5], क्योंकि वे पिता के स्वामित्व में बाधाएं हैं। जाहिर है कि हम इन सभी को हटा नहीं सकते क्योंकि C5पूरी तरह से असंबंधित है Me

अगर मैं उपयोग करता हूं grandfather.constraints, तो मुझे मिलेगा [C3,C4,C6]। फिर से, हम इन सभी को हटा नहीं सकते क्योंकि C6बरकरार रहना चाहिए।

ब्रूट फोर्स एप्रोच को व्यू के प्रत्येक पूर्वजों (स्वयं सहित) पर लूप करना है, और यह देखते हुए कि खुद ही दृश्य हैं firstItemया नहीं secondItem; यदि हां, तो उस बाधा को हटा दें। इससे एक सही समाधान होगा, वापसी [C0,C1,C2,C3,C4], और केवल उन बाधाओं को।

हालांकि, मुझे उम्मीद है कि पूर्वजों की पूरी सूची के माध्यम से लूप होने की तुलना में अधिक सुरुचिपूर्ण समाधान है।


कैसे के बारे में आप सभी बाधाओं को दूर करना चाहते हैं आप के लिए एक पहचानकर्ता डाल दिया? इस तरह आपको उनके लिए एक आउटलेट रखने की आवश्यकता नहीं है।
nsuinteger

जवाबों:


71

इस दृष्टिकोण ने मेरे लिए काम किया:

@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

ऐसा करने के बाद, यह आपके दृष्टिकोण को क्रियान्वित करता है जहां यह था क्योंकि यह ऑटोरेस्पोन्जिंग बाधाओं का निर्माण करता है। जब मैं ऐसा नहीं करता तो दृश्य गायब हो जाता है। इसके अतिरिक्त, यह केवल पर्यवेक्षण से अड़चन को दूर नहीं करता है, बल्कि सभी तरह से आगे बढ़ाता है क्योंकि पूर्वजों के विचारों को प्रभावित करने में बाधाएं हो सकती हैं।


स्विफ्ट 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
    }
}

3
यह आधिकारिक उत्तर होना चाहिए।
जेसन क्रोकर

आपके पास self.translatesAutoresizingMaskIntoConstraints = YES क्यों है; ? आप शाब्दिक रूप से उन विचारों के लिए कभी नहीं चाहते जो आप बाधाओं के साथ स्थापित कर रहे हैं
लेंसोवेट

4
मैं बाधाओं को दूर कर रहा हूं, इसलिए मैं अन्य बाधाओं को दूर करने के लिए ऑटोरेस्ज़ कॉन्सट्रैक्ट्स का उपयोग करना चाहता हूं, क्योंकि मैं अपने कोड में उस लाइन के बिना दृश्य को गायब कर
दूंगा

मुझे डिबगिंग उद्देश्यों के लिए सभी बाधाओं को लॉग इन करने की आवश्यकता है और मैं ऐसा करने के लिए इस उत्तर को थोड़ा संशोधित करने में सक्षम था। +1
मिर्ची

यह गलत तरीके से हटा देगा C7। हालांकि, यह आसान है, तो आप निकालना ठीक करने के लिए किया जाना चाहिए [self removeConstraints:self.constraints];और परिवर्तन UIView *superview = self.superview;करने के लिए UIView *superview = self;
सेंसफुल

50

एकमात्र उपाय जो मैंने अब तक पाया है, वह है अपने पर्यवेक्षक से दृश्य को हटाना:

[view removeFromSuperview]

ऐसा लगता है कि यह अपने लेआउट को प्रभावित करने वाली सभी बाधाओं को दूर करता है और एक पर्यवेक्षण में जोड़ा जाने के लिए तैयार है और इसमें नई बाधाएं जुड़ी हुई हैं। हालांकि, यह गलत तरीके से पदानुक्रम से किसी भी साक्षात्कार को हटा देगा, और [C7]गलत तरीके से छुटकारा दिलाएगा।


यदि आप उन सभी को खोजने के लिए दृश्य पदानुक्रम के माध्यम से आपके दृश्य और लूप पर लागू होते हैं, तो यह जांचने के लिए आप बाधाओं की पहली इटिम और दूसरी इटेम गुणों का उपयोग कर सकते हैं। मुझे लगता है कि हटाना और फिर से जोड़ना एक बेहतर उपाय है, हालाँकि। मुझे आपके उपयोग के मामले को देखने में दिलचस्पी होगी क्योंकि ऐसा लगता है कि ऐसा करना बहुत बुरी बात है। आपके अवरोध आसानी से पूरी तरह से अमान्य हो सकते हैं क्योंकि अन्य विचार उन बाधाओं पर निर्भर हो सकते हैं ताकि वे ठीक से बाहर हो सकें।
बज्जिट्स

@bjtitus: अच्छी बात है। हालांकि, इस विशिष्ट मामले में, मैं एक ऐसे दृश्य का विरोध कर रहा हूं, जिस पर कुछ भी निर्भर नहीं है। यह जानने के लिए कि दूसरे स्थान पर अन्य विचारों का उपयोग किया जाता है, और यह देखने के लिए कोई दृश्य नहीं हैं कि इसका उपयोग कहाँ किया जाए।
सेंसफुल

एकमात्र समाधान नहीं है, लेकिन बहुत सरल है। मेरे उपयोग के मामले में मैंने अभी-अभी पर्यवेक्षण से दृश्य हटा दिया है और फिर बाद में इसे फिर से जोड़ा है।
मरिआन Marierný

49

आप यह करके एक दृश्य में सभी बाधाओं को दूर कर सकते हैं:

self.removeConstraints(self.constraints)

संपादित करें: सभी साक्षात्कारों की बाधाओं को दूर करने के लिए, स्विफ्ट में निम्नलिखित एक्सटेंशन का उपयोग करें:

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

22
इस समाधान के साथ समस्या यह है कि यह केवल उन बाधाओं को दूर करता है जो इस दृश्य का मालिक है (जैसे इसकी चौड़ाई और ऊंचाई)। यह प्रमुख और शीर्ष बाधाओं जैसी चीजों को दूर नहीं करता है।
सेंसफुल

2
मैंने आपकी टिप्पणी को ऊपर सत्यापित नहीं किया है। हालाँकि, मेरा मानना ​​है कि यह ऊपर के समान या उससे भी बेहतर काम करेगा, [NSLayoutConstraint निष्क्रिय करेंConstraints: self.constraints];
emdog4

2
यह मूल समस्या के रूप में एक ही समस्या से ग्रस्त होगा। self.constraintsकेवल उन बाधाओं को लौटाता selfहै, जो प्रभावित करने वाली सभी बाधाओं को नियंत्रित करती हैं self
सेंसफुल

1
मैं समझता हूं कि अब आप क्या कह रहे हैं। अपने जवाब में , मैं UITableViewCell के contentView से बाधाओं को हटा रहा हूं। इस विधि को अपडेट किया गया है और फिर सभी साक्षात्कारों के लिए बाधाओं को जोड़ा जाएगा और लेआउट को रीसेट किया जाएगा। उपरोक्त मेरी पहली टिप्पणी में , मुझे self.view.constraints टाइप करना चाहिए। Self.view और self.contentView दोनों पदानुक्रम के शीर्ष पर हैं। TranslatesAutoresizingMasksToConstraints = YES को self.view या self.contentView पर सेट करना एक बुरा विचार है। ;-)। मुझे addSubview के लिए कॉल पसंद नहीं है: मेरे अद्यतन में विधि, पदानुक्रम से दृश्य को हटाने से अनावश्यक अनावश्यक लगता है।
emdog4

मैंने सिर्फ यह दिखाने के लिए प्रश्न को अपडेट किया कि इस तरह से एक समाधान काम नहीं करेगा जो मैं देख रहा हूं। मान लें कि आप UITableView के भीतर हैं तो contentView के बराबर दादाजी हैं। इसलिए आपका समाधान गलत तरीके से निकाल देगा [C6], और गलत तरीके से नहीं हटाएगा [C0,C1,C2]
सेंसफुल

20

Apple Developer Documentation के अनुसार इसे प्राप्त करने के दो तरीके हैं

1। NSLayoutConstraint.deactivateConstraints

यह एक सुविधा विधि है जो एक कॉल के साथ बाधाओं के एक सेट को निष्क्रिय करने का एक आसान तरीका प्रदान करती है। इस विधि का प्रभाव प्रत्येक बाधा की झूठी संपत्ति को असत्य पर सेट करने के समान है। आमतौर पर, इस पद्धति का उपयोग प्रत्येक बाधा को व्यक्तिगत रूप से निष्क्रिय करने की तुलना में अधिक कुशल है।

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

// Usage
NSLayoutConstraint.deactivate(yourView.constraints)

2. UIView.removeConstraints> (iOS 8.0 के लिए संक्षिप्त)

IOS 8.0 या बाद के लिए विकसित करते समय, NSLayoutConstraint वर्ग के डिएक्टिवेटकॉन्स्ट्रेंट्स का उपयोग करें: हटाने के बजाय कॉल को हटाने के लिए विधि: सीधे विधि। निष्क्रिय करने के तरीके: विधि स्वचालित रूप से सही विचारों से बाधाओं को हटा देती है।

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

// Usage
yourView.removeConstraints(yourView.constraints)

टिप्स

StoryboardS या XIBs का उपयोग करने से आपके परिदृश्य पर बताई गई बाधाओं को कॉन्फ़िगर करने में ऐसा दर्द हो सकता है, आपको उन सभी लोगों के लिए IBOutlets बनाना होगा जिन्हें आप हटाना चाहते हैं। फिर भी, अधिकांश समयInterface Builder हल करने की तुलना में अधिक परेशानी पैदा करता है।

इसलिए जब बहुत गतिशील सामग्री और दृश्य के विभिन्न राज्य होते हैं, तो मैं सुझाव दूंगा:

  1. अपने विचारों को प्रोग्रामेटिक रूप से बनाना
  2. उन्हें लेआउट और NSLayoutAnchor का उपयोग कर
  3. प्रत्येक बाधा है कि एक सरणी के लिए बाद में हटा दिया हो सकता है जोड़ें
  4. नई स्थिति लागू करने से पहले उन्हें हर बार साफ़ करें

सरल कोड

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

संदर्भ

  1. NSLayoutConstraint
  2. UIView

2
सावधान रहे। एक आंतरिक सामग्री का आकार निर्दिष्ट करने वाले दृश्य में NSContentSizeLayoutConstraint स्वतः iOS द्वारा जोड़ा जाएगा। इसे सामान्य से हटाकर आपके व्यू.ऑनस्ट्रेन्ट्स प्रॉपर्टी उन विचारों पर ऑटोलैयट को तोड़ देगी।
टाइगरकोडिंग

इस समाधान के साथ समस्या यह है कि यह केवल उन बाधाओं को दूर करता है जो इस दृश्य का मालिक है (जैसे इसकी चौड़ाई और ऊंचाई)। यह प्रमुख और शीर्ष बाधाओं जैसी चीजों को दूर नहीं करता है।
सेंसफुल

हाँ, Senseful ने क्या कहा। हालाँकि ये विधियाँ मौजूद हैं, वे उस समस्या को हल करने के लिए नहीं हैं जिस सवाल के बारे में वास्तव में पूछ रहे हैं।
GSnyder

18

स्विफ्ट में:

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

यदि आपका दृश्य 'पर्यवेक्षण' में नहीं है तो यह दुर्घटनाग्रस्त हो जाएगा। कृपया भाग को एक 'अगर
सुपरवाइड

1
इससे सभी अड़चनें दूर नहीं होंगी। बाधाएं 2 प्रभावित विचारों के निकटतम माता-पिता को ले जाती हैं, इसलिए यदि आप एक बाधा बनाते हैं जो इस दृश्य के
पर्यवेक्षण को

2
शायद अधिक सही यह होगा कि पहचान की तुलना if c.firstItem === selfकास्टिंग के बजाय करें as? UIViewऔर समानता की जाँच करें==
user1244109

संभवत: निष्कासन का उपयोग नहीं करना चाहिए: सेब डॉक से: // निष्कासन विधि भविष्य में रिलीज में हटा दी जाएगी और इसे टाला जाना चाहिए। इसके बजाय + [NSLayoutConstraint को निष्क्रिय करें।
eonist

@eonist जवाब 3 साल पहले का है। आलोचना के बजाय आपको इसे संपादित करना चाहिए।
अलेक्जेंडर वोल्कोव

5

विवरण

  • Xcode 10.2.1 (10E1001), स्विफ्ट 5

उपाय

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

प्रयोग

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

1
यह बहुत अच्छा है।
eonist

2

एक स्विफ्ट समाधान:

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

सभी माता-पिता के माध्यम से जाना महत्वपूर्ण है, क्योंकि दो तत्वों के बीच की बाधाएं आम पूर्वजों द्वारा धारण की जाती हैं, इसलिए इस उत्तर में विस्तृत रूप में पर्यवेक्षक को साफ करना काफी अच्छा नहीं है, और आप बाद में खराब आश्चर्यचकित हो सकते हैं।


2

पिछले उत्तरों (स्विफ्ट 4) के आधार पर

जब आप संपूर्ण पदानुक्रम को क्रॉल नहीं करना चाहते हैं, तो आप तत्काल कॉन्ट्रैट्स का उपयोग कर सकते हैं।

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

सभी बाधाओं को दूर करने के लिए मैं निम्नलिखित विधि का उपयोग करता हूं:

.h फ़ाइल:

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

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

आप इस पोस्ट को भी पढ़ सकते हैं को मेरे ब्लॉग पर बेहतर तरीके से समझने के लिए कि यह हुड के पीछे कैसे काम करता है।

यदि आपको अधिक दानेदार नियंत्रण की आवश्यकता है, तो मैं दृढ़ता से चिनाई के लिए स्विच करने की सलाह दूंगा , एक शक्तिशाली ढांचा वर्ग जिसे आप उपयोग कर सकते हैं जब भी आपको प्रोग्राम को ठीक से संभालने की आवश्यकता हो।


2

आसान और कुशल दृष्टिकोण यह है कि दृश्य को सुपरव्यू से हटा दें और फिर से सबव्यू के रूप में जोड़ें। इसके कारण सभी सबव्यू बाधाएं स्वचालित रूप से दूर हो जाती हैं


1

उद्देश्य के साथ

[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

आप कुछ इस तरह का उपयोग कर सकते हैं:

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

मूल रूप से, यह viewA के पर्यवेक्षण पर सभी बाधाओं पर आधारित है और viewA से संबंधित सभी बाधाओं को दूर करता है।

उसके बाद, दूसरा भाग viewA की बाधाओं का उपयोग करके viewA से बाधाओं को हटा देता है।


1
इस समाधान के साथ समस्या यह है कि यह केवल उन बाधाओं को हटा देता है जो पर्यवेक्षण के स्वामित्व में हैं। यह दृश्य को प्रभावित करने वाली सभी बाधाओं को दूर नहीं करता है। (जैसे कि आप आसानी से पर्यवेक्षक के पर्यवेक्षक के पर्यवेक्षण पर अड़चनें स्थापित कर सकते हैं, जो इस समाधान का उपयोग नहीं करेगा।)
Senseful

मैंने सिर्फ यह दिखाने के लिए प्रश्न को अपडेट किया कि यह समाधान काम क्यों नहीं करेगा। यह सही होने के सबसे करीब है, क्योंकि यह मेरे द्वारा उल्लिखित जानवर बल समाधान के सबसे करीब है। हालाँकि, यह समाधान गलत तरीके से निकाल [C7]देगा और गलत तरीके से नहीं निकालेगा [C3,C4]
सेंसफुल

आप पदानुक्रम को क्रॉल करने के लिए विधि डिज़ाइन कर सकते हैं। लेकिन यह समाधान काफी अच्छा है, क्योंकि आपको वैसे भी तत्काल पर्यवेक्षण के ऊपर बाधाओं को जोड़ना चाहिए। IMO
eonist

0

(31 जुलाई, 2017 तक)

स्विफ्ट 3

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

उद्देश्य सी

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

यह उन सभी बाधाओं को जल्दी से दूर करने का सबसे आसान तरीका है जो एक यूआईवीयूवाई पर मौजूद हैं। बस यूवीवाई को वापस जोड़ना सुनिश्चित करें क्योंकि यह नई बाधाओं या नए फ्रेम के बाद =) है


0

पुन: प्रयोज्य अनुक्रम का उपयोग करना

मैंने इसे अधिक 'पुन: प्रयोज्य' तरीके से देखने का निर्णय लिया। चूँकि किसी दृश्य को प्रभावित करने वाली सभी बाधाओं का पता लगाना उपरोक्त सभी का आधार है, मैंने एक कस्टम अनुक्रम को लागू करने का निर्णय लिया जो उन सभी के लिए मेरे साथ-साथ अपने विचारों को भी लौटाता है।

पहली बात यह है कि एक विशिष्ट दृश्य को प्रभावित करने वाले सभी तत्वों को रिटर्न पर एक विस्तार परिभाषित किया गया Arraysहै NSLayoutConstraint

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

फिर हम उस एक्सटेंशन को कस्टम अनुक्रम में उपयोग करते हैं जो उस दृश्य को प्रभावित करने वाली सभी बाधाओं को वापस करता है, साथ ही उन विचारों के साथ जो वास्तव में उनके खुद के हैं (जो कि दृश्य पदानुक्रम कहीं भी हो सकते हैं)

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

अंत में हम UIViewएक साधारण संपत्ति में इसे प्रभावित करने वाली सभी बाधाओं को उजागर करने के लिए एक विस्तार की घोषणा करते हैं जिसे आप एक साधारण प्रत्येक वाक्यविन्यास के साथ उपयोग कर सकते हैं।

extension UIView {

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

अब हम एक दृश्य को प्रभावित करने वाली सभी बाधाओं को दूर कर सकते हैं और हम उनके साथ जो चाहते हैं ...

उनके पहचानकर्ताओं की सूची बनाएं ...

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

उन्हें निष्क्रिय करें ...

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

या उन्हें पूरी तरह से हटा दें ...

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

का आनंद लें!


0

तीव्र

UIView एक्सटेंशन के बाद देखने के सभी एज बाधाएं दूर हो जाएंगी:

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

-1

यह एक विशिष्ट दृष्टिकोण से सभी बाधाओं को अक्षम करने का तरीका है

 NSLayoutConstraint.deactivate(myView.constraints)

इस समाधान के साथ समस्या यह है कि यह केवल उन बाधाओं को दूर करता है जो इस दृश्य का मालिक है (जैसे इसकी चौड़ाई और ऊंचाई)। यह प्रमुख और शीर्ष बाधाओं जैसी चीजों को दूर नहीं करता है।
सेंसफुल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.