2012-05-24 27 views
10

Tôi có một số thuộc tính xuất hiện tùy chỉnh trong lớp chế độ xem của tôi (con cháu của UIView). Tôi muốn tùy chỉnh sự xuất hiện quan điểm theo các đặc tính này, nhưng tôi không thể làm điều đó bên trong initializer, vì các giá trị thiết lập sử dụng [[MyClass appearance] setFoo:…] không có hiệu lực tại thời điểm đó:Khi nào tôi có thể bắt đầu sử dụng các thuộc tính được đặt bằng UIAppearance?

@interface View : UIView 
@property(strong) UIColor *someColor UI_APPEARANCE_SELECTOR; 
@end 

@implementation View 
@synthesize someColor; 

// Somewhere in other code before the initializer is called: 
// [[View appearance] setSomeColor:[UIColor blackColor]]; 

- (id) initWithFrame: (CGRect) frame 
{ 
    self = [super initWithFrame:frame]; 
    NSLog(@"%@", someColor); // nil 
    return self; 
} 

@end 

Họ đã thiết lập trong layoutSubviews, nhưng đó không phải là điểm tốt để thực hiện các tùy chỉnh chế độ xem, vì một số tùy chỉnh có thể kích hoạt lại layoutSubviews, dẫn đến vòng lặp vô tận.

Vì vậy, điểm tốt để thực hiện các tùy chỉnh là gì? Hoặc có cách nào để kích hoạt mã áp dụng các giá trị xuất hiện không?

+0

Tôi nghĩ rằng khi lớp tùy chỉnh được phân bổ, các thuộc tính của thành viên luôn có thể được truy cập và thay đổi theo yêu cầu và sau đó đối tượng có thể được sử dụng với thông tin đã sửa đổi trong mã. –

+1

Để chắc chắn, tôi đang nói về các thuộc tính được thiết lập thông qua proxy xuất hiện ('UIAppearance'). Các giá trị này được đặt ở đâu đó muộn hơn trong bộ khởi tạo. Nếu tôi đặt một điểm ngắt trên trình thiết lập thuộc tính, tôi có thể thấy rằng các giá trị được áp dụng từ '[CALayer layoutSublayers]'. – zoul

Trả lời

2

Một workaround có thể là để lấy các giá trị trực tiếp từ proxy:

- (id) initWithFrame: (CGRect) frame 
{ 
    self = [super initWithFrame:frame]; 
    NSLog(@"%@", [[View appearance] someColor); // not nil 
    return self; 
} 

Tất nhiên điều này giết chết các tùy chọn để thay đổi diện mạo theo container xem và nói chung là xấu xí. Lựa chọn thứ hai tôi thấy là để thực hiện các tùy chỉnh trong setter:

- (void) setSomeColor: (UIColor*) newColor 
{ 
    someColor = newColor; 
    // do whatever is needed 
} 

Tôi vẫn muốn có một số móc mà được gọi là sau khi các thuộc tính xuất hiện được thiết lập.

+0

xem câu trả lời của tôi; 'móc' là UIView didMoveToSuperview :, tôi tin. – TomSwift

1

Tại sao không chờ đợi cho đến khi

- (void)willMoveToSuperview:(UIView *)newSuperview { 
    [super willMoveToSuperview:newSuperview]; 

    if (newSuperview) { 
     ... code here ... 
    } 
} 

nếu nó đem lại cho bạn gặp rắc rối?

+2

Đó là nỗ lực tiếp theo của tôi, nhưng các giá trị không được đặt tại thời điểm đó. – zoul

0

Tôi đã nghĩ rằng viewDidLoad sẽ là tốt nhất nếu đó là điều một lần. Nếu không, viewWillAppear.

EDIT:

Nếu bạn muốn làm điều đó trong giao diện, chứ không phải đó là điều khiển sau đó tôi sẽ tạo ra một init tùy chỉnh cho quan điểm dọc theo dòng:

-(id) initWithFrame:(CGRect) frame andAppearanceColor:(UIColor)theColor; 

từ đó đi qua các màu vào chế độ xem tại thời điểm tạo.

+0

Đây là các phương pháp điều khiển và tôi muốn xử lý nó nhiều hơn trong chế độ xem.Bên cạnh đó, có thể xảy ra các giá trị chưa được đặt trong các cuộc gọi này. – zoul

+0

Việc chuyển màu trong bộ khởi tạo cũng không phải là một tùy chọn vì có nhiều thuộc tính xuất hiện hơn và bộ khởi tạo được gọi ở một vị trí ngoài bộ điều khiển… erm, * của bộ điều khiển *. Người ta có thể nói rằng toàn bộ quan điểm của API proxy xuất hiện là loại bỏ tất cả các giá trị bằng tay mọi lúc. – zoul

+0

Tôi thấy bạn đến từ đâu. Có lẽ bạn có thể tạo một phương thức để thiết lập các thuộc tính xuất hiện và gọi nó để đáp ứng với một NSNotification (được gửi khi các thuộc tính xuất hiện được chỉ định)? – ader

0

Tôi tin rằng UIAppearance thuộc tính được áp dụng cho chế độ xem khi được thêm vào phân cấp chế độ xem. Vì vậy, có lẽ bạn có thể truy cập các thuộc tính thiết lập trong UIView didMoveToSuperview.

1

Lưu ý: Tôi đang sử dụng Swift 2, vì vậy không chắc chắn về các phiên bản trước của Swift/Objective-C. Nhưng tôi thấy rằng didMoveToSuperview() sẽ không hoạt động. Các thuộc tính có sẵn trong layoutSubviews(), nhưng đó không phải là một nơi tuyệt vời để làm bất cứ điều gì như thế này (vì nó có thể được gọi nhiều hơn một lần). Nơi tốt nhất để truy cập các thuộc tính này trong vòng đời của chế độ xem mà tôi đã tìm thấy là didMoveToWindow().

Các vấn đề liên quan