मैं कैसे रन समय में बाधाओं को प्राथमिकता में बदल सकता हूं


86

मेरे पास एक दृष्टिकोण है जिसकी गतिशील ऊंचाई है और मैं इस दृश्य ऊंचाई प्राथमिकता को रन समय में बदलने की कोशिश कर रहा हूं।

यहाँ मेरे कोड का हिस्सा है;

if (index == 0) {

    surveyViewHeightConstraint.constant = 0;
    surveyViewHeightConstraint.priority = 1000;

} else if (index == 1) {

    surveyViewHeightConstraint.constant = 163;
    surveyViewHeightConstraint.priority = 500;

}

मैं बटन कार्रवाई के साथ सूचकांक बदल रहा हूं। जब मैं यह कोड चलाता हूं, तो मुझे यह त्रुटि मिल रही है:

*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174

इसमें मेरी क्या गलती है?

जवाबों:


172

जैसा कि NSLayoutConstraintकक्षा संदर्भ में कहा गया है :

प्राथमिकताएँ गैर-आवश्यकता से परिवर्तित नहीं हो सकती हैं, या आवश्यकता से अप्रतिष्ठित तक परिवर्तित नहीं हो सकती हैं। यदि NSLayoutPriorityRequiredओएस एक्स या UILayoutPriorityRequiredआईओएस में प्राथमिकता को कम प्राथमिकता में बदल दिया जाता है, या बाधाओं को एक दृश्य में जोड़ने के बाद एक कम प्राथमिकता को आवश्यक प्राथमिकता में बदल दिया जाता है, तो एक अपवाद को फेंक दिया जाएगा । एक दृश्य पर बाधा स्थापित होने के बाद भी एक वैकल्पिक प्राथमिकता से दूसरी वैकल्पिक प्राथमिकता में बदलाव की अनुमति है।

1000 के बजाय प्राथमिकता 999 का उपयोग करें। यह तकनीकी रूप से बोलने की बिल्कुल आवश्यकता नहीं होगी, लेकिन यह किसी भी चीज़ की तुलना में अधिक प्राथमिकता होगी।


4
आपके अच्छे उत्तर के लिए धन्यवाद, लेकिन अगर मैं 1000 के बजाय 999 का उपयोग करता हूं, तो मैं 0 से ऊँचाई की बाधा को बताकर अपना दृष्टिकोण नहीं छिपा सकता।
Le'Kirdok

यह एक और समस्या है। आपके पास अन्य विरोधी बाधाएं हो सकती हैं। यदि आपका कोड अब दुर्घटना नहीं करता है, लेकिन आपका दृश्य एनीमेशन अभी भी गलत है, तो कृपया इस प्रश्न को हल के रूप में चिह्नित करें; फिर एक और खोलें।
साइरिल

अच्छा है, यह विभिन्न मूल्यों (999, 900, 500, आदि) का उपयोग करने के लिए कोई समस्या नहीं है :)
user924

7
गंभीरता से? क्या आईओएस विकास में सिर्फ सामान्य रूप से काम कर रहा है? तो कई चीजें मैन्युअल रूप से की जानी थीं और / या सिस्टम बग या असमर्थता के कारण वर्कअराउंड कोड के टन को लागू करना था। रचनात्मक टिप्पणी नहीं करने के लिए क्षमा करें।
लुटेन

6
ऐसा लगता है कि इस सीमा आईओएस 13. मैं में हटा दिया गया है से एक बाधा को बदलने की कोशिश की requiredकरने के लिए defaultLowऔर यह काम किया। इसी कोड का इस्तेमाल iOS 12 पर किया गया था
स्टीवन वांडेवेघे

52

मैं साइरिल के उत्तर के लिए एक छोटा सा जोड़ बनाना चाहता हूं।

यदि आप कोड में बाधा पैदा कर रहे हैं, तो इसे सक्रिय करने से पहले इसकी प्राथमिकता तय करना सुनिश्चित करें। उदाहरण के लिए:

surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
                                               attribute:NSLayoutAttributeHeight
                                               relatedBy:NSLayoutRelationEqual
                                                  toItem:self.superview
                                               attribute:NSLayoutAttributeHeight
                                              multiplier:1
                                                constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;

इसके परिणामस्वरूप रन-टाइम अपवाद होगा।

एक स्थापित बाधा (या इसके विपरीत) पर नहीं करने के लिए आवश्यक से एक प्राथमिकता का समर्थन समर्थित नहीं है।

सही क्रम है:

surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;

स्विफ्ट संस्करण 4+ के लिए

constraintName.priority = UILayoutPriority(rawValue: 999)


8

जिस तरह से हमने हमेशा इसे संभाला है, वह है कि निरंतरता को न बदलकर, सिर्फ प्राथमिकता। उदाहरण के लिए, आपकी स्थिति में दो ऊँचाई की कमी है।

 heightConstraintOne (who's height is set in the storyboard at 150, and priority set at 750)
 heightConstraintTwo (who's height is set in the storyboard at 0, and priority set at 250)

यदि आप दृश्य छिपाना चाहते हैं, तो आप:

heightConstraintTwo.priority = 999;

इसी तरह, यदि आप दृश्य दिखाना चाहते हैं:

heightConstraintTwo.priority = 250;

5
कूल, समझ में आ गया: 1000 के बजाय 999 का उपयोग करें। धन्यवाद
ब्रेनरे

3

मुझे उम्मीद है कि यह परिदृश्य किसी की मदद करेगा: मेरे पास दो बाधाएं थीं, कि वे एक दूसरे के विपरीत थे, मेरा मतलब है कि वे एक ही समय में संतुष्ट नहीं हो सकते हैं, इंटरफ़ेस बिल्डर में उनमें से एक की प्राथमिकता 1000 थी और अन्य की 1000 से कम प्राथमिकता थी। जब मैंने उन्हें कोड में बदल दिया, तो मुझे यह त्रुटि मिली:

अनकैप्ड अपवाद 'NSInternalInconsistencyException' के अपवाद के कारण ऐप समाप्त करना, कारण: 'किसी स्थापित बाधा (या इसके विपरीत) पर आवश्यक नहीं से प्राथमिकता को म्यूट करना समर्थित नहीं है। आपने प्राथमिकता 250 को पार कर ली और मौजूदा प्राथमिकता 1000 हो गई। '

तब मैंने उन्हें सिर्फ .DelLoad फ़ंक्शन के साथ .DfaultHigh और .defaultLow मानों के साथ आरंभिक किया और इस समस्या को ठीक किया।


1

के अनुसार NSLayoutConstraints classअंदर UIKit Module

यदि एक बाधा का प्राथमिकता स्तर UILayoutPriorityRequired से कम है, तो यह वैकल्पिक है। उच्च प्राथमिकता की कमी को कम प्राथमिकता की बाधाओं से पहले पूरा किया जाता है। बाधा संतुष्टि सभी या कुछ भी नहीं है। यदि कोई बाधा 'a == b' वैकल्पिक है, तो इसका मतलब है कि हम 'abs (ab)' को कम करने का प्रयास करेंगे। यह संपत्ति केवल प्रारंभिक सेट अप या वैकल्पिक के हिस्से के रूप में संशोधित की जा सकती है। एक दृश्य में एक बाधा जोड़े जाने के बाद, प्राथमिकता को NSLayoutPyerityRequired से / से बदल दिया जाता है, तो एक अपवाद को फेंक दिया जाएगा।

उदाहरण: - UIButtonविभिन्न प्राथमिकताओं के साथ अड़चनें -

 func setConstraints() {
        buttonMessage.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -10).isActive = true

        let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 10)

        leading.isActive = true


        let widthConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)

        let heightConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)


        let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)

        trailingToSuperView.priority = 999
        trailingToSuperView.isActive = true

        //leading.isActive = false//uncomment & check it will align to right of the View

        buttonMessage.addConstraints([widthConstraint,heightConstraint])

         }  

1
नहीं, आपको कभी अड़चन नहीं बनानी चाहिए viewDidLayoutSubviews। उस विधि को कई बार कहा जा सकता है, जो आपके एप्लिकेशन को क्रैश कर सकता है यदि आप वहां डुप्लिकेट बाधाएं बनाते हैं।
mph

0

मैं उसी मुद्दे का सामना कर रहा था। जैसा कि iOS 13 में उपर्युक्त उत्तर में से कुछ में परिवर्तन करना प्राथमिकता पर काम करेगा, हालाँकि iOS 12 में यह दुर्घटना का कारण बनेगा।

IBOutlet NSLayoutConstraint को उस विशिष्ट बाधा में स्टोरीबोर्ड पर बनाकर मैं इस समस्या को ठीक करने में सक्षम था, अपनी प्राथमिकता को 1000 तक बनाए रखना, नीचे ठीक करने के लिए कोड है।

if (Condition) {
    surveyViewHeightConstraint.constant = 0;
    surveyViewHeightConstraint.isActive = false;
} else if (index == 1) {
    surveyViewHeightConstraint.constant = 163;
    surveyViewHeightConstraint.isActive = True;
}

उम्मीद है की यह मदद करेगा!!! चियर्स


-3

अब आप कर सकते हैं, बस अपने बाधाओं के लिए IBOutlet कनेक्शन लें, फिर इस कोड का उपयोग करें।

self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.