UI基础(五)之代理、通知的小结

代理:

这里只强调一些注意点:

注意点(一):代理为什么要用weak修饰?

答:为了防止内存泄漏

代码如下:

HSDog.h类
@protocol HSDogDelegate <NSObject>
@end

@interface HSDog : NSObject

@property (nonatomic, weak) id<HSDogDelegate>delegate;

@end


HSDog.m
#import "HSDog.h"

@implementation HSDog

- (void)dealloc
{
    NSLog(@"HSDog----销毁");
}

@end

HSPerson.h
@interface HSPerson : NSObject

@end

HSPerson.m
#import "HSPerson.h"
#import "HSDog.h"

@interface HSPerson()<HSDogDelegate>
/** 强引用dog*/
@property (nonatomic, strong) HSDog *dog;
@end

@implementation HSPerson

- (instancetype)init
{
    self = [super init];
    if (self) {
        // 实例化dog
        self.dog = [[HSDog alloc] init];
        self.dog.delegate = self;

    }
    return self;
}

- (void)dealloc
{
    NSLog(@"HSPerson----销毁");
}

@end

ViewController.m
#import "ViewController.h"
#import "HSPerson.h"

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    HSPerson *person = [[HSPerson alloc] init];

}
@end

代码其实可以不用看,只需要知道几点:

(1)Person *p = [Person alloc]init];在ARC中默认是强指针指向,但p指针存放在栈区,出了其所在的括号就会被回收掉

(2)self.dog = [[Dog alloc]init];注意的是:self.dog调用set方法,方法内部其实是:__strong Dog* _dog; 因为有: 

/** 强引用dog*/
@property (nonatomic, strong) HSDog *dog;

所以知道_dog是strong修饰的.

(3)而dog是依附于person对象的,也就是说self.dog指针的存亡取决于person对象是否消失,如果person对象没有消失,那么self.dog就一直存在着。

同理self.dog.delegate= self也是如此

综上所述:代理需要用weak修饰,至于用strong会不会产生内存泄漏也要根据具体代码和指针指向来判断。

 







 

 

 

 

1.需要掌握:

•通知的发布
 
•通知的监听
 
•通知的移除
通知中心(NSNotificationCenter)

 

小结:其实很简单:通知流程就是:一个发布通知的对象把通知发布给通知中心,通知中心负责把通知传递给通知的接收者.
 
 

 

插曲:一直以来都是创建UI项目,但不能忘记OC 项目是怎么创建的,看下图:

 第一个最简单的通知的使用:过程分析:

注意点:添加监听者必须写在发送通知之前

1.通知中心发送通知,(前提是必须有一个通知,可以直接在发送通知中写出来,不用提前创建通知对象).

2.通知中心发送了通知之后,会找前面是否有监听者监听我的这个通知,如果有,就会找到这个监听者对象.

3.找到监听者对象后会调用监听者对象的方法,完成实现通知的方法.

4.注意:不能忘记通知的使用完毕后,要移除监听者.

 

5.注意:有没有想过:为什么一般我写监听者对象实现的方法中带的参数是通知类型的?可以带别的类型的参数么?

答:是不能带别的类型的参数的,该方法存在的意义在于:我传给监听者一个通知,并要你实现一个方法,目的是为了让你看到

我通知的具体内容,因为我传递的就是通知,该方法也称之为通知方法,用于传递通知的具体信息,怎么看呢,只需要带上通知类型的参数打印出来就可以了.

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

@interface News : NSObject

@property (nonatomic,copy) NSString *newsName;



@end

News.m

#import "News.h"

@implementation News

@end

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject


@property (nonatomic,copy) NSString *name;


- (void)show:(NSNotification *)notification;

@end

Person.m

#import "Person.h"

@implementation Person

- (void)show:(NSNotification *)notification{
    
    
    NSDictionary *dict = notification.userInfo;


    NSLog(@"%@",dict[@"吴亦凡"]);
    NSLog(@"监听到通知了  监听人 %@--- %@",self.name,notification);
    
}




- (void)dealloc{

#pragma mark -- 移除监听者
    
//    在MRC中,非ARC 中,需要调用下面的方法
//    [super dealloc];
    
//    NSLog(@"移除监听者");
    [[NSNotificationCenter defaultCenter]removeObserver:self];
    
    

}
@end

main.m

//
//  main.m
//  03-通知的使用
//
//  Created by apple on 16/7/15.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "News.h"
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        
        News *sinaNew = [[News alloc]init];
        
        sinaNew.newsName = @"sina";
        
        News *wangNew = [[News alloc]init];
        
        wangNew.newsName = @"wangyi";
        
        Person *p1 = [[Person alloc]init];
        
        p1.name = @"zhangsan";
        
        
        Person *p2 = [[Person alloc]init];
        p2.name = @"lisi";
        
     
#pragma mark -- 通知
        
        // 1. 参数1: name =>通知的名字
        // 2. 参数2: object =>发布通知的对象
        // 3. 参数3: userInfo=>额外信息
        NSNotification *notification = [NSNotification notificationWithName:@"yule" object:sinaNew userInfo:@{@"赵薇事件":@"黑社会"}];
        
        NSNotification *notification2 = [NSNotification notificationWithName:@"yule" object:wangNew userInfo:@{@"吴亦凡":@"做坏事"}];
        
        
        NSNotification *notification3 = [NSNotification notificationWithName:@"junshi" object:sinaNew userInfo:@{@"南海":@"仲裁不通过"}];
        
#pragma  mark -- 发布通知
        
        //1. 现有通知中心
        // 通知中心 是单例设置模式, 它有一个默认的方法,可以得到这个对象[NSNotificationCenter defaultCenter]
        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
        
        
        //2. 发布通知
        // 将创建的通知发布出去
//        [notificationCenter postNotification:notification];
        
#pragma mark -- 监听通知
        
        //添加监听者
        //<#(nonnull id)#> 代表监听者对象
        //@selector   代表监听到消息后,所调用的方法
        // name 发布的通知名字  传入nil代表无论是什么通知,都接受
        //object 发布通知的对象  传入nil代表无论哪个通知对象发布的信息都接受
        [notificationCenter addObserver:p1 selector:@selector(show:) name:nil object:nil];
        
        [notificationCenter addObserver:p2 selector:@selector(show:) name:@"yule" object:nil];
        
        
        
        [notificationCenter postNotification:notification];
        [notificationCenter postNotification:notification2];
        [notificationCenter postNotification:notification3];
        
        
        NSLog(@"代码执行结束");
        
        
        
    }
    return 0;
}

代理事例二:

main.m

//
//  main.m
//  01-通知的使用
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>

#import "Baby.h"
#import "Father.h"
#import "Mother.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Father *father = [[ Father alloc]init];
        
        Mother *mother = [[Mother alloc]init];
        
        
      
        Baby *baby = [[Baby alloc]init];
        
// 通知的使用: 添加监听者
        // 第一个参数 id--> 监听者对象
        // 第二个参数 selector--> 监听到后调用的方法
        // 第三个参数 name --> 发布通知的名字
        // 第四个参数 object -> 发布通知的对象
        [[NSNotificationCenter defaultCenter]addObserver:father selector:@selector(notification:) name:nil object:baby];

        
        
        [[NSNotificationCenter defaultCenter]addObserver:mother selector:@selector(notification:) name:nil object:baby];
        
        
        [baby babyKu];
        
        [baby babyNiao];
        
        
    }
    return 0;
}

Baby.h

//
//  Baby.h
//  01-通知的使用
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>
@class Baby;


@interface Baby : NSObject





-(void)babyKu;

- (void)babyNiao;

@end

Baby.m

//
//  Baby.m
//  01-通知的使用
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import "Baby.h"

@implementation Baby


-(void)babyKu{

    NSLog(@"宝宝在哭");
    

    //1. 通知的使用
//    NSNotification
    
    //1.1 发布通知
    
    // name---> 通知的名字
    // object -->发布通知的对象
    // userInfo-->额外信息
    [[NSNotificationCenter defaultCenter]postNotificationName:@"ku" object:self userInfo:nil];
    
   

}

- (void)babyNiao{


    NSLog(@"宝宝尿床了");
    
    
    [[NSNotificationCenter defaultCenter]postNotificationName:@"niao" object:self userInfo:nil];
    
    
   
    
    
    
    
}

@end

Father.h

//
//  Father.h
//  01-通知的使用
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface Father : NSObject 

@end

Father.m

//
//  Father.m
//  01-通知的使用
//
//  Created by apple on 16/7/17.
//  Copyright © 2016年 itcast. All rights reserved.
//

#import "Father.h"

@interface Father ()

@end

@implementation Father


- (void)notification:(NSNotification *)notification{

    NSLog(@"%@",notification);
    
    NSString *name = notification.name;
    
    
    if ([@"ku" isEqualToString:name]) {
        [self lookBabyKu];
    }else{
    
        [self lookBabyNiao];
    }

}


- (void)dealloc{

    //销毁监听者
    [[NSNotificationCenter defaultCenter]removeObserver:self];

}


- (void)lookBabyKu{

    NSLog(@"爸爸 照顾婴儿哭");
}


- (void)lookBabyNiao{

    NSLog(@"爸爸 照顾婴儿尿");

}


@end

 

 小结:
通知:很简单,就四步:
第一步:我需要传递数据的时候(一般多控制器就是逆传),发布通知:
//发送通知
        [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ" object:self userInfo:nil];

第二步:哪个控制器需要监听我这个通知,我就在那个控制器里面(具体位置是可以获取到目标控制器的方法中),添加监听者对象

//用通知来传递数据
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelLoginMessage) name:nil object:listController];

第三步:实现第二步里面的方法

 
#pragma mark -- 实现通知方法
- (void)cancelLoginMessage{
    //用户名和密码清空
            _nameField.text = @"";
            _passwordField.text = @"";
            //关闭自动登录和记住密码switch
            _recordSwitch.on = NO;
            _autoSwitch.on = NO;
            //登录按钮
            _loginBtn.enabled = NO;
    
            //保存在用户偏好设置的数据也要恢复默认值
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:KRecordSwitch];
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:KAutoSwitch];
            [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:KUserName];
            [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:KPassWord];
}

第四步:很关键,别忘了在这个下面移除监听者

#pragma mark -- 销毁监听者
- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

 

 
 
 
 代理和通知区别:
代理只能有一个代理对象,通知可以有多个监听者,也就是所谓的一对一和一对多的区别:
因为代理:
baby.delegate= father;
baby.delegate = mather;
当我这样设置的时候,其实很明显知道,baby的代理对象是下面的mather ,这是根据赋值运算的基本原理得出的,所以代理只能有一个代理对象.
而通知,谁成为我通知的监听者,谁就能做通知对象.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2016-11-06 02:52  忆缘晨风  阅读(183)  评论(0编辑  收藏  举报