การสร้างข้อ จำกัด ของโครงร่างโดยใช้โปรแกรม


84

ฉันรู้ว่ามีคนถามคำถามมากมายเกี่ยวกับเรื่องนี้อยู่แล้ว แต่ถึงแม้จะมีคำตอบฉันก็ไม่สามารถใช้งานได้

เมื่อฉันจัดการกับข้อ จำกัด บนกระดานเรื่องราวมันง่าย แต่ในรหัสฉันมีช่วงเวลาที่ยากลำบาก ตัวอย่างเช่นฉันพยายามที่จะมีมุมมองที่อยู่ทางด้านขวาและมีความสูงของหน้าจอตามการวางแนวหน้าจอ นี่คือรหัสของฉัน:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

ไม่เป็นไปตามข้อ จำกัด บางประการ ไม่เห็นมีอะไรผิดปกติ นอกจากนี้เหตุใดฉันจึงไม่สามารถใช้คุณสมบัติ like self.myViewแทนตัวแปรท้องถิ่นเช่นmyView?


vivi ในโค้ดด้านบนคืออะไร?
iDev

14
โปรดเปลี่ยนชื่อเป็น "iOS" แทน "IOS" - ส่วนหลังหมายถึงระบบปฏิบัติการสวิตช์ / เราเตอร์ของ Cisco ทำให้ฉันสับสน ขอบคุณ.
armani

1
คำถามหลายข้อเกี่ยวกับเรื่องนี้: (1) คุณได้รับข้อผิดพลาดอะไรเมื่อ "ไม่เป็นไปตามข้อ จำกัด " (2) คุณกำลังแปลการปรับอัตโนมัติเป็นข้อ จำกัดmyViewหรือไม่? (3) อะไรvivi(ตามที่ ACB ถาม)? (4) คุณมีmyViewประกาศทรัพย์สินselfหรือไม่?
ทิม

1
ฉันขอโทษที่วีวี่ฉันเคาะเร็วเกินไป ... มันคือ myView แปลว่าอะไรคะ? ทั้งหมดที่ฉันทำก็คือโค้ดด้านบน เกี่ยวกับอสังหาริมทรัพย์ที่ฉันมีมุมมองอื่น ๆ บางอย่างที่ประกาศเป็นทรัพย์สิน แต่เมื่อฉันใช้รหัสเดียวกันคุณสมบัติเหล่านั้นมันผิดพลาด ... ข้อความ "ข้อผิดพลาด" มีขนาดใหญ่จริงๆผมไม่สามารถวางได้ที่นี่
pierre23

หากต้องการลบข้อ จำกัด ออกจากมุมมองใดมุมมองหนึ่งชั่วคราวจากนั้นทำstackoverflow.com/questions/13388104/…
Sam B

คำตอบ:


106

เมื่อใช้การจัดวางอัตโนมัติในโค้ดการตั้งค่าเฟรมจะไม่ทำอะไรเลย ดังนั้นการที่คุณระบุความกว้าง 200 ในมุมมองด้านบนไม่ได้มีความหมายอะไรเลยเมื่อคุณกำหนดข้อ จำกัด เพื่อให้การตั้งค่าข้อ จำกัด ของมุมมองไม่คลุมเครือจำเป็นต้องมีสี่สิ่ง: ตำแหน่ง x ตำแหน่ง y ความกว้างและความสูงสำหรับสถานะใด ๆ

ขณะนี้ในโค้ดด้านบนคุณมีเพียงสอง (ความสูงเทียบกับซุปเปอร์วิวและตำแหน่ง y เทียบกับซูเปอร์วิว) นอกจากนี้คุณยังมีข้อ จำกัด ที่จำเป็นอีก 2 ข้อซึ่งอาจขัดแย้งกันได้ขึ้นอยู่กับวิธีการตั้งค่าข้อ จำกัด ของมุมมอง Superview หากซูเปอร์วิวต้องมีข้อ จำกัด ที่จำเป็นซึ่งระบุว่าความสูงเป็นค่าที่น้อยกว่า 748 คุณจะได้รับข้อยกเว้น "ข้อ จำกัด ที่ไม่น่าพอใจ"

การที่คุณตั้งค่าความกว้างของมุมมองก่อนกำหนดข้อ จำกัด ก็ไม่มีความหมาย จะไม่คำนึงถึงเฟรมเก่าด้วยซ้ำและจะคำนวณเฟรมใหม่ตามข้อ จำกัด ทั้งหมดที่ระบุไว้สำหรับมุมมองเหล่านั้น เมื่อจัดการกับ autolayout ในรหัสฉันมักจะเพียงแค่สร้างมุมมองใหม่โดยใช้หรือเพียงแค่initWithFrame:CGRectZeroinit

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

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

การอธิบายเค้าโครงนี้ด้วยวาจาอ่านดังนี้โดยเริ่มต้นด้วยข้อ จำกัด แนวตั้ง:

myView จะเติมความสูงของ superview ด้วยช่องว่างด้านบนและด้านล่างเท่ากับช่องว่างมาตรฐาน superview ของ myView มีความสูงขั้นต่ำ 748pts ความกว้างของ myView คือ 200pts และมีช่องว่างภายในเท่ากับพื้นที่มาตรฐานเทียบกับ superview

หากคุณต้องการเพียงแค่ต้องการให้มุมมองเติมเต็มความสูงของซูเปอร์วิวทั้งหมดโดยไม่จำกัดความสูงของซูเปอร์วิวคุณก็แค่ไม่ใส่(>=748)พารามิเตอร์ในข้อความรูปแบบภาพ หากคุณคิดว่า(>=748)ต้องใช้พารามิเตอร์เพื่อให้ความสูง - คุณไม่ได้อยู่ในกรณีนี้: การตรึงมุมมองไว้ที่ขอบของ superview โดยใช้ไวยากรณ์bar ( |) หรือ bar ที่มีช่องว่าง ( |-, -|) คุณกำลังให้มุมมองของคุณเป็น y - ตำแหน่ง (ตรึงมุมมองบนขอบด้านเดียว) และตำแหน่ง y ที่มีความสูง (ตรึงมุมมองไว้ที่ขอบทั้งสองด้าน) ดังนั้นจึงเป็นไปตามข้อ จำกัด ของคุณสำหรับมุมมอง

เกี่ยวกับคำถามที่สองของคุณ:

การใช้NSDictionaryOfVariableBindings(self.myView)(ถ้าคุณมีการตั้งค่าคุณสมบัติสำหรับ myView) และป้อนข้อมูลนั้นลงใน VFL ของคุณเพื่อใช้self.myViewในข้อความ VFL ของคุณคุณอาจได้รับข้อยกเว้นเมื่อการจัดวางอัตโนมัติพยายามแยกวิเคราะห์ข้อความ VFL ของคุณ valueForKeyPath:มันจะทำอย่างไรกับสัญกรณ์จุดในคีย์พจนานุกรมและระบบการพยายามที่จะใช้ ดูที่นี่สำหรับคำถามที่คล้ายกันและคำตอบ


อย่าลืมวัตถุบางอย่างเช่น UILabel มีขนาดที่แท้จริงและคุณไม่จำเป็นต้องกำหนดความกว้างหรือความสูงของวัตถุนั้นเพียง แต่เป็นตำแหน่งเท่านั้น อย่างไรก็ตามหากคุณตั้งค่าความสูงหรือความกว้างฉันเชื่อว่ามันจะลบทั้งสองอย่างออกไปและคุณต้องใส่ทั้งสองอย่าง
Nick Turner

แม้ว่าคำตอบนี้จะไม่ตอบคำถามของฉัน แต่ก็ช่วยให้ฉันตระหนักถึงบางสิ่งได้ ขอบคุณที่เป็นอยู่! :)
Matej

1
การแนะนำเค้าโครงอัตโนมัติที่กระชับและอ่านได้บนอินเทอร์เน็ตจนถึงตอนนี้
Joey Carson

โปรดช่วยฉันด้วยคำถามของฉันคือ ... ฉันไม่รู้วิธีใช้ข้อ จำกัด ทางโปรแกรม stackoverflow.com/questions/36326288/…

61

สวัสดีฉันใช้หน้านี้บ่อยมากสำหรับข้อ จำกัด และ "วิธีการ" ฉันต้องใช้เวลาตลอดไปกว่าจะมาถึงจุดที่ตระหนักว่าฉันต้องการ:

myView.translatesAutoresizingMaskIntoConstraints = NO;

เพื่อให้ตัวอย่างนี้ใช้งานได้ ขอบคุณ Userxxx, Rob M. และโดยเฉพาะอย่างยิ่ง larsacus สำหรับคำอธิบายและรหัสที่นี่มันมีค่ามาก

นี่คือโค้ดแบบเต็มเพื่อรับตัวอย่างด้านบนเพื่อเรียกใช้:

UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor redColor];
myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up 
[self.view addSubview:myView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

11

รุ่น Swift

อัปเดตสำหรับ Swift 3

ตัวอย่างนี้จะแสดงวิธีการสองวิธีในการเพิ่มข้อ จำกัด ต่อไปนี้โดยทางโปรแกรมเหมือนกับที่ทำใน Interface Builder:

ความกว้างและความสูง

ใส่คำอธิบายภาพที่นี่

ตรงกลางในคอนเทนเนอร์

ใส่คำอธิบายภาพที่นี่

รหัสหม้อไอน้ำ

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here (choose one of the methods below)
    // ...
}

วิธีที่ 1: Anchor Style

// width and height
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

// center in container
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

วิธีที่ 2: NSLayoutConstraint Style

// width and height
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true

// center in container
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true

หมายเหตุ

  • สไตล์ Anchor เป็นวิธีที่ต้องการมากกว่าNSLayoutConstraintสไตล์อย่างไรก็ตามใช้ได้เฉพาะใน iOS 9 ดังนั้นหากคุณรองรับ iOS 8 คุณควรใช้NSLayoutConstraintสไตล์
  • ดูเอกสารประกอบการสร้างข้อ จำกัด แบบเป็นโปรแกรม
  • ดูคำตอบนี้สำหรับตัวอย่างที่คล้ายกันของการเพิ่มข้อ จำกัด ในการตรึง

5

สำหรับคำถามที่สองเกี่ยวกับคุณสมบัติคุณสามารถself.myViewใช้ได้ก็ต่อเมื่อคุณประกาศเป็นคุณสมบัติในชั้นเรียนเท่านั้น เนื่องจากmyViewเป็นตัวแปรท้องถิ่นคุณจึงไม่สามารถใช้มันได้ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ผมจะแนะนำให้คุณไปถึงเอกสารแอปเปิ้ลในอสังหาริมทรัพย์ประกาศ ,


5

เหตุใดฉันจึงไม่สามารถใช้คุณสมบัติ like self.myViewแทนตัวแปรภายในเช่น myView ได้

ลองใช้:

NSDictionaryOfVariableBindings(_view)

แทน self.view


นั่นทำให้แอปของฉันขัดข้องมีข้อความว่า 'ไม่สามารถแยกวิเคราะห์รูปแบบข้อ จำกัด : polylineImageView ไม่ใช่กุญแจสำคัญในพจนานุกรมมุมมอง'
Tai Le

4

โปรดทราบว่าจาก iOS9 เราสามารถกำหนดข้อ จำกัด ของโปรแกรม"กระชับมากขึ้นและง่ายต่อการอ่าน"โดยใช้ subclasses ของชนชั้นผู้ช่วยใหม่NSLayoutAnchor

ตัวอย่างจากเอกสาร:

[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.