IOS设计模式之三(适配器模式,观察者模式)
如何使用适配器模式
- @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];
- }
- }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。