Tôi có một UIView được đặt trên màn hình thông qua một số ràng buộc. Một số ràng buộc thuộc sở hữu của superview, một số ràng buộc khác thuộc sở hữu của tổ tiên khác (ví dụ: có lẽ thuộc tính view của UIViewController).
Tôi muốn loại bỏ tất cả các ràng buộc cũ này và đặt nó vào một nơi mới bằng cách sử dụng các ràng buộc mới.
Làm cách nào tôi có thể thực hiện việc này mà không cần tạo IBOutlet cho mọi ràng buộc đơn lẻ và phải nhớ chế độ xem nào sở hữu ràng buộc nói trên?
Nói một cách chi tiết, cách tiếp cận đơn giản sẽ là tạo một loạt các IBOutlet cho mỗi ràng buộc và sau đó sẽ liên quan đến việc gọi mã như:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Vấn đề với mã này là ngay cả trong trường hợp đơn giản nhất, tôi sẽ cần tạo 2 IBOutlet. Đối với các bố cục phức tạp, điều này có thể dễ dàng đạt được 4 hoặc 8 IBOutlet yêu cầu. Hơn nữa, tôi cần đảm bảo rằng lệnh gọi của tôi để loại bỏ ràng buộc đang được gọi trên dạng xem thích hợp. Ví dụ, hãy tưởng tượng rằng nó myViewsLeftConstraint
được sở hữu bởi viewA
. Nếu tôi vô tình gọi [self.view removeConstraint:self.myViewsLeftConstraint]
thì sẽ không có chuyện gì xảy ra.
Lưu ý: Các ràng buộc của phương thứcAffectingLayoutForAxis trông có vẻ hứa hẹn, nhưng chỉ dành cho mục đích gỡ lỗi.
Cập nhật: Nhiều người trong số các câu trả lời tôi nhận được thỏa thuận với self.constraints
, self.superview.constraints
hoặc một số biến thể của những người. Các giải pháp này sẽ không hoạt động vì các phương thức đó chỉ trả về các ràng buộc thuộc sở hữu của chế độ xem, không trả về các ràng buộc ảnh hưởng đến chế độ xem.
Để làm rõ vấn đề với các giải pháp này, hãy xem xét hệ thống phân cấp chế độ xem này:
- Ông nội
- Bố
- Tôi
- Con trai
- Con gái
- Anh trai
- Tôi
- Chú
- Bố
Bây giờ hãy tưởng tượng chúng ta tạo các ràng buộc sau và luôn gắn chúng với tổ tiên chung gần nhất của chúng:
- C0: Tôi: cùng top với Son (thuộc sở hữu của Tôi)
- C1: Tôi: chiều rộng = 100 (thuộc sở hữu của Tôi)
- C2: Tôi: cùng chiều cao với Anh (thuộc sở hữu của Cha)
- C3: Tôi: cùng top với Bác (thuộc sở hữu của Ông)
- C4: Tôi: cùng bên trái với Ông (thuộc sở hữu của Ông)
- C5: Anh trai: cùng bên trái với Cha (thuộc sở hữu của Cha)
- C6: Chú: cùng bên trái với Ông (thuộc sở hữu của Ông)
- C7: Con trai: cùng bên trái với Con gái (thuộc sở hữu của Tôi)
Bây giờ hãy tưởng tượng chúng ta muốn loại bỏ tất cả các ràng buộc ảnh hưởng Me
. Bất kỳ giải pháp thích hợp nào nên loại bỏ [C0,C1,C2,C3,C4]
và không có gì khác.
Nếu tôi sử dụng self.constraints
(nơi tự là Tôi), tôi sẽ nhận được [C0,C1,C7]
, vì đó là những ràng buộc duy nhất thuộc sở hữu của Tôi. Rõ ràng là sẽ không đủ để loại bỏ điều này vì nó bị thiếu [C2,C3,C4]
. Hơn nữa, nó đang loại bỏ C7
không cần thiết.
Nếu tôi sử dụng self.superview.constraints
(nơi tự là Tôi), tôi sẽ nhận được [C2,C5]
, vì đó là những ràng buộc thuộc sở hữu của Cha. Rõ ràng là chúng tôi không thể xóa tất cả những điều này vì C5
hoàn toàn không liên quan đến Me
.
Nếu tôi sử dụng grandfather.constraints
, tôi sẽ nhận được [C3,C4,C6]
. Một lần nữa, chúng tôi không thể xóa tất cả những thứ này vì nó C6
sẽ vẫn còn nguyên vẹn.
Cách tiếp cận brute force là lặp lại từng tổ tiên của chế độ xem (bao gồm cả chính nó) và xem liệu chế độ xem có firstItem
hay secondItem
không; nếu vậy, hãy loại bỏ ràng buộc đó. Điều này sẽ dẫn đến một giải pháp chính xác, quay trở lại [C0,C1,C2,C3,C4]
và chỉ những ràng buộc đó.
Tuy nhiên, tôi hy vọng có một giải pháp thanh lịch hơn là phải lặp lại toàn bộ danh sách tổ tiên.