iOS知识梳理3:设计模式


iOS有哪些常见的设计模式?
单例模式/委托模式/观察者模式/MVC模式


单例模式

单例保证了应用程序的生命周期内仅有一个该类的实例对象,而且易于外界访问.

在ios sdk中,UIApplication, NSBundle, NSNotificationCenter, NSFileManager, NSUserDefault, NSURLCache等都是单例.

在实际开发中,单例一般会分为ARC和非ARC两种不同的写法,这些代码可以通过判断统一整理到PCH文件中,这样每次使用单例时就不用多次输入重复的代码.

单例的代码简单样例:

//.h
@interface Singleton:NSObject
+(Singleton *)sharedManager;
@property(nonatomic,strong)NSString *singletonData;
@end
//.m
#import "Singleton.h"
@implementation Singleton

static Singleton *sharedManager = nil;

+(Singleton *)sharedManager
{
     static dispatch_once_t once;
    dispatch_once(&once,^{
            sharedManager = [[self alloc] init];
     });
    return sharedManager;
}
@end

委托模式

委托Delegate是协议的一种,通过@protocol方式实现. 顾名思义, 就是委托他人帮自己去做什么事. 也就是当自己不方便做什么事情的时候, 就可以建立一个委托, 这样就可以委托他人帮忙去做.

比如常见的UITableView, iOS SDK在写这个类的时候,肯定不知道开发者想要在点击某一行之后都要进行什么操作, 所以只好让程序员委托UIViewController去代理UITableViewDelegate来实现这个方法.

同样的,它也不知道开发者希望这个表有多少行,每个cell的内容都是什么样的,所以UITableView只好委托UIViewController去代理他的UITableViewDataSource来实现这些方法.

当然,代理方法一是可以传递事件, 二也可以用来传递值,
比如:tableview的datasource里的一个代理方法

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

委托者可以把行数通过indexpath传递给被委托者,被委托者取到行数之后,自定义如何表现这个cell,再把cell传回给委托者.

下面有用一个Man类的例子来详细解说一下.
Man类,可以初始化一个胖子或瘦子,然后完成他的早中晚的一天......然后吃饭工作睡觉之后都干什么他自己不知道.....只好告诉你他吃了什么,睡了多久 ,让你来帮他决定.....我瞎编的...你也许可以编一个好一点的....

//man.h
#import <Foundation/Foundation.h>

//*************** delegate ***********************
//创建代理.吃喝工作的结果让别人帮你完成,你只需要提供吃了啥,睡了多久就行了.
@protocol ManDelegate <NSObject>

@required
//人可以吃不睡,但是一定要工作啊....所以required
-(void)work;

@optional
//返回一个睡觉的时间给被委托的对象,通过这个时间来处理相关事宜
-(void)sleepWithTime:(int)time;
//通过给被委托者一种食物,返回一个布尔值,来判断是否吃饱.
-(BOOL)eatWithFood:(NSString *)food;

@end
//*************** delegate ***********************
@interface Man : NSObject

//delegate属性
@property (nonatomic, weak) id<ManDelegate> delegate;

//是胖,是瘦呢,这个在实例化类的时候完成.
@property (nonatomic, assign) BOOL isFat;

//你这一天都分别干了啥,这个要你自己完成
-(void)morning;
-(void)afternoon;
-(void)everning;

@end
//man.m
#import "Man.h"
@implementation Man

//通过[self.delegate XXXX]确定代理出去的方法在自己的方法里的实现的位置;

//早上睡了7个小时.吃了点面包,没吃饱就不工作,吃饱了就接着工作..
-(void)morning{
    [self.delegate sleepWithTime:7];
    BOOL isFull = [self.delegate eatWithFood:@"面包"];
    //觉得面包吃饱了就工作,面包吃不饱就不工作.
    if(isFull == YES){
        NSLog(@"早饭吃饱了,工作");
        [self.delegate work];
    }
    else{
        NSLog(@"早饭吃饱了,不工作");
    }
}

//中午睡了1个小时,睡完接着工作.
-(void)afternoon{
    [self.delegate sleepWithTime:1];
    [self.delegate work];
}


//晚上睡了3个小时...
-(void)everning{
    [self.delegate sleepWithTime:3];
}
@end
//代理执行的位置
#import "ViewController.h"
#import "Man.h"

@interface ViewController ()<ManDelegate>

@property (nonatomic,retain) Man *zhangsan;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //初始化一个张三实例,张三不胖.
    self.zhangsan = [[Man alloc] init];
    self.zhangsan.isFat = NO;
    
    //把张三工作/吃/睡之后要干嘛,交给self也就是ViewController来决定,就是实现代理方法
    self.zhangsan.delegate = self;

    //张三的一天.
    [self.zhangsan morning];
    [self.zhangsan afternoon];
    [self.zhangsan everning];
}

#pragma mark ----ManDelegate
//viewcontroller决定,让张三工作的时候打印一句话到控制台.
-(void)work{
    NSLog(@"Working");
}

//viewcontroller决定,根据张三提供来的休息时间,把他的休息情况打印到控制台上.
-(void)sleepWithTime:(int)time
{
    NSLog(@"Slept for %d hour",time);
    if(time>4){
        NSLog(@"长眠不起");
    }else if(time == 4){
        NSLog(@"不长不短");
    }else if(time < 4){
        NSLog(@"小眯一下");
    }
}

//viewcontroller决定,通过张三提供吃的食物的内容,来判断张三是不是吃饱了...并且返回给张三...让他自己通过判断自己饱了没饱来处理一些事情
-(BOOL)eatWithFood:(NSString *)food{
    if (self.zhangsan.isFat == YES && [food isEqualToString:@"面包"]) {
        return NO;
    }
    else if(self.zhangsan.isFat == NO && [food isEqualToString:@"面包"]){
        return YES;
    }
    else{
        return YES;
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

问题1:为什么delegate作为属性需要是weak?

防止retain cycle循环引用...
比如tableview....UIViewCotroller通过self.view addsubview.已经指向tableview了......所以tableview.delegate = self 和tableview.datasource又指向了viewcontroller,如果此时delegate是strong,就会发生循环引用无法释放,所以这里应该是weak.....详细见上一章属详解.

观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 简而言之,就是A和B,A对B的变化感兴趣,就注册为B的观察者,当B发生变化时通知A,告知B发生了变化。这个也叫做经典观察者模式。

在iOS中,观察者模式的具体实现有两种: 通知机制(notification)和KVO机制(Key-value Observing)

1.通知机制

注册通知接收者的代码:

[[NSNotificationCenter DefaultCenter] addObserver:self
                                        selector:@selector(registerCompeletion:)
                                           name:@"RigsterCompletionNotification"
                                          object:nil];

-(void)registerCompletion:(NSNotification *)notification{
      NSDictionary *theData = [notification useInfo];
      NSString *username = [theData objectForKey:@"username"];
      NSLog(@"username = %@",username);
}

投送通知的代码

NSDictionary *dataDic = [NSDictionary dictionaryWithObject:self.text
                                                    forkey:@"username"];
[[NSNotificationCenter DefaultCenter] postNotificationName:@"RegisterCompeletionNotification"
                                                    object:nil
                                                  userInfo:dataDict];
问题1. object是干嘛的?是不是可以用来传值?

答:object是用来过滤Notification的,只接收指定的sender所发的Notification.....传值请用userInfo,而不是object

问题2. iOS中,广播通知(broadcast notification)/本地通知(local notification)/推送通知(push notification)有什么区别和不同?

出了名字相似以外,广播通知和其他两个通知是完全不一样的: 广播通知是cocoatouch中观察者模式的一种机制, 实现应用内部多个对象的通信...本地通知和推送通知中的"通知"是一种"提示"...通过警告框,发出声音,振动和在应用图标上显示数组等,在计划时间到达时,本地通知通过本地iOS发出,推送通知由第三方程序发送给苹果远程服务器,再由远程服务器推送给iOS特定应用.

2.KVO机制

对象的属性变化时,通知会直接发送到观察者对象.

可以用来实现 ,比如, UITableView滑动时导航自动变换颜色,或者,一个计算房贷的软件,当首付金额改变时,每月还款数目等数据相应自动改变等.

这里来观察UITableView一个实例的contentOffset属性.

//添加监听者
[self.tableView addObserver:self    //监听者
                forKeyPath:@"contentOffset"  //被观察对象的属性字符串
      options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld//设置.这里的设置表示把属性变换的新旧两个值都传递给观察者
                   context:nil];//上下文内容,c语言形式的任何指针类型
//监听属性变化时的回调
-(void)obserValueForKeyPath:(NSString *)keyPath   //被观察的属性
                   ofObject:(id)object   //被观察的对象
                     change:(NSDictionary *)change//字典类型包含了变化的内容,与options呼应
                    context:(void *)context//传递过来的上下文
{
             NSLog(@"%@-%@",keyPah, (NSString *)change[NSKeyValueChangeNewKey]);//通过change字典渠道变化的属性变化前或变化后的值.
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容