เมื่อฉันเริ่มสร้างแอปด้วย Xcode ครั้งแรก ฉันคิดว่าสตอรี่บอร์ดเป็นสิ่งมหัศจรรย์ การลากและวางการดูย่อยเข้าที่นั้นทำได้ง่ายมาก ฉันไม่เคยเข้าใจว่าผู้คนสร้างการดูโดยไม่มีการดูได้อย่างไร
ในที่สุด ฉันตัดสินใจว่าจะเป็น "โปรแกรมเมอร์ระดับปรมาจารย์" ฉันต้องเรียนรู้วิธีสร้างมุมมองแบบเป็นโปรแกรม ปัญหาหนึ่ง การเขียนข้อจำกัดในโค้ดเป็นเรื่องที่ยุ่งยาก
let horizontalConstraint = NSLayoutConstraint( item: newView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
นั่นคือข้อจำกัดในแนวนอนที่จะจัดกึ่งกลางมุมมองย่อยบนแกน X ของการตรวจสอบ ไม่ง่ายเลยที่จะอ่านและเขียนว่าทุกข้อจำกัดนั้นเก่าไปอย่างรวดเร็ว ถึงกระนั้น ฉันต้องการที่จะทิ้งกระดานเรื่องราวดังนั้นฉันจึงค้นหาทางเลือกอื่น นั่นคือตอนที่ฉันพบ SnapKit
SnapKit มี API ที่ชัดเจนและรัดกุมที่ทำให้การเขียนข้อจำกัดในโค้ดเป็นเรื่องง่าย ฉันจะพูดถึงตัวอย่างเบื้องต้นเกี่ยวกับสิ่งที่สามารถทำได้ใน SnapKit
ฉันจะไปมากกว่า:
- วางเค้าโครงย่อยในการดูแล
- การจัดวางมุมมองย่อยที่สัมพันธ์กัน
- กำลังอัปเดตและจำกัดการเคลื่อนไหว
เริ่มต้นใช้งาน
ตรวจสอบให้แน่ใจว่าคุณดาวน์โหลด SnapKit ในโครงการของคุณ ฉันใช้ Cocoapods สำหรับห้องสมุดบุคคลที่สาม
เพิ่ม pod 'SnapKit'
ไปที่ Podfile ของคุณและเรียกใช้ pod install
. ตอนนี้เขียน import SnapKit
ที่ด้านบนของไฟล์ที่คุณต้องการใช้
การจัดวางมุมมองย่อยในการควบคุมดูแล
ก่อนอื่น ฉันจะปักหมุดมุมมองย่อยไว้ที่ขอบของการดูแล:
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)}
การดำเนินการนี้จะกำหนดข้อจำกัดสำหรับขอบด้านบน ด้านล่าง ด้านซ้าย และด้านขวาของมุมมองย่อยเป็นขอบที่สอดคล้องกันของ superview ที่มีค่าคงที่เป็น 0
สังเกตว่าฉันเพิ่มการดูย่อยในการดูแลก่อนที่จะตั้งค่าข้อจำกัดของมุมมองย่อย หากคุณเขียนข้อจำกัดสำหรับมุมมองที่ยังไม่ได้เพิ่มใน superview จะทำให้เกิดข้อผิดพลาดรันไทม์ร้ายแรงเมื่อโหลดมุมมอง
ไวยากรณ์ SnapKit สามารถอ่านได้มากกว่าไลบรารีมาตรฐานอยู่แล้ว แต่สามารถย่อให้สั้นลงได้ SnapKit เป็นวิธีที่รัดกุมยิ่งขึ้นในการจำกัดมุมมองไว้ที่ขอบของ superview:
let subview = UIView()view.addSubview(subview)
subview.snp.makeConstraints { (make) in make.top.bottom.left.right.equalTo(view)}
สิ่งนี้จะเลย์เอาต์ย่อยของฉันในลักษณะเดียวกับโค้ดด้านบน แต่มีหนึ่งบรรทัดแทนที่จะเป็นสี่
ฉันยังสามารถจำกัดขนาดของมุมมองย่อยของฉันได้ ด้านล่างนี้ ฉันจะกำหนดความสูงและความกว้างของมุมมองย่อยและตั้งไว้ที่กึ่งกลางของมุมมองย่อย:
subview.snp.makeConstraints { (make) in make.width.equalTo(200) make.height.equalTo(200) make.centerX.equalTo(view) make.centerY.equalTo(view)}
ตัวอย่างนั้นค่อนข้างง่าย แต่ฉันพูดซ้ำบ่อยมาก เมื่อตั้งค่าข้อจำกัดที่มีค่าเหมือนกัน SnapKit ช่วยให้ฉันสามารถโยงข้อจำกัดต่างๆ เข้าด้วยกันดังนี้:
subview.snp.makeConstraints { (make) in make.width.height.equalTo(200) make.centerX.centerY.equalTo(view)}
การบล็อกนี้จะส่งผลให้มีข้อจำกัดเช่นเดียวกับข้อข้างต้น อีกวิธีหนึ่งที่ SnapKit ช่วยในการเขียนโค้ดที่สะอาดยิ่งขึ้น
การจัดวางการดูย่อยที่สัมพันธ์กัน
เมื่อเพิ่มการดูย่อยจำนวนมากในมุมมองเดียว มีแนวโน้มว่าคุณจะต้องการจัดวางการดูย่อยให้สัมพันธ์กัน ในตัวอย่างนี้ ฉันจะ:
- เพิ่ม
subview1
และบังคับมันไว้ที่ขอบด้านซ้ายของ superview - เพิ่ม
subview2
และจำกัดไว้ที่ขอบขวาของ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)}
จนถึงตอนนี้ ฉันต้องการให้ข้อจำกัดของฉันเท่ากับข้อจำกัดที่สอดคล้องกันสำหรับมุมมองแบบสัมพัทธ์ ตัวอย่างเช่น ใน make.left.equalTo(view)
SnapKit ตั้งค่า left
จาก subview1
ไปที่ left
จาก view
. SnapKit จะจับคู่กับข้อจำกัดที่ฉันตั้งไว้โดยอัตโนมัติหากฉันไม่ได้ระบุเป็นอย่างอื่น
สำหรับ left
ข้อจำกัดของ subview2
ฉันต้องการตั้งค่าเป็น right
ขอบของ subview1
. ถ้าฉันเขียน make.left.equalTo(subview1)
SnapKit จะตั้งค่า left
ขอบ subview2
ไปที่ left
ขอบของ subview1
. แต่ฉันใช้ right
. แทน ขอบ subview1
ที่ผมคว้ามาโดยการเขียน subview1.snp.right
.
ฉันเข้าถึงข้อจำกัดของเลย์เอาต์ของมุมมองได้โดยเพิ่ม snp
ดังที่เห็นด้านบน
ตอนนี้มี subview2
. แล้ว ทางขวาของ subview1
ฉันจะสร้างช่องว่างระหว่างพวกเขาโดยเพิ่ม ออฟเซ็ต ถึง subview2
.
subview2.snp.makeConstraints { (make) in make.width.height.equalTo(subview1) make.left.equalTo(subview1.snp.right).offset(50)}
สามารถใส่ offset ต่อท้าย equalTo()
. ใดก็ได้ เพื่อเปลี่ยนค่าคงที่ของข้อจำกัดนั้น ตอนนี้ subview2
จะมีค่าคงที่ 50 ใน left
ข้อจำกัด
กำลังอัปเดตและข้อจำกัดด้านภาพเคลื่อนไหว
หากคุณต้องการให้แอปของคุณเป็น #NextBigThing ที่ทุกคนรู้ คุณจะต้องเพิ่มไหวพริบ! SnapKit มีวิธีอัปเดตข้อจำกัดเพื่อสร้างมุมมองไดนามิกอย่างง่ายดาย
การอัปเดตข้อจำกัดด้วย SnapKit เกือบจะเหมือนกับการเพิ่มข้อจำกัดใหม่ ฉันจะอัปเดตข้อจำกัดสำหรับ subview1
จากตัวอย่างก่อนหน้านี้โดยเปลี่ยน left
ค่าคงที่ข้อจำกัดขอบจาก 0 ถึง 50:
subview1.snp.updateConstraints { (make) in make.left.equalTo(50)}
และนั่นแหล่ะ! มุมมองย่อยของฉันจะอัปเดตเป็นข้อจำกัดใหม่เมื่อมีการเรียกใช้บล็อกโค้ด
คุณอาจสังเกตเห็นว่า subview2
ย้ายเมื่อฉันอัปเดต subview1
แม้ว่าฉันจะไม่ได้อัปเดตข้อจำกัดของมันก็ตามsubview2
ถูกจำกัดไว้ที่ขอบขวาของ subview1
. เมื่อ subview1
ถูกย้าย subview2
จะยังคงปฏิบัติตามข้อจำกัดด้านซ้ายที่มี subview1
.
ตอนนี้ฉันจะเพิ่มแอนิเมชั่นเพื่อทำให้ช่วงการเปลี่ยนภาพราบรื่นขึ้น หากคุณเคยดูภาพเคลื่อนไหวมาก่อน ไวยากรณ์นี้จะคุ้นเคย:
UIView.animate(withDuration: 0.3) { subview1.snp.updateConstraints { (make) in make.left.equalTo(50) } self.view.layoutIfNeeded()}
เมื่อทำการอัปเดตเกี่ยวกับข้อจำกัดของฉัน ฉันต้องโทร layoutIfNeeded()
บนพาเรนต์ย่อยของ หากฉันสร้างภาพเคลื่อนไหวมากกว่าหนึ่งมุมมองในคราวเดียว ฉันจะต้องเรียก layoutIfNeeded()
ในการกำกับดูแลทั่วไปที่ใกล้เคียงที่สุดของมุมมองย่อย
updateConstraints()
สามารถอัปเดตข้อจำกัดที่มีอยู่เท่านั้น การพยายามอัปเดตข้อจำกัดที่ยังไม่มีอยู่จะส่งผลให้เกิดข้อผิดพลาดรันไทม์ร้ายแรง
หากคุณต้องการเพิ่มข้อจำกัดใหม่ให้กับมุมมองย่อยของคุณ ให้ใช้ remakeConstraints()
. remakeConstraints()
จะลบข้อจำกัดที่มีอยู่ใดๆ ที่คุณตั้งไว้ในมุมมองย่อยนั้น และให้คุณเพิ่มรายการใหม่ได้
คุณยังสามารถใช้ deactivate()
เพื่อลบข้อจำกัด ด้านล่างฉันสร้าง ตั้งค่า และลบข้อจำกัดโดยใช้ deactivate()
:
var constraint: Constraint!let subview = UIView()
subview.snp.makeConstraints { (make) in constraint = make.height.equalTo(100).constraint}
constraint.deactivate()
คุณยังสามารถทำให้การลบข้อจำกัดเคลื่อนไหวได้ด้วยการปิดใช้งานภายในบล็อกแอนิเมชั่น
ดังนั้นตอนนี้ คุณเป็นผู้เชี่ยวชาญในการเขียนข้อจำกัดทางโปรแกรม สตอรี่บอร์ดดูเหมือนเป็นเรื่องตลกในตอนนี้และไม่มีเหตุผลที่จะต้องกลับไปดูอีกแล้วใช่ไหม
ไม่เชิง. สตอรี่บอร์ดและ nibs ยังคงเป็นวิธีที่เร็วที่สุดในการรวบรวม view controller และหากคุณทำงานกับผู้ที่ไม่ใช่นักพัฒนา สิ่งเหล่านี้เป็นวิธีที่ดีที่สุดในการแสดงว่าแอปจะมีหน้าตาเป็นอย่างไรโดยไม่ต้องส่งเวอร์ชันเบต้า
ส่วนตัวผมใช้ทั้งสองอย่าง ในแอพล่าสุดที่ฉันสร้าง ฉันได้เพิ่มข้อจำกัดทั้งในโค้ดด้วย SnapKit และการใช้เค้าโครงอัตโนมัติบนกระดานเรื่องราวและปลายปากกา ซึ่งบางครั้งก็อยู่ในมุมมองเดียวกัน ในท้ายที่สุด คุณจะต้องตัดสินใจว่าสิ่งใดดีที่สุดสำหรับมุมมองที่คุณกำลังสร้าง
ขอบคุณมากสำหรับการอ่าน! หากคุณชอบเรื่องนี้ ติดตามฉันบน Twitter ที่ฉันโพสต์บทความเกี่ยวกับการจัดการผลิตภัณฑ์ วิศวกรรม และการออกแบบ