Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> สมาร์ทโฟน >> iPhone

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps

ตอนเริ่มสร้างแอปด้วย Xcode คิดว่า Storyboards เป็นเวทมนตร์ Drag-and-drop Subviews วางตำแหน่งง่ายมาก ไม่เข้าใจว่าคนอื่นสร้าง View โดยไม่ใช้ Storyboard ยังไง

สุดท้ายตัดสินใจว่าเพื่อเป็น "Master Programmer" ต้องเรียนรู้การสร้าง View ด้วยโค้ด ปัญหาคือเขียน Constraints ในโค้ดเจ็บปวด

let horizontalConstraint = NSLayoutConstraint( item: newView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)

นี่คือ Horizontal Constraint จัดกึ่งกลาง Subview บนแกน X ของ Superview ไม่ง่ายต่อการอ่าน การเขียนแบบนี้ทุก Constraint ทำให้เบื่อเร็ว แต่อยากเลิก Storyboard จึงหาทางเลือก พบ SnapKit

SnapKit มี API ชัดเจนกระชับ ทำให้เขียน Constraints ในโค้ดง่ายขึ้น มาไปดูตัวอย่างพื้นฐานกัน

จะครอบคลุม:

  1. จัด Layout Subview ใน Superview
  2. จัด Layout Subviews เทียบกัน
  3. Update และ Animate Constraints

เริ่มต้น

ดาวน์โหลด SnapKit ในโปรเจกต์ ผมใช้ CocoaPods สำหรับ Library ภายนอก

เพิ่ม pod 'SnapKit' ใน Podfile รัน pod install เขียน import SnapKit บนไฟล์ที่ต้องการใช้

จัด Layout Subview ใน Superview

ก่อนอื่น Pin Subview ไปขอบ Superview:

let subview = UIView() view.addSubview(subview)
subview.snp.makeConstraints { (make) in make.top.equalTo(view) make.bottom.equalTo(view) make.left.equalTo(view) make.right.equalTo(view) }

ตั้ง Constraints ขอบบน ล่าง ซ้าย ขวาของ Subview ให้ตรงขอบ Superview ด้วย Constant 0

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps
Subview Pin ไปขอบ Superview ด้วย Constant 0

สังเกตว่า Add Subview ไป Superview ก่อนตั้ง Constraints ถ้าเขียน Constraints สำหรับ View ที่ยังไม่ Add ไป Superview จะ Error Fatal Runtime ตอน Load View

Syntax SnapKit อ่านง่ายกว่า Standard Library แล้ว แต่ย่อได้อีก SnapKit ให้วิธีสั้นกว่าจัด Constraint View ไปขอบ Superview:

let subview = UIView() view.addSubview(subview)
subview.snp.makeConstraints { (make) in make.top.bottom.left.right.equalTo(view) }

Layout Subview เหมือนโค้ดข้างต้น แต่ 1 บรรทัดแทน 4 บรรทัด

ยังกำหนดขนาด Subview ได้ ด้านล่างตั้ง Height, Width และจัดกึ่งกลาง Superview:

subview.snp.makeConstraints { (make) in make.width.equalTo(200) make.height.equalTo(200) make.centerX.equalTo(view) make.centerY.equalTo(view) }
เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps

ตัวอย่างง่ายแต่ซ้ำโค้ดมาก SnapKit ให้ Chain Constraints ที่มีค่าเดียวกันได้:

subview.snp.makeConstraints { (make) in make.width.height.equalTo(200) make.centerX.centerY.equalTo(view) }

Block นี้ให้ Constraints เหมือนข้างต้น อีกวิธี SnapKit ช่วยเขียนโค้ดสะอาด

จัด Layout Subviews เทียบกัน

เพิ่ม Subviews หลายตัวใน View เดียว น่าจะอยาก Layout Subviews เทียบกัน ตัวอย่างนี้:

  1. เพิ่ม subview1 Constraint ไปขอบซ้าย Superview
  2. เพิ่ม subview2 Constraint ไปขอบขวาของ subview1
let subview1 = UIView() let subview2 = UIView() view.addSubview(subview1) view.addSubview(subview2)
subview1.snp.makeConstraints { (make) in make.width.height.equalTo(100) make.left.equalTo(view) }
subview2.snp.makeConstraints { (make) in make.width.height.equalTo(subview1) make.left.equalTo(subview1.snp.right) }

จนตอนนี้ Constraints ต้องการ Equal กับ Constraint ตรงข้ามของ Relative View เช่น make.left.equalTo(view) SnapKit ตั้ง left ของ subview1 ให้ left ของ view SnapKit จับคู่ Constraint อัตโนมัติหากไม่ระบุอื่น

สำหรับ Constraint left ของ subview2 ต้องการตั้งให้ขอบขวาของ subview1 ถ้าเขียน make.left.equalTo(subview1) SnapKit จะตั้ง left ของ subview2 ให้ left ของ subview1 แทน จึงใช้ขอบขวาของ subview1 โดยเขียน subview1.snp.right

เข้าถึง Constraint ใดๆ ของ View Layout ได้โดยเพิ่ม snp ตามตัวอย่าง

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps
subview 2 Constraint ไปขวาของ subview 1 ด้วย Constant 0

ตอนนี้ subview2 อยู่ขวา subview1 สร้าง Space ระหว่างกันด้วย Offset เพิ่มใน subview2

subview2.snp.makeConstraints { (make) in make.width.height.equalTo(subview1) make.left.equalTo(subview1.snp.right).offset(50) }

Offset เพิ่มท้าย equalTo() ใดๆ เพื่อเปลี่ยน Constant ของ Constraint ตอนนี้ subview2 มี Constant 50 บน Constraint left

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps
subview 2 Constraint กับ subview 1 ด้วย Constant 50

Update และ Animate Constraints

อยากให้แอปเป็น #NextBigThing ต้องเพิ่ม Flair นิดหน่อย SnapKit ให้ Update Constraints สร้าง Dynamic Views ได้ง่าย

Update Constraint ด้วย SnapKit คล้ายเพิ่มใหม่ ตัวอย่าง Update Constraint subview1 จากตัวอย่างก่อน เปลี่ยน Constant left จาก 0 เป็น 50:

subview1.snp.updateConstraints { (make) in make.left.equalTo(50) }

แค่นี้! Subview จะ Update ไป Constraints ใหม่ตอนรัน Block

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps
กดปุ่ม Update Constraints ของ subview1

สังเกตว่า subview2 เคลื่อนที่ตอน Update subview1 แม้ไม่ Update Constraints ของมัน subview2 Constraint ไปขวา subview1 ตอน subview1 ย้าย subview2 ยังเคารพ Constraint left กับ subview1

เพิ่ม Animation ทำ Transition นุ่มนวล Syntax คุ้นเคยถ้าเคย Animate View:

UIView.animate(withDuration: 0.3) { subview1.snp.updateConstraints { (make) in make.left.equalTo(50) } self.view.layoutIfNeeded() }

ตอน Animate Update Constraints ต้องเรียก layoutIfNeeded() บน Parent ของ Subview ถ้า Animate หลาย View พร้อมกัน เรียก layoutIfNeeded() บน Closest Common Superview

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps

updateConstraints() Update Constraints ที่มีอยู่แล้วพยายาม Update Constraint ที่ยังไม่มี จะ Error Fatal Runtime

อยากเพิ่ม Constraints ใหม่ให้ Subview ใช้ remakeConstraints() remakeConstraints() ลบ Constraints เดิมทั้งหมดบน Subview นั้น และเพิ่มใหม่ได้

ยังใช้ deactivate() ลบ Constraint ได้ ด้านล่างสร้าง ตั้ง และลบ Constraint ด้วย deactivate():

var constraint: Constraint! let subview = UIView()
subview.snp.makeConstraints { (make) in constraint = make.height.equalTo(100).constraint }
constraint.deactivate()

ยัง Animate การลบ Constraint ได้โดย Deactivate ภายใน Animation Block

ตอนนี้คุณ Master เขียน Constraints แบบ Programmatic แล้ว Storyboard ดูเหมือนขำขัน ไม่มีเหตุผลกลับไปใช้อีกแล้วใช่ไหม?

เชี่ยวชาญ SnapKit: เขียน Constraints แบบ Programmatic ให้สะอาดสำหรับ iOS Apps
รูปแบบการ Build Storyboard หลังอ่านคู่มือนี้

ไม่จริง Storyboards และ Nibs ยังเป็นวิธีเร็วที่สุดรวม View Controller และถ้าทำงานกับ Non-Developers เป็นวิธีดีที่สุดแสดงรูปลักษณ์แอปโดยไม่ส่ง Beta

ส่วนตัวผมใช้ทั้งคู่ โปรเจกต์ล่าสุดเพิ่ม Constraints ทั้งโค้ดกับ SnapKit และ Auto Layout บน Storyboards/Nibs บางครั้งบน View เดียวกัน ท้ายที่สุดต้องตัดสินใจว่าอะไรเหมาะกับ View ที่สร้าง

ขอบคุณที่อ่าน! ถ้าชอบ ติดตาม Twitter ผมโพสต์บทความ Product Management, Engineering, และ Design