ฉันจะเปลี่ยนลำดับความสำคัญของข้อ จำกัด ในเวลาทำงานได้อย่างไร


87

ฉันมีมุมมองที่มีความสูงแบบไดนามิกและฉันกำลังพยายามเปลี่ยนลำดับความสำคัญของมุมมองนี้ในเวลาทำงาน

นี่คือส่วนหนึ่งของรหัสของฉัน

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

ความผิดพลาดของฉันที่นี่คืออะไร?

คำตอบ:


174

ตามที่ระบุไว้ในNSLayoutConstraintการอ้างอิงชั้นเรียน :

ลำดับความสำคัญต้องไม่เปลี่ยนจากไม่จำเป็นเป็นจำเป็นหรือจากจำเป็นเป็นไม่จำเป็น ข้อยกเว้นจะเกิดขึ้นหากลำดับความสำคัญของNSLayoutPriorityRequiredOS X หรือUILayoutPriorityRequiredใน iOS เปลี่ยนเป็นลำดับความสำคัญที่ต่ำกว่าหรือหากลำดับความสำคัญต่ำกว่าถูกเปลี่ยนเป็นลำดับความสำคัญที่จำเป็นหลังจากเพิ่มข้อ จำกัด ในมุมมอง อนุญาตให้เปลี่ยนจากลำดับความสำคัญที่เป็นทางเลือกหนึ่งไปเป็นลำดับความสำคัญทางเลือกอื่นได้แม้ว่าจะติดตั้งข้อ จำกัด ในมุมมองแล้วก็ตาม

ใช้ลำดับความสำคัญ 999 แทน 1,000 ไม่จำเป็นต้องพูดในทางเทคนิค แต่จะมีลำดับความสำคัญสูงกว่าสิ่งอื่นใด


4
ขอบคุณสำหรับคำตอบที่ดี แต่ถ้าฉันใช้ 999 แทน 1,000 ฉันไม่สามารถซ่อนมุมมองของฉันได้โดยกำหนด 0 เป็นข้อ จำกัด ของความสูง
Le'Kirdok

นั่นเป็นอีกปัญหาหนึ่ง คุณอาจมีข้อ จำกัด อื่น ๆ ที่ขัดแย้งกัน หากรหัสของคุณไม่ขัดข้องอีกต่อไป แต่ภาพเคลื่อนไหวการดูของคุณยังไม่ถูกต้องโปรดทำเครื่องหมายคำถามนี้ว่าแก้ไขแล้ว จากนั้นเปิดอีกอัน
Cyrille

ดีไม่มีปัญหาในการใช้ค่าที่แตกต่างกัน (999, 900, 500 ฯลฯ ) :)
user924

7
อย่างจริงจัง? มีอะไรทำงานได้ตามปกติในการพัฒนา iOS หรือไม่? มีหลายสิ่งที่ต้องทำด้วยตนเองและ / หรือต้องใช้รหัสวิธีแก้ปัญหาจำนวนมากสาเหตุของข้อบกพร่องของระบบหรือการไม่รองรับ ขออภัยสำหรับความคิดเห็นที่ไม่สร้างสรรค์
Luten

7
ดูเหมือนว่าข้อ จำกัด นี้จะถูกลบออกใน iOS 13 ฉันลองเปลี่ยนข้อ จำกัด จากrequiredเป็นเป็นdefaultLowและใช้งานได้ รหัสเดียวกับที่ใช้ใน iOS 12
Steven Vandeweghe

53

ฉันต้องการเพิ่มคำตอบของ Cyrille เล็กน้อย

หากคุณกำลังสร้างข้อ จำกัด ในโค้ดตรวจสอบให้แน่ใจว่าได้กำหนดลำดับความสำคัญก่อนที่จะเปิดใช้งาน ตัวอย่างเช่น:

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;

สำหรับ Swift เวอร์ชัน 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
เจ๋งไปเลย: ใช้ 999 แทน 1,000 ขอบคุณ
brainray

3

ฉันหวังว่าสถานการณ์นี้จะช่วยใครบางคน: ฉันมีข้อ จำกัด สองข้อคือพวกเขาอยู่ตรงข้ามกันฉันหมายความว่าพวกเขาไม่สามารถพอใจได้ในเวลาเดียวกันในเครื่องมือสร้างอินเทอร์เฟซหนึ่งในนั้นมีลำดับความสำคัญ 1,000 รายการและอีกรายการมีลำดับความสำคัญน้อยกว่า 1,000 รายการ เมื่อฉันเปลี่ยนในรหัสฉันพบข้อผิดพลาดนี้:

การยุติแอปเนื่องจากไม่มีข้อยกเว้น 'NSInternalInconsistencyException' เหตุผล: ไม่รองรับ 'การเปลี่ยนลำดับความสำคัญจากที่จำเป็นเป็นไม่ได้อยู่ในข้อ จำกัด ที่ติดตั้งไว้ (หรือในทางกลับกัน) คุณผ่านลำดับความสำคัญ 250 และลำดับความสำคัญที่มีอยู่คือ 1,000

จากนั้นฉันเพิ่งเริ่มต้นในฟังก์ชั่น viewDidLoad ด้วยค่า .defaultHigh และ .defaultLow และสิ่งนี้ช่วยแก้ปัญหาของฉันได้


1

ตามNSLayoutConstraints classด้านใน UIKit Module

หากระดับความสำคัญของข้อ จำกัด น้อยกว่า UILayoutPriorityRequired แสดงว่าเป็นทางเลือก พบข้อ จำกัด ที่มีลำดับความสำคัญสูงกว่าก่อนข้อ จำกัด ลำดับความสำคัญต่ำ ความพึงพอใจที่มีข้อ จำกัด ไม่ใช่ทั้งหมดหรือไม่มีเลย หากข้อ จำกัด 'a == b' เป็นทางเลือกนั่นหมายความว่าเราจะพยายามย่อ 'abs (ab)' ให้น้อยที่สุด คุณสมบัตินี้สามารถแก้ไขได้เฉพาะเป็นส่วนหนึ่งของการตั้งค่าเริ่มต้นหรือเมื่อเป็นทางเลือก หลังจากเพิ่มข้อ จำกัด ในมุมมองแล้วข้อยกเว้นจะถูกโยนทิ้งหากลำดับความสำคัญถูกเปลี่ยนจาก / เป็น NSLayoutPriorityRequired

ตัวอย่าง: - 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. วิธีนี้สามารถเรียกใช้ได้หลายครั้งซึ่งอาจทำให้แอปของคุณขัดข้องหากคุณสร้างข้อ จำกัด ซ้ำที่นั่น
ไมล์ / ชม.

0

ฉันประสบปัญหาเดียวกัน เนื่องจากคำตอบบางส่วนที่กล่าวถึงข้างต้นในการเปลี่ยนลำดับความสำคัญของ iOS 13 จะทำงานได้ดีอย่างไรก็ตามใน iOS 12 จะนำไปสู่ความผิดพลาด

ฉันสามารถแก้ไขปัญหานี้ได้โดยการสร้าง IBOutlet NSLayoutConstraint ตามข้อ จำกัด เฉพาะนั้นใน Storyboard โดยมีลำดับความสำคัญเป็น 1,000 ด้านล่างคือรหัสสำหรับการแก้ไข

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

หวังว่านี่จะช่วยได้ !!! ไชโย


-2

ตอนนี้คุณสามารถทำได้เพียงใช้การเชื่อมต่อ IBOutlet สำหรับข้อ จำกัด ของคุณแล้วใช้รหัสนี้

self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.