이전에 문제가 되었던 UIScrollView에서의 page detecting을 해결하기 위해 구글링 도중에 page의 lazy loading을 고민하는 사람이 많다는 것을 알게 되었다. 이는 지금 나같이 너댓장의 이미지를 로딩하는 데에는 큰 문제가 되지 않지만 수십 수백장의 이미지 혹은 다른 그 어떤 것을 로딩하기 에는 좀 문제가 된다.
원래대로라면 하나의 scrollview에 수십 수백장의 imageview를 addSubview를 이용해 추가하는 것인데 당연히 퍼포먼스나 메모리 관리 측면에서 문제가 안될리 없다. 그래서 많은 image gallery 어플이 하는 방식인 현재 보이는 view와 그 이전/이후의 view만을 로딩하는 lazy loading 방식에 대해 찾아 보다가 stack overflow에서 아래의 sample code를 발견했다.
먼저 interface 부분.
01.@interface UntitledViewController : UIViewController<UIScrollViewDelegate> {
02.@private
03.UIScrollView *_scrollView;
04. 
05.NSArray *_objects;
06. 
07.UILabel *_detailLabel1;
08.UILabel *_detailLabel2;
09.UILabel *_detailLabel3;
10.}
11. 
12.- (void)replaceHiddenLabels;
13.- (void)displayLabelsAroundIndex:(NSInteger)index;
14. 
15.@end

그리고 실제 구현 부분.
001.@implementation UntitledViewController
002. 
003.- (void)dealloc
004.{
005.[_objects release];
006.[_scrollView release];
007.[_detailLabel1 release];
008.[_detailLabel2 release];
009.[_detailLabel3 release];
010.[super dealloc];
011.}
012. 
013.- (void)viewDidLoad
014.{
015.[super viewDidLoad];
016. 
017._objects = [[NSArray alloc] initWithObjects:@"first", @"second", @"third",
018.@"fourth", @"fifth", @"sixth", @"seventh", @"eight", @"ninth", @"tenth", nil];
019. 
020._scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
021._scrollView.contentSize = CGSizeMake(320.0 * [_objects count], 460.0);
022._scrollView.showsVerticalScrollIndicator = NO;
023._scrollView.showsHorizontalScrollIndicator = YES;
024._scrollView.alwaysBounceHorizontal = YES;
025._scrollView.alwaysBounceVertical = NO;
026._scrollView.pagingEnabled = YES;
027._scrollView.delegate = self;
028. 
029._detailLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
030._detailLabel1.textAlignment = UITextAlignmentCenter;
031._detailLabel1.font = [UIFont boldSystemFontOfSize:30.0];
032._detailLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(320.0, 0.0, 320.0, 460.0)];
033._detailLabel2.textAlignment = UITextAlignmentCenter;
034._detailLabel2.font = [UIFont boldSystemFontOfSize:30.0];
035._detailLabel3 = [[UILabel alloc] initWithFrame:CGRectMake(640.0, 0.0, 320.0, 460.0)];
036._detailLabel3.textAlignment = UITextAlignmentCenter;
037._detailLabel3.font = [UIFont boldSystemFontOfSize:30.0];
038. 
039.// We are going to show all the contents of the _objects array
040.// using only these three UILabel instances, making them jump
041.// right and left, replacing them as required:
042.[_scrollView addSubview:_detailLabel1];
043.[_scrollView addSubview:_detailLabel2];
044.[_scrollView addSubview:_detailLabel3];
045. 
046.[self.view addSubview:_scrollView];
047.}
048. 
049.- (void)viewDidAppear:(BOOL)animated
050.{
051.[super viewDidAppear:animated];
052.[_scrollView flashScrollIndicators];
053.}
054. 
055.- (void)viewWillAppear:(BOOL)animated
056.{
057.[super viewWillAppear:animated];
058.[self displayLabelsAroundIndex:0];
059.}
060. 
061.- (void)didReceiveMemoryWarning
062.{
063.// Here you could release the data source, but make sure
064.// you rebuild it in a lazy-loading way as soon as you need it again...
065.[super didReceiveMemoryWarning];
066.}
067. 
068.#pragma mark -
069.#pragma mark UIScrollViewDelegate methods
070. 
071.- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
072.{
073.// Do some initialization here, before the scroll view starts moving!
074.}
075. 
076.- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
077.{
078.[self replaceHiddenLabels];
079.}
080. 
081.- (void)displayLabelsAroundIndex:(NSInteger)index
082.{
083.NSInteger count = [_objects count];
084.if (index >= 0 && index < count)
085.{
086.NSString *text = [_objects objectAtIndex:index];
087._detailLabel1.frame = CGRectMake(320.0 * index, 0.0, 320.0, 460.0);
088._detailLabel1.text = text;
089.[_scrollView scrollRectToVisible:CGRectMake(320.0 * index, 0.0, 320.0, 460.0) animated:NO];
090. 
091.if (index < (count - 1))
092.{
093.text = [_objects objectAtIndex:(index + 1)];
094._detailLabel2.frame = CGRectMake(320.0 * (index + 1), 0.0, 320.0, 460.0);
095._detailLabel2.text = text;
096.}
097. 
098.if (index > 0)
099.{
100.text = [_objects objectAtIndex:(index - 1)];
101._detailLabel3.frame = CGRectMake(320.0 * (index - 1), 0.0, 320.0, 460.0);
102._detailLabel3.text = text;
103.}
104.}
105.}
106. 
107.- (void)replaceHiddenLabels
108.{
109.static const double pageWidth = 320.0;
110.NSInteger currentIndex = ((_scrollView.contentOffset.x - pageWidth) / pageWidth) + 1;
111. 
112.UILabel *currentLabel = nil;
113.UILabel *previousLabel = nil;
114.UILabel *nextLabel = nil;
115. 
116.if (CGRectContainsPoint(_detailLabel1.frame, _scrollView.contentOffset))
117.{
118.currentLabel = _detailLabel1;
119.previousLabel = _detailLabel2;
120.nextLabel = _detailLabel3;
121.}
122.else if (CGRectContainsPoint(_detailLabel2.frame, _scrollView.contentOffset))
123.{
124.currentLabel = _detailLabel2;
125.previousLabel = _detailLabel1;
126.nextLabel = _detailLabel3;
127.}
128.else
129.{
130.currentLabel = _detailLabel3;
131.previousLabel = _detailLabel1;
132.nextLabel = _detailLabel2;
133.}
134. 
135.currentLabel.frame = CGRectMake(320.0 * currentIndex, 0.0, 320.0, 460.0);
136.currentLabel.text = [_objects objectAtIndex:currentIndex];
137. 
138.// Now move the other ones around
139.// and set them ready for the next scroll
140.if (currentIndex < [_objects count] - 1)
141.{
142.nextLabel.frame = CGRectMake(320.0 * (currentIndex + 1), 0.0, 320.0, 460.0);
143.nextLabel.text = [_objects objectAtIndex:(currentIndex + 1)];
144.}
145. 
146.if (currentIndex >= 1)
147.{
148.previousLabel.frame = CGRectMake(320.0 * (currentIndex - 1), 0.0, 320.0, 460.0);
149.previousLabel.text = [_objects objectAtIndex:(currentIndex - 1)];
150.}
151.}
152. 
153.@end

언더바를 많이 쓰고 대괄호 쓰는 방식이 C 프로그래밍 스타일이라 좀 별로지만 그대로 옮겨왔다. 수정하기 귀찮... 하여간 이 코드를 그대로 갖다 복사해도 동작한다. scrollview에 각각 label을 붙이는 subview를 만들어서 한번에 세개의 view를 로딩하고 스크롤할 때마다 다시 그 다음 것들을 loading하는 방식이다.

그리고 추가로 저 위의 scrollViewDidEndDecelerating 메소드 안에 아래의 코드를 갖다 붙이면 현재 보이는 page를 알아낼 수 있다.

1.int page = floor((_scrollView.contentOffset.x - PAGE_WIDTH / 2) / PAGE_WIDTH) + 1;

http://yangsae.tistory.com/38
by Anna 안나 2012. 1. 16. 14:39