2013-09-25 82 views
33

Tôi đang gặp sự cố với tính năng tự động điền trong dự án xcode 5. Tôi đang sử dụng một bộ điều khiển xem đơn giản bên trong với một bộ điều khiển điều hướng. Tôi có một số MKMapView ở nửa trên và UITableView ở nửa dưới. Tôi đang sử dụng storyboards và đã định cấu hình mẫu thử nghiệm UITableViewCell, nhưng tôi đang thêm các ràng buộc thông qua mã. Tôi đã kiểm tra lại mọi điều khiển trong nguyên mẫu và không thấy bất kỳ ràng buộc nào được định cấu hình ở đó. Vấn đề của tôi xảy ra khi tôi thêm các ràng buộc cho UITableViewCell. Tôi có mã sau trong các ô:Sự cố với Tự động hoàn tất trên UITableViewCell

-(void)updateConstraints { 
    [super updateConstraints]; 
    //first remove old constraints 
    [self removeConstraints:self.constraints]; 
    [self.nameLabel removeConstraints:self.nameLabel.constraints]; 
    [self.addressLabel removeConstraints:self.nameLabel.constraints]; 
    [self.rentableSquareFeetLabel removeConstraints:self.rentableSquareFeetLabel.constraints]; 
    [self.lastSaleAmountLabel removeConstraints:self.lastSaleAmountLabel.constraints]; 
    [self.lastSaleDateLabel removeConstraints:self.lastSaleAmountLabel.constraints]; 
    [self.thumbnailImageView removeConstraints:self.thumbnailImageView.constraints]; 

    //then set up constraints 
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_thumbnailImageView, _nameLabel, _rentableSquareFeetLabel, _lastSaleAmountLabel, _addressLabel, _lastSaleDateLabel); 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_thumbnailImageView(60)]-[_nameLabel(<=200)]-(>=8)-[_rentableSquareFeetLabel]-(>=8)-[_lastSaleAmountLabel]|" options:0 metrics:nil views:viewsDictionary]]; 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_nameLabel]-(-4)-[_addressLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]]; 
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_lastSaleAmountLabel]-(-4)-[_lastSaleDateLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]]; 
} 

Tôi nhận được thông tin sau trong bảng điều khiển gỡ lỗi. Ngoại lệ được kích hoạt bởi dòng addConstraints đầu tiên. Nếu tôi chỉ cần tiếp tục thông qua những sau đó cuối cùng tất cả mọi thứ xuất hiện như nó phải được, vì nó trông giống như xcode được lựa chọn để phá vỡ các hạn chế chính xác:

2013-09-25 15:07:14.169 PECProperties[32381:a0b] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) (
    "<NSIBPrototypingLayoutConstraint:0x9d56c70 'IB auto generated at build time for view with fixed frame' H:|-(0)-[UIImageView:0x9d558f0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620)>", 
    "<NSIBPrototypingLayoutConstraint:0x9d56d20 'IB auto generated at build time for view with fixed frame' H:[UIImageView:0x9d558f0(60)]>", 
    "<NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620)>", 
    "<NSLayoutConstraint:0x9d53830 H:[UIImageView:0x9d558f0]-(NSSpace(8))-[UILabel:0x9d559e0]>") 

Will attempt to recover by breaking constraint <NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR) (Names: '|':UITableViewCellContentView:0x9d55620)> 

Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 

Các NSIBPrototypingLayoutConstraint thứ ba cho thấy 78 điểm giữa các cạnh của quan điểm và một nhãn. Đó là nơi nguyên mẫu được định vị gần (và nếu tôi di chuyển nó trong nguyên mẫu, tôi thấy sự thay đổi trong ràng buộc trong bảng điều khiển gỡ lỗi), nhưng xung đột với khoảng cách "chuẩn" của riêng tôi giữa chế độ xem hình ảnh và nhãn .

Tôi đã thử đặt translatesAutoresizingMaskIntoConstraints=NO trong bộ điều khiển của chế độ xem cellForRowAtIndexPath, nhưng điều đó dường như không giúp được gì. Làm thế nào tôi có thể sửa bố cục?

+0

Tôi nhận thấy lỗi từng người một trong iOS7 gây ra sự cố tương tự. Tôi đã xác định tất cả các ràng buộc trong IB và XCode là hạnh phúc. Nhưng tổng của tất cả các kích thước dọc trong ngoại lệ Matt

Trả lời

78

Một số điều cần che ở đây:

  1. Các NSIBPrototypingLayoutConstraint khó khăn mà bạn đang chạy vào (và đang gây ra trường hợp ngoại lệ) được tự động tạo ra bởi giao diện Builder để làm cho Storyboard hoặc XIB của bạn xem bố cục không mơ hồ. Nó khá lén lút về việc này, nhưng nó tự động thêm các ràng buộc tối thiểu cần thiết để vị trí và kích thước của mỗi chế độ xem mơ hồ trở nên được chỉ định đầy đủ. Đây là một sự thay đổi từ Xcode 4, bởi vì trong Xcode 4 bạn không thể có các bố cục mơ hồ trong Interface Builder. Với Xcode 5 và sau đó bạn có thể, tuy nhiên IB sẽ tự động tạo ra những ràng buộc cho bạn nếu bố cục của bạn là mơ hồ tại thời gian biên dịch.

    Cách khắc phục sự cố này là thêm các ràng buộc bắt buộc tối thiểu trong Trình tạo giao diện để vị trí của mỗi lượt xem & được chỉ định đầy đủ, sau đó chọn từng ràng buộc không mong muốn này, chuyển đến thanh bên bên phải Thanh tra thuộc tính và kiểm tra hộp bên cạnh Trình giữ chỗ - Xóa tại thời gian xây dựng.

    Screenshot of the constraint Placeholder checkbox in Xcode 6.

    Không chỉ hộp kiểm này loại bỏ các hạn chế bạn thêm vào, nhưng quan trọng nhất là nó sẽ ngăn chặn việc tự động tạo IB chế từ đang diễn ra của nó! (Như bạn có thể hình dung, điều này khá tẻ nhạt khi bạn có một số quan điểm trong IB và muốn quản lý tất cả các ràng buộc của bạn trong mã. Vì lý do này, bạn có thể tránh sử dụng IB hoàn toàn cho các cấu trúc phân cấp khung nhìn mà bạn dự định triển khai Auto Bố trí theo lập trình.)

    Sự khác nhau giữa ràng buộc Trình giữ chỗ và ràng buộc Gỡ cài đặt là gì? Dưới đây là một slide từ tôi Adaptive Auto Layout talk (video) (PDF slides) so sánh hai:

    Comparison between Placeholder constraints and Uninstalled constraints.

  2. Trong updateConstraints, bạn không muốn loại bỏ những hạn chế và tái thêm chúng như bạn có ở đó. Tại sao không?Về cơ bản, nó thật khủng khiếp cho hiệu suất, và tôi đã xác nhận với các kỹ sư của Apple rằng đây không phải là một ý tưởng hay. Xem question/answer I have posted here để biết thêm chi tiết, cũng như số answer này. Để ngăn chặn các ràng buộc được thêm nhiều lần, sử dụng cờ boolean (ví dụ: hasSetupConstraints) mà bạn đặt thành CÓ khi bạn đã thiết lập ràng buộc lần đầu tiên và nếu updateConstraints được gọi lại, bạn có thể quay lại ngay lập tức nếu bạn không có các ràng buộc mới cần thêm. Xem this question để thảo luận thêm.

  3. Mã bạn đang sử dụng để xóa các ràng buộc có thể không hoạt động hoàn toàn. Điều này là do [view removeConstraints:view.constraints] sẽ chỉ xóa các ràng buộc đã được thêm vào view - hãy nhớ rằng các ràng buộc có thể được thêm vào bất kỳ giám sát chung nào về các chế độ xem mà chúng hạn chế - và các ràng buộc được thêm vào view có thể không phải là những ràng buộc duy nhất ảnh hưởng đến bố cục của view ! Nếu bạn cần loại bỏ một số ràng buộc, bạn nên lưu trữ một tham chiếu đến từng ràng buộc đó trong một thuộc tính (ví dụ một thuộc tính NSArray chứa các cá thể NSLayoutConstraint), và sau đó hủy kích hoạt/loại bỏ các ràng buộc đó bằng cách sử dụng API trên NSLayoutConstraint hoặc the PureLayout open-source library. Bạn chỉ nên vô hiệu hóa/loại bỏ ít ràng buộc nhất có thể bởi vì nó có tính toán tốn kém để làm như vậy. Mặt khác, việc thay đổi constant của bất kỳ ràng buộc nào là rất hiệu quả và được khuyến khích, và bạn không cần phải loại bỏ hoặc thêm lại ràng buộc để làm điều đó.

+0

Cảm ơn bạn rất nhiều vì đã giúp đỡ bạn. Tôi đã thêm các ràng buộc trong IB, đánh dấu chúng là trình giữ chỗ và tránh ngoại lệ. Trong suy nghĩ thông qua phần còn lại của lời khuyên của bạn, tôi nghĩ rằng không có nhiều lý do tại sao tôi không thể xác định tất cả các ràng buộc trong IB và loại bỏ các mã hoàn toàn. Đây là dự án đầu tiên của tôi với autolayout, và trên bộ điều khiển khung nhìn, tôi cần thêm/gỡ bỏ các ràng buộc khi xoay, do đó, về cơ bản tôi cố gắng thực hiện cùng một cách tiếp cận trên ô xem bảng. Nhưng như bạn đã chỉ ra, tôi không cần. Cảm ơn một lần nữa! –

+0

Không sao cả. Nếu bạn có thể nhận được những hạn chế làm việc tốt từ IB, hãy cho nó. Nhưng cá nhân tôi về cơ bản đã ngừng sử dụng IB hoàn toàn, đặc biệt là khi nói đến Auto Layout. IB trông rất đơn giản nhưng có thể gây ra rất nhiều đau đớn cho bất cứ thứ gì nhưng đơn giản nhất là thiết lập chế độ xem (thông thường, những gì bạn thấy là ** không ** những gì bạn nhận được!). Dù sao ... cảm thấy tự do để hỏi nếu bạn chạy qua bất kỳ khối ngại nào khác. – smileyborg

+0

Tôi không hiểu ý bạn là gì? "Hộp kiểm này không chỉ loại bỏ ràng buộc mà bạn đã thêm" tại sao bạn muốn loại bỏ ràng buộc mà bạn vừa thêm vào? – drc