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 观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监 ...
随机推荐
- java web页面 base
<base href="<%=basePath%>"> <base src="<%=basePath%>"> 主 ...
- OpenGL程序运行提示glut32.dll丢失问题
转: http://blog.csdn.net/liufeng520/article/details/8064170 今天调试OpenGl的源程序,编译通过,但一运行就提示,计算机丢失 glut32. ...
- sql主键的一点重要理解
sql只会读取数据,不会自动设置主键,所以绑定数据后要设置主键(前台) 不管是int或者uniqueidentifier只要类型对得上就可以用,int自增其实没什么太大优势(但是通常都会用自增来做,从 ...
- 【hdu2815-Mod Tree】高次同余方程-拓展BadyStepGaintStep
http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意:裸题... 关于拓展BSGS的详细解释我写了一篇博文:http://www.cnblogs.com/ ...
- ANDROID STUDIO, GRADLE AND NDK INTEGRATION
Originally posted on:http://ph0b.com/android-studio-gradle-and-ndk-integration/ With the recent chan ...
- MONO常用快捷键
Action Mac OS X Win/Linux 注释代码(//) Cmd + / Ctrl + / 注释代码(/**/) Cmd + Option + / Ctrl + Shift + / 格 ...
- Android核心分析之十七电话系统之rilD
Android电话系统之-rild Rild是Init进程启动的一个本地服务,这个本地服务并没有使用Binder之类的通讯手段,而是采用了socket通讯这种方式.RIL(Radio Interfac ...
- 超级内存NVDIMM
1.序言 基于非易失性内存(NVDIMM)的新一代内存条规格已经研制成功,其中集成了DRAM和非易失性存储芯片,能够在完全断电的时候完整保存内存数据,并支持主内存在持久高速高性能计算上的应用.区别于普 ...
- 图解TCP/IP读书笔记(二)
图解TCP/IP读书笔记(二) 第二章.TCP/IP基础知识 一.TCP/IP出现的背景及其历史 年份 事件 20世纪60年代后半叶 应DoD(美国国防部)要求,美国开始进行通信技术相关的研发 196 ...
- Linux内核通杀提权漏洞CVE-2016-5195 - 内核升级方法
如题,对于脏牛(Dirty COW)漏洞的修复方式已经在上篇文章中有介绍过如何验证,这里对如何升级内核给出修复建议. (注意:为避免不必要的生产风险的发生,请审核自己的实际环境而决定采用什么方法进行升 ...