5

UI/NSTableView에 대해 재사용 가능한 셀을 구현하는 방법을 찾고 있지만 NSScrollView에 대해 설명합니다. 기본적으로 WWDC 2011 비디오 "Session 104 - Advanced Scroll View Techniques"와 같지만 Mac의 경우와 같습니다.NSScrollView 무한/무한 스크롤 | 서브 뷰 재사용

나는 이것을 실현하는 데 몇 가지 문제점이 있습니다. 첫 번째 : NSScrollView에는 -layoutSubviews이 없습니다. 나는 다른 contentOffset을 설정하는 대신 -adjustScroll를 사용하지만 실패했습니다 : 나는 시도

- (NSRect)adjustScroll:(NSRect)proposedVisibleRect { 
    if (proposedVisibleRect.origin.x > 600) { 
     // non of them work properly 
     // proposedVisibleRect.origin.x = 0; 
     // [self setBoundsOrigin:NSZeroPoint]; 
     // [self setFrameOrigin:NSZeroPoint]; 
     // [[parentScrollView contentView] scrollPoint:NSZeroPoint]; 
     // [[parentScrollView contentView] setBoundsOrigin:NSZeroPoint]; 
    } 
    return proposedVisibleRect; 
} 

다음 것은 아이폰 OS에 비해 실제로 작동하는 픽셀의 수백만 (의 width와 정말 엄청난 내용보기를 설정하는 것이 었습니다!)하지만 이제 문제는 재사용 풀을 설치하는 방법입니다.
새 위치로 스크롤하는 동안 하위보기를 이동하거나 모든 하위보기를 제거하고 다시 삽입하는 것이 더 좋습니까? 어떻게하고 어디에서해야합니까?

답변

2

내가 알 수있는 것처럼, -adjustScroll:은 보편적으로 호출되지 않기 때문에 스크롤 이벤트를 활용하려는 위치가 아닙니다. 나는 -reflectScrolledClipView:이 아마 더 나은 접속 지점이라고 생각한다.

보기 재사용 스크롤보기를 수행하는 한 방향의 높은 지점에 도달해야하는 다음 예제를 정리했습니다. 간단히하기 위해 스크롤 동작을 무한히 "가짜"로 만들려고 시도하지 않고 scrollView의 documentView 크기를 "거대한"것으로 설정했습니다. 분명히 현실을 구성하는 타일 뷰를 그리는 것은 당신에게 달려 있습니다. (이 예에서는 그냥 모든 것이 작동 것을 자신을 설득하기 위해 파란색 1 {빨간색으로 자신을 채운다 더미보기를 만들었습니다.) 그것은 다음과 같이 나온이 꽤 잘 내가 말할 수있는 최선으로 일

// For the header file 
@interface SOReuseScrollView : NSScrollView 
@end 

// For the implementation file 
@interface SOReuseScrollView() // Private 

- (void)p_updateTiles; 
@property (nonatomic, readonly, retain) NSMutableArray* p_reusableViews; 

@end 

// Just a small diagnosting view to convince myself that this works. 
@interface SODiagnosticView : NSView 
@end 

@implementation SOReuseScrollView 

@synthesize p_reusableViews = mReusableViews; 

- (void)dealloc 
{ 
    [mReusableViews release]; 
    [super dealloc]; 
} 

- (NSMutableArray*)p_reusableViews 
{ 
    if (nil == mReusableViews) 
    { 
     mReusableViews = [[NSMutableArray alloc] init]; 
    } 
    return mReusableViews; 
} 

- (void)reflectScrolledClipView:(NSClipView *)cView 
{ 
    [super reflectScrolledClipView: cView]; 
    [self p_updateTiles]; 
} 

- (void)p_updateTiles 
{ 
    // The size of a tile... 
    static const NSSize gGranuleSize = {250.0, 250.0}; 

    NSMutableArray* reusableViews = self.p_reusableViews; 
    NSRect documentVisibleRect = self.documentVisibleRect; 

    // Determine the needed tiles for coverage 
    const CGFloat xMin = floor(NSMinX(documentVisibleRect)/gGranuleSize.width) * gGranuleSize.width; 
    const CGFloat xMax = xMin + (ceil((NSMaxX(documentVisibleRect) - xMin)/gGranuleSize.width) * gGranuleSize.width); 
    const CGFloat yMin = floor(NSMinY(documentVisibleRect)/gGranuleSize.height) * gGranuleSize.height; 
    const CGFloat yMax = ceil((NSMaxY(documentVisibleRect) - yMin)/gGranuleSize.height) * gGranuleSize.height; 

    // Figure out the tile frames we would need to get full coverage 
    NSMutableSet* neededTileFrames = [NSMutableSet set]; 
    for (CGFloat x = xMin; x < xMax; x += gGranuleSize.width) 
    { 
     for (CGFloat y = yMin; y < yMax; y += gGranuleSize.height) 
     { 
      NSRect rect = NSMakeRect(x, y, gGranuleSize.width, gGranuleSize.height); 
      [neededTileFrames addObject: [NSValue valueWithRect: rect]]; 
     } 
    } 

    // See if we already have subviews that cover these needed frames. 
    for (NSView* subview in [[[self.documentView subviews] copy] autorelease]) 
    { 
     NSValue* frameRectVal = [NSValue valueWithRect: subview.frame]; 

     // If we don't need this one any more... 
     if (![neededTileFrames containsObject: frameRectVal]) 
     { 
      // Then recycle it... 
      [reusableViews addObject: subview]; 
      [subview removeFromSuperview]; 
     } 
     else 
     { 
      // Take this frame rect off the To-do list. 
      [neededTileFrames removeObject: frameRectVal]; 
     } 
    } 

    // Add needed tiles from the to-do list 
    for (NSValue* neededFrame in neededTileFrames) 
    { 
     NSView* view = [[[reusableViews lastObject] retain] autorelease]; 
     [reusableViews removeLastObject]; 

     if (nil == view) 
     { 
      // Create one if we didnt find a reusable one. 
      view = [[[SODiagnosticView alloc] initWithFrame: NSZeroRect] autorelease]; 
      NSLog(@"Created a view."); 
     } 
     else 
     { 
      NSLog(@"Reused a view."); 
     } 

     // Place it and install it. 
     view.frame = [neededFrame rectValue]; 
     [view setNeedsDisplay: YES];   
     [self.documentView addSubview: view]; 
    } 
} 

@end 

@implementation SODiagnosticView 

- (void)drawRect:(NSRect)dirtyRect 
{ 
    // Draw a red tile with a blue border. 
    [[NSColor blueColor] set]; 
    NSRectFill(self.bounds); 

    [[NSColor redColor] setFill]; 
    NSRectFill(NSInsetRect(self.bounds, 2,2));  
} 

@end 

. 다시 말하면 재사용 된 견해에서 의미있는 것을 그리는 것은 실제 작업이 여기에있는 곳입니다.

희망이 있습니다.

+0

부적처럼 작동합니다. 감사합니다. 자동 크기 조정 및 다른 사용자 정의를 지원하기 위해 다음 날을 더 깊이 파고들 것입니다 =) –