2012-10-24 23 views
50

Tôi có một subview mà tôi muốn giữ lại các điểm dừng trong màn hình xoay, vì vậy tôi quyết định đưa loại NSLayoutConstraint:

Trailing Space để SuperView
Lên trên Không gian để Superview
Không gian nút để Superview
Tôi đang ở trong một phân lớp của UITableViewCell. Tôi đã viết code nhưng tôi nhận được lỗi sau:
'NSInvalidArgumentException', lý do: 'Không thể phân tích định dạng constraint'

'NSInvalidArgumentException', reason: 'Unable to parse constraint format: 
self is not a key in the views dictionary. 
H:[self.arrows]-5-| 


Mã của tôi trong CustomCell.m là:

self.arrows = [[Arrows alloc]initWithFrame:CGRectMake(self.contentView.bounds.size.width-30, self.bounds.origin.y+4, 30, self.contentView.bounds.size.height-4)]; 

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self.arrows, self.contentView); 
NSMutableArray * constraint=[[NSMutableArray alloc]init]; 
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H: [self.arrows]-5-|" options:0 metrics:nil views:viewsDictionary]]; 
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-1-[self.arrows]" options:0 metrics:nil views:viewsDictionary]]; 
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"[V: [self.arrows]-1-|" options:0 metrics:nil views:viewsDictionary]]; 
[self.arrows addConstraints:constraint]; 

Trả lời

121

Dường như rằng động cơ autolayout định dạng hình ảnh phân tích cú pháp được giải thích "." trong ràng buộc VFL của bạn là một keyPath thay vì một khóa như nó sử dụng valueForKeyPath:.

NSDictionaryOfVariableBindings(...) sẽ lấy bất kỳ thông số nào của bạn nằm trong dấu ngoặc đơn và dịch nó thành khóa bằng chữ với đối tượng làm giá trị (trong trường hợp của bạn: @{"self.arrow" : self.arrow}). Trong trường hợp của VFL, autolayout đang nghĩ rằng bạn có một khóa có tên self trong từ điển xem của bạn với một subdictionary (hoặc subobject) mà có một chìa khóa của arrow,

@{ 
    @"self" : @{ @"arrow" : self.arrow } 
} 

khi bạn có nghĩa là muốn hệ thống để giải thích khóa của bạn là "self.arrow".

Thông thường, khi tôi đang sử dụng một trường hợp biến getter như thế này, tôi thường kết thúc việc tạo từ điển riêng của tôi thay vì sử dụng NSDictionaryOfVariableBindings(...) như vậy:

NSDictionary *views = @{ @"arrowView" : self.arrow } 

hoặc

NSDictionary *views = NSDictionaryOfVariableBindings(_arrow); 

nào sẽ cho phép bạn sử dụng chế độ xem trong VFL mà không có bản thân và bạn vẫn biết những gì bạn đang nói về:

NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views]; 

hoặc

NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views]; 

Theo nguyên tắc chung, tôi đã học không có các phím từ điển với một dấu chấm (.) trong đó để tránh bất kỳ sự nhầm lẫn hệ thống hoặc những cơn ác mộng gỡ lỗi.

+1

Thank you very much –

+25

Khá nực cười rằng các tài liệu cung cấp cho ví dụ về sử dụng 'NSDictionaryOfVariableBindings' để tạo từ điển, nhưng không đề cập đến rằng nó sẽ không làm việc với bất kỳ tài sản hoặc IBOutlets –

+0

Jonathan, tôi khá bối rối vì điều này. Các tài liệu cụ thể nhà nước để sử dụng phương pháp đó. Tôi chỉ đoán nó đủ thông minh để loại bỏ cái tôi. một phần của khóa tự động. – Nailer

7

Bí quyết của tôi là chỉ cần khai báo biến cục bộ chỉ là một con trỏ khác đến thuộc tính và đặt nó vào trong NSDictionaryOfVariableBindings.

@interface ViewController() 
@property (strong) UIButton *myButton; 
@property (strong) UILabel *myLabel; 
@end 

... 

UIButton *myButtonP = self.myButton; 
UILabel *theLabelP = self.myLabel; 
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(myButtonP, myLabelP); 

Hậu tố P là dành cho "con trỏ".

+2

Điều này phủ nhận điểm của NSDictionaryOfVariableBindings, để làm cho mọi thứ ngắn hơn. Tại sao không sử dụng 'NSDictionary * views = @ {@" myButton ": self.myButton, @" myLabel ": self.myLabel}' thay thế? Nó ngắn hơn. –

+0

Nó không phủ nhận điểm nào cả, nếu bạn có một danh sách dài các khung nhìn khác và muốn chèn một tham chiếu đến 'self.view'. – davidf2281

+0

tại sao làm điều này thay vì sử dụng _myButton và _myLabel? hoặc tổng hợp để đặt tên cho ivars khác nhau? –

-1

Đảm bảo bạn thêm các ràng buộc sau khi thêm chế độ xem phụ bắt buộc vào chế độ xem chính của bạn. Phải mất một thời gian để có kiến ​​thức liên quan đến vấn đề này.

1

Giải pháp dễ nhất là tránh getters cho biến từ lớp của riêng bạn và xác định lại biến từ superclasses dưới dạng biến cục bộ.Một giải pháp ví dụ của bạn là

UIView *contentView = self.contentView; 
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);