2012-05-23 23 views
7

NSViews lớp lưu trữ (do đó NSViews mà bạn cung cấp một cá thể CALayer và đặt nó với setLayer:) rõ ràng có thể chứa các bản xem trước. Tại sao rõ ràng? Bởi vì trong Apple của riêng Cocoa Slides sample code project, bạn có thể kiểm tra một hộp kiểm mà chuyển mạch AssetCollectionView khỏi bị lớp hậu thuẫn để trở thành lớp lưu trữ:NSViews lưu trữ lớp có được phép xem phụ không?

- (void)setUsesQuartzCompositionBackground:(BOOL)flag { 
    if (usesQuartzCompositionBackground != flag) { 
     usesQuartzCompositionBackground = flag; 

     /* We can display a Quartz Composition in a layer-backed view tree by 
      substituting our own QCCompositionLayer in place of the default automanaged 
      layer that AppKit would otherwise create for the view. Eventually, hosting of 
      QCViews in a layer-backed view subtree may be made more automatic, rendering 
      this unnecessary. To minimize visual glitches during the transition, 
      temporarily suspend window updates during the switch, and toggle layer-backed 
      view rendering temporarily off and back on again while we prepare and set the 
      layer. 
     */ 
     [[self window] disableScreenUpdatesUntilFlush]; 
     [self setWantsLayer:NO]; 
     if (usesQuartzCompositionBackground) { 
      QCCompositionLayer *qcLayer = [QCCompositionLayer compositionLayerWithFile:[[NSBundle mainBundle] pathForResource:@"Cells" ofType:@"qtz"]]; 
      [self setLayer:qcLayer]; 
     } else { 
      [self setLayer:nil]; // Discard the QCCompositionLayer we were using, and let AppKit automatically create self's backing layer instead. 
     } 
     [self setWantsLayer:YES]; 
    } 
} 

Trong cùng lớp AssetCollectionView, subviews được thêm vào cho mỗi hình ảnh đó sẽ được hiển thị:

- (AssetCollectionViewNode *)insertNodeForAssetAtIndex:(NSUInteger)index { 
    Asset *asset = [[[self assetCollection] assets] objectAtIndex:index]; 
    AssetCollectionViewNode *node = [[AssetCollectionViewNode alloc] init]; 
    [node setAsset:asset]; 
    [[self animator] addSubview:[node rootView]]; 
    [nodes addObject:node]; 

    return [node autorelease]; 
} 

Khi tôi tạo và chạy ứng dụng và chơi cùng với nó, mọi thứ có vẻ ổn.

Tuy nhiên, trong Apple's NSView Class Reference for the setWantsLayer: method nó đọc:

Khi sử dụng một cái nhìn lớp lưu trữ bạn không nên dựa vào quan điểm cho vẽ, cũng không phải bạn nên thêm subviews đến xem lớp-hosting.

Điều gì là đúng? Mã mẫu có đúng không và nó chỉ là trùng hợp ngẫu nhiên khi nó hoạt động? Hoặc là tài liệu sai (mà tôi nghi ngờ)? Hoặc là nó OK vì các subviews được thêm thông qua proxy animator?

Trả lời

19

Khi AppKit là "lưu trữ lớp", chúng tôi giả sử bạn có thể (hoặc có thể không) có toàn bộ các lớp mà AppKit không biết.

Nếu bạn thêm chế độ xem con vào chế độ xem được lưu trữ trên lớp thì có thể nó không xuất hiện theo đúng thứ tự anh chị em mà bạn muốn. Thêm vào đó, đôi khi chúng tôi thêm và xóa chúng, do đó, nó có thể thay đổi tùy thuộc vào thời điểm bạn gọi setLayer :, setWantsLayer: hoặc khi chế độ xem được thêm hoặc xóa khỏi superview. Trên Lion (và trước đó) chúng ta loại bỏ các lớp mà chúng ta "sở hữu" (tức là: lớp sao lưu) khi xem được loại bỏ khỏi cửa sổ (hoặc superview).

Bạn có thể thêm các bản xem trước ... thứ tự con em họ trong mảng lớp con có thể không xác định được nếu bạn có các lớp anh chị em không phải là NSViews.

+0

Cảm ơn bạn rất rất nhiều! –

1

Tôi không biết câu trả lời "đúng" là gì. Nhưng tôi nghĩ rằng ví dụ CocoaSlides hoạt động trong ranh giới của những gì các tài liệu nói rằng bạn "không nên" làm. Trong ví dụ này, hãy xem phương thức insertNodeForAssetAtIndex: được gọi là gì và bạn sẽ thấy rằng phương thức này chỉ xảy ra khi chế độ xem đang được điền, trước nó từng được gán một lớp hoặc có setWantsLayer: được gọi trên đó.

Tài liệu không cho biết chế độ xem được lưu trữ trên lớp không thể chứa bất kỳ bản xem phụ nào, họ chỉ nói rằng bạn không thể thêm và các bản xem trước vào một. Tại thời điểm khi các bản xem trước đó được thêm vào, chế độ xem chính chưa trở thành chế độ xem lớp lưu trữ. Sau khi nó được chuyển thành chế độ xem lớp lưu trữ bằng cách tạo lớp được tạo theo cách thủ công được gán cho nó, không có thêm bản xem trước nào được thêm vào.

Vì vậy, thực sự không có mâu thuẫn giữa các tài liệu và ví dụ cụ thể này. Điều đó đang được nói, có thể thú vị khi khám phá thêm điều này, có thể bằng cách bật lớp nền QC ngay từ đầu, ví dụ: bằng cách dán [self setUsesQuartzCompositionBackground:YES]; ngay bên trong initWithFrame:.

SPOLIER ALERT: Dường như hoạt động tốt. Việc tạo ra màn hình hiển thị chậm hơn một chút (không đáng ngạc nhiên với tất cả các hoạt hình QC đang diễn ra), nhưng ngoài ra nó là thuyền buồm trơn tru.

+0

Cảm ơn, Jack! Thú vị quan sát về "thêm" vs "đã có" subviews. Có thể các tài liệu đã lỗi thời, vì chúng cũng về câu hỏi này: http://stackoverflow.com/questions/10720062/are-layer-backed-nsview-siblings-allowed-to-overlap/10720422#10720422 –

0

Một nhận xét về mã này từ Apple: nó bị vỡ.

Khi bạn lần đầu tiên khởi động ứng dụng, hãy lưu ý nền gradient đẹp. Bật QC rồi tắt.

poof, không có nền gradient nữa.

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