2010-09-24 16 views
15

Tôi không thể tìm thấy câu trả lời phù hợp để giải thích cho tôi sự khác biệt giữa 2 chức năng này. khi nào mọi người được gọi, và người kia khác nhau như thế nào? Ví dụ:drawrect Vs layoutsubviews - NSView - Cocoa touch

chẳng hạn, tôi không thể bố cục chế độ xem của mình bên trong drawrect?

Cảm ơn

Trả lời

56

-layoutSubviews được gọi từ -layoutIfNeeded nếu "bố trí cần thiết" cờ đã được thiết lập (sử dụng -setNeedsLayout, hoặc tự động khi chế độ xem thay đổi giới hạn). Sử dụng nó để định vị chế độ xem của bạn [EDIT: Sử dụng nó để định vị subviews].

-drawRect: được gọi từ -displayIfNeeded nếu cờ "hiển thị cần thiết" được đặt (sử dụng -setNeedsDisplay hoặc tự động nếu bạn đặt view.contentMode = UIViewContentModeRedraw).

Cả hai -layoutIfNeeded-displayIfNeeded được gọi tự động bởi UIKit/CoreAnimation trước khi mọi thứ được vẽ ra màn hình; bạn hiếm khi cần gọi trực tiếp cho họ.

Bạn có thể xác định vị trí của bạn trong subviews -drawRect: (thậm chí bạn có thể thêm subviews!), Nhưng điều này là không khôn ngoan:

  • Theo mặc định, -setNeedsDisplay không được gọi tự động vào một sự thay đổi giới hạn.
  • Triển khai -drawRect: giảm hiệu suất (UIKit/CoreAnimation phải tạo ngữ cảnh đồ họa được bitmap hỗ trợ cho bạn); chỉ làm như vậy nếu bạn cần thực hiện bản vẽ tùy chỉnh.
  • Bạn cần vẽ lại chế độ xem trong -drawRect:. Vẽ là tốn kém. Quan điểm di chuyển xung quanh là rẻ.
  • UIKit/CoreAnimation có thể có một đường viền bố trí theo sau là một hình vẽ. CoreAnimation có thể sử dụng thông tin bố cục để quyết định xem những gì cần vẽ (ví dụ: nó có thể bỏ qua các chế độ xem bị che khuất bởi các chế độ xem mờ, lượt xem màn hình hoặc các bản xem trước bên ngoài giới hạn của clipToBounds = YES view; xem lớn). Nếu bạn di chuyển các khung nhìn trong khi vẽ, CoreAnimation có thể không vẽ chúng một cách chính xác.

EDIT: Và một số chi tiết hơn khi tôi tỉnh táo:

sự khác biệt giữa "hiển thị" và "vẽ" là gì? Việc hiển thị được thực hiện bởi -[CALayer display]; triển khai mặc định là (khoảng)

  • Nếu đại biểu của lớp phản hồi -displayLayer:, hãy gọi [self.delegate displayLayer:self].-displayLayer: là nghĩa vụ phải thiết lập layer.content đến (ví dụ) một CGImage,
  • Ngược lại, nếu đại biểu của lớp đáp ứng -drawLayer:inContext:, thiết lập một bối cảnh bitmap hậu thuẫn, gọi [self.delegate drawLayer:self inContext:context], và lưu kết quả để layer.content (đầu ra thực sự là một CABackingStore , có lẽ là một API riêng)
  • Nếu không, không thay đổi layer.content.

Quan điểm là đại biểu của lớp, vì vậy bạn có thể thực hiện -[MyView displayLayer:] thay vào đó, và làm công cụ thú vị như

  • self.layer.contents = (id)([UIImage imageNamed:@"foo"].CGImage) (đó là khoảng những gì UIImageView làm)
  • Một không-op, để ngăn chặn bất kỳ "bản vẽ" nào. Điều này có thể hữu ích nếu bạn đã phân lớp, ví dụ: UIToolbar và muốn cho nó một nền trong suốt. (Điều này cũng ngăn cản việc tạo CGContext/CABackingStore.)
  • Di chuyển các bài đánh giá xung quanh mà không có hình phạt về hiệu suất (nhưng vẫn không phải là một ý tưởng hay vì những lý do trên).
+0

Câu trả lời hay. cảm ơn! – Idan

-2

Có lẽ tôi không có tất cả các câu trả lời, nhưng tôi có thể nói với bạn rằng: - layoutSubviews được gọi khi khung nhìn được thay đổi - drawRect được gọi khi setNeedDisplay được gọi

Hầu hết thời gian bạn sẽ không sử dụng layoutSubviews.

Có thể có trường hợp những người khác, nhưng nó có thể cung cấp cho bạn một mảnh đầu tiên của câu trả lời ^^

Chúc may mắn

+0

Vui lòng cung cấp thêm chi tiết xung quanh xác nhận của bạn rằng "hầu hết thời gian bạn sẽ không sử dụng layoutSubviews". –