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];
- }
- }

IOS设计模式之三(适配器模式,观察者模式)的更多相关文章
- IOS设计模式之三:MVC模式
IOS设计模式之三:MVC模式 模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团 ...
- iOS设计模式之适配器模式
一,适配器的定义 定义 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 需求场景 需要使用以前开发的“一些现存的对象”,但是新环境中要求 ...
- java23种设计模式之三: 适配器模式
一.适配器模式 就是个通过一个中间件转化,可以将不匹配的两件事整合到一起,把不匹配变的匹配. 二.适配器分类 1.类适配器 2.对象适配器 三. 适配器的3种组成 1.类适配器组成 1.2个接口 ...
- iOS 设计模式
很赞的总结 iOS Design Patterns 中文版 IOS设计模式之一(MVC模式,单例模式) IOS设计模式之二(门面模式,装饰器模式) IOS设计模式之三(适配器模式,观察者模式) IOS ...
- 大型Java进阶专题(八)设计模式之适配器模式、装饰者模式和观察者模式
前言 今天开始我们专题的第八课了.本章节将介绍:三个设计模式,适配器模式.装饰者模式和观察者模式.通过学习适配器模式,可以优雅的解决代码功能的兼容问题.另外有重构需求的人群一定需要掌握装饰者模式. ...
- IOS设计模式-观察者模式
前言:23种软件设计模式中的观察者模式,也是在软件开发中,挺常用的一种设计模式.而在苹果开发中,苹果Cocoa框架已经给我们实现了这个设 计模式,那就是通知和KVO(Key-Value Observi ...
- iOS书摘之Objective-C编程之道 iOS设计模式解析
来自<Objective-C编程之道iOS设计模式解析>一书的摘要总结 一.Prototype 原型模式 定义:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象.(<设 ...
- iOS设计模式 - (1)概述
近期可自由安排的时间比較多, iOS应用方面, 没什么好点子, 就先放下, 不写了.花点时间学学设计模式. 之后将会写一系列博文, 记录设计模式学习过程. 当然, 由于我自己是搞iOS的, 所以之后设 ...
- Java设计模式之《观察者模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6513651.html 观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监 ...
随机推荐
- tomcat 跨域
http://www.360doc.com/content/14/0920/14/7909375_411017244.shtml http://www.tuicool.com/articles/Znq ...
- 全注解的SSH框架
基于struts2.23 + spring2.5.6 + hibernate3.6.4 + hibernate-generic-dao1.0(除了spring,我整合的都是最新的GA包,hiberna ...
- 关于null == 0?返回false的问题
1.首先我们先看各种情况的结果: null > 0? //=>false null < 0? //=>false null >= 0? //=>true null ...
- [RM HA4] RM状态存储与还原原理详解
RM状态存储与还原机制详解 转载请注明原始链接http://www.cnblogs.com/shenh062326/p/3562199.html. 摘要 本文基于Apache Hadoop社区最新re ...
- 关于playmaker play animation出现警告 The AnimationClip 'xxx' used by the Animati ...
转载自网络: 出现这个提示: The AnimationClip 'xxx' used by the Animation component 'xxx' must be marked as Legac ...
- 博弈的SG函数理解及模板
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数.例如mex{0,1,2,4}=3.mex{2,3,5}=0.mex{}=0. 对 ...
- phpeclipse常用快捷键
phpeclipse常用快捷键
- Java:Collection集合类
特点:只能用于存储对象,集合长度时可变的,集合可以存储不同类型的对象. 数组和集合类同时容器,不同的是: 1.数组虽然也可以存储对象,但是长度是固定的:集合长度时可变的. 2.数组中可以存储基本数据类 ...
- iOS:模态弹出窗控制器UIPopoverPresentationController
模态弹出窗控制器:UIPopoverPresentationController 实质:就是将内容控制器包装成PopoverPresentationController的形式,然后再模态出来,必须指定 ...
- Bootstrap plugin编写
滚动demo: <!doctype html> <html lang="en"> <head> <meta charset="U ...