trandy 2013-09-15
如何使用适配器模式
@protocolHorizontalScrollerDelegate <NSObject> // methods declaration goes in here @end
@required // ask the delegate how many views he wants to present inside the horizontal scroller - (NSInteger)numberOfViewsForHorizontalScroller:(HorizontalScroller*)scroller; // ask the delegate to return the view that should appear at <index> - (UIView*)horizontalScroller:(HorizontalScroller*)scroller viewAtIndex:(int)index; // inform the delegate what the view at <index> has been clicked - (void)horizontalScroller:(HorizontalScroller*)scroller clickedViewAtIndex:(int)index; @optional // ask the delegate for the index of the initial view to display. this method is optional // and defaults to 0 if it's not implemented by the delegate - (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller*)scroller;
这里你既有必需的方法也有可选方法。必需的方法要求委托必须实现它,因为它提供一些必需的数据。在这里,必需的是视图的数量,指定索引位置的视图,以及用户点击视图后的行为,可选的方法是初始化视图;如果它没有实现,那么HorizontalScroller将缺省用第一个索引的视图。
@property (weak) id<HorizontalScrollerDelegate> delegate; - (void)reload;
#import "HorizontalScroller.h" // 1 #define VIEW_PADDING 10 #define VIEW_DIMENSIONS 100 #define VIEWS_OFFSET 100 // 2 @interfaceHorizontalScroller () <UIScrollViewDelegate> @end // 3 @implementationHorizontalScroller { UIScrollView *scroller; } @end
- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; scroller.delegate = self; [self addSubview:scroller]; UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollerTapped:)]; [scroller addGestureRecognizer:tapRecognizer]; } return self; }
- (void)scrollerTapped:(UITapGestureRecognizer*)gesture { CGPoint location = [gesture locationInView:gesture.view]; // we can't use an enumerator here, because we don't want to enumerate over ALL of the UIScrollView subviews. // we want to enumerate only the subviews that we added for (int index=0; index<[self.delegate numberOfViewsForHorizontalScroller:self]; index++) { UIView *view = scroller.subviews[index]; if (CGRectContainsPoint(view.frame, location)) { [self.delegate horizontalScroller:self clickedViewAtIndex:index]; [scroller setContentOffset:CGPointMake(view.frame.origin.x - self.frame.size.width/2 + view.frame.size.width/2, 0) animated:YES]; break; } } }
- (void)reload { // 1 - nothing to load if there's no delegate if (self.delegate == nil) return; // 2 - remove all subviews [scroller.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [obj removeFromSuperview]; }]; // 3 - xValue is the starting point of the views inside the scroller CGFloat xValue = VIEWS_OFFSET; for (int i=0; i<[self.delegate numberOfViewsForHorizontalScroller:self]; i++) { // 4 - add a view at the right position xValue += VIEW_PADDING; UIView *view = [self.delegate horizontalScroller:self viewAtIndex:i]; view.frame = CGRectMake(xValue, VIEW_PADDING, VIEW_DIMENSIONS, VIEW_DIMENSIONS); [scroller addSubview:view]; xValue += VIEW_DIMENSIONS+VIEW_PADDING; } // 5 [scroller setContentSize:CGSizeMake(xValue+VIEWS_OFFSET, self.frame.size.height)]; // 6 - if an initial view is defined, center the scroller on it if ([self.delegate respondsToSelector:@selector(initialViewIndexForHorizontalScroller:)]) { int initialView = [self.delegate initialViewIndexForHorizontalScroller:self]; [scroller setContentOffset:CGPointMake(initialView*(VIEW_DIMENSIONS+(2*VIEW_PADDING)), 0) animated:YES]; } }
- (void)didMoveToSuperview { [self reload]; }
- (void)centerCurrentView { int xFinal = scroller.contentOffset.x + (VIEWS_OFFSET/2) + VIEW_PADDING; int viewIndex = xFinal / (VIEW_DIMENSIONS+(2*VIEW_PADDING)); xFinal = viewIndex * (VIEW_DIMENSIONS+(2*VIEW_PADDING)); [scroller setContentOffset:CGPointMake(xFinal,0) animated:YES]; [self.delegate horizontalScroller:self clickedViewAtIndex:viewIndex]; }
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self centerCurrentView]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self centerCurrentView]; }
#import "HorizontalScroller.h" #import "AlbumView.h"
@interfaceViewController ()<UITableViewDataSource, UITableViewDelegate, HorizontalScrollerDelegate>
HorizontalScroller *scroller;
#pragma mark - HorizontalScrollerDelegate methods - (void)horizontalScroller:(HorizontalScroller *)scroller clickedViewAtIndex:(int)index { currentAlbumIndex = index; [self showDataForAlbumAtIndex:index]; }
- (NSInteger)numberOfViewsForHorizontalScroller:(HorizontalScroller*)scroller { return allAlbums.count; }
- (UIView*)horizontalScroller:(HorizontalScroller*)scroller viewAtIndex:(int)index { Album *album = allAlbums[index]; return [[AlbumView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) albumCover:album.coverUrl]; }
这里你创建了一个新的AlbumView,并且将它传递给HorizontalScroller。
- (void)reloadScroller { allAlbums = [[LibraryAPI sharedInstance] getAlbums]; if (currentAlbumIndex < 0) currentAlbumIndex = 0; else if (currentAlbumIndex >= allAlbums.count) currentAlbumIndex = allAlbums.count-1; [scroller reload]; [self showDataForAlbumAtIndex:currentAlbumIndex]; }
scroller = [[HorizontalScroller alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 120)]; scroller.backgroundColor = [UIColor colorWithRed:0.24f green:0.35f blue:0.49f alpha:1]; scroller.delegate = self; [self.view addSubview:scroller]; [self reloadScroller];
[[NSNotificationCenterdefaultCenter] postNotificationName:@"BLDownloadImageNotification" object:self userInfo:@{@"imageView":coverImage, @"coverUrl":albumCover}];
[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(downloadImage:) name:@"BLDownloadImageNotification" object:nil];
- (void)dealloc { [[NSNotificationCenterdefaultCenter] removeObserver:self]; }
- (void)saveImage:(UIImage*)image filename:(NSString*)filename; - (UIImage*)getImage:(NSString*)filename;
- (void)saveImage:(UIImage*)image filename:(NSString*)filename { filename = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", filename]; NSData *data = UIImagePNGRepresentation(image); [data writeToFile:filename atomically:YES]; } - (UIImage*)getImage:(NSString*)filename { filename = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", filename]; NSData *data = [NSDatadataWithContentsOfFile:filename]; return [UIImage imageWithData:data]; }
- (void)downloadImage:(NSNotification*)notification { // 1 UIImageView *imageView = notification.userInfo[@"imageView"]; NSString *coverUrl = notification.userInfo[@"coverUrl"]; // 2 imageView.image = [persistencyManager getImage:[coverUrl lastPathComponent]]; if (imageView.image == nil) { // 3 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ UIImage *image = [httpClient downloadImage:coverUrl]; // 4 dispatch_sync(dispatch_get_main_queue(), ^{ imageView.image = image; [persistencyManager saveImage:image filename:[coverUrl lastPathComponent]]; }); }); } }
下面是以上代码分段描述:
[coverImage addObserver:self forKeyPath:@"image" options:0 context:nil];
- (void)dealloc { [coverImage removeObserver:self forKeyPath:@"image"]; }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"image"]) { [indicator stopAnimating]; } }