类之间通信

1.类之间通信的原因

在Class中实例化BClass并调用BClass的方法之后,绝不能在BClass中再实例化AClass并调用AClass中的方法,会造成交叉引用,无法释放对象,这就是类之间通信的原因。

类之间通信的三大方式:Block 通知 委托代理

2.Block

//Block:代码块

//Block:1.声明    返回值+(MyBlock,也可以取名为其他的)声明+传递参数

typedef    int    (^MyBlock)(int);

//Block:2.实现

MyBlock b1 = ^(int b){

    NSLog(@"我是一个代码块,我的接收参数是%d",b);    //当调用b1的时候,就是在调用这个代码块

return b+1;

};

//Block:3.调用

int newB = b1(10);

NSLog(@"%d",newB);

输出结果:

我是一个代码块,我的接收参数是10

11

//Block:4.变量的作用范围 

_block int a = 5;

MyBlock b1 = ^(int b){

    NSLog(@"我是一个代码块,我的接收参数是a=%d b=%d",a,b);   

    a = a + 1;

return a+b;

};

a在Block外定义的,可以在Block里正常输出打印,但是不能在Block里对a进行操作,会报错,想解决的话定义a的时候在前面加_block。

代码的执行顺序:执行的时候执行到Block的时候会先跳过,直到调用它的时候才进入Block。

//Block:5.block在类之间通信的使用


//BClass.h 

typedef void (^MyBlock)(NSString);

-(void)testBlock:(MyBlock)block str1:(NSString*)str1;


//BClass.m

-(void)testBlock:(MyBlock)block str1:(NSString*)str1{

    NSLog(@"我是被谁调用的:%@",str1);

    NSLog(@"我是一个B类");

    block(@"我是从B类来的");

}


//AClass.h

#import "BClass.h"


//AClass.m

MyBlock b1 = ^(NSString *str1){

    NSLog(@"AClass:%@",str1);

};

BClass  *classb = [[BClass alloc]init];

[classb testBlock:b1 str1:@"AClass"];


运行结果:

我是被谁调用的:AClass

我是一个B类

AClass:我是从B类来的

//Block:6.快速的实现方法


BClass *classb = [[BClass alloc]init]; 

[classb testBlock:^(NSString* str1){

    NSLog(@"AClass:%@",str1);

} str1:@"AClass"];


3.广播Notification

1.广播(通知)中心

2.发起人

3.接收者

4.步骤

①广播接收者向广播中心注册广播接收对象

②定义广播接收的方法

③发起人向广播中心发送广播

5.例:A发送,B接收


//main.m

#import "BClass.h"

BClass *b1 = [[BClass alloc]init];

[b1 testNotification];


//BClass.h

#import "AClass.h"

-(void)testNotification;


//BClass.m    A->B

-(void)testNotification{

    //①注册

    //参数1:谁在接收这个方法    参数2:这个广播的响应方法    参数3:广播名称    参数4:别的广播发过来的时候是可以带一些自己的参数的

    //self:当前的这个类

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(testAction) name:@"TESTNOTIF" object:nil];

    Class *classa = [[AClass alloc]init];

/*带参数的广播

    //加了个冒号

        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(testAction:) name:@"TESTNOTIF" object:nil];

        Class *classa = [[AClass alloc]init];

*/

}

-(void)testAction{

    NSLog(@"我已经接收到广播");

}

/*带参数的广播

-(void)testAction:(NSNotification*)notify{

    NSNumber *num = notify.object;

    NSDictionary *dic = notify.userInfo;

    NSLog(@"%@ %@",num,dic);

}

*/

//销毁

-(void)dealloc{

    [[NSNotificationCenter defaultCenter]removeObserver:self name:@"TESTNOTIF" object:nil];

}


//AClass.m

-(id)init {

    self = [super init];

    if(self){

        [[NSNotificationCenter defaultCenter]postNotificationName:@"TESTNOTIF" object:nil];

/*带参数的广播

    NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];

    [dic setValue:@"123" forKey:@"keya"];

    //参数1:广播的唯一标识符(名称)    参数2:object对象    参数3:一个字典

    [[NSNotificationCenter defaultCenter]postNotificationName:@"TESTNOTIF" object:[NSNumber numberWithInt:5] userInfo:dic];

    //NSNumber和Int都表示整型数据,唯一不同点是NSMumber是oc中的一个对象,而Int只是一个整型数据

*/

    }

    return self;

}


//一对多的广播


//Teacher.m

-(id)init {

    self = [super init];

    if (self) {

        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notification) name:@"TESTNOTIF" object:nil];

    }

    return self;

}

-(void)notification {

    NSLog(@"Teacher已接收");

}

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TESTNOTIF" object:nil];

}


//Student.m

-(id)init {

    self = [super init];

    if (self) {

        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notification) name:@"TESTNOTIF" object:nil];

    }

    return self;

}

-(void)notification {

    NSLog(@"Student已接收");

}

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TESTNOTIF" object:nil];

}


//Person.m

@interface Person() {

    //类扩展 

    Student *s1;

    Teacher *t1;

}

@end

@implementation Person

-(void)testNotification {

    s1 = [[Student alloc]init];

    t1 = [[Teacher alloc]init];

    [[NSNotificationCenter defaultCenter]postNotificationName:@"TESTNOTIF" object:nil];

}

@end


//main.m

Person *p = [[Person alloc]init];

[p testNotification];


//多对一的广播


//Teacher.m

-(id)init {

    self = [super init];

    if (self) {

        NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];

        [dic setValue:@"我来自Teacher" forKey:@"info"];

        [[NSNotificationCenter defaultCenter]postNotificationName:@"TESTNOTIF" object:nil userInfo:dic];

    }

    return self;

}


//Student.m

-(id)init {

    self = [super init];

    if (self) {

        NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];

        [dic setValue:@"我来自Student" forKey:@"info"];

        [[NSNotificationCenter defaultCenter]postNotificationName:@"TESTNOTIF" object:nil userInfo:dic];

    }

    return self;

}


//Person.m

@interface Person() {

    //类扩展

    Student *s1;

    Teacher *t1;

}

@end

@implementation Person

-(void)testNotification {

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notification:) name:@"TESTNOTIF" object:nil];

    s1 = [[Student alloc]init];

    t1 = [[Teacher alloc]init];

}

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

    NSDictionary *d = notification.userInfo;

    NSString *str = [d valueForKey:@"info"];

    NSLog(@"%@",str);

}

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TESTNOTIF" object:nil];

}

@end


4.协议委托代理

1.定义协议(以找黄牛买票为例)

@property(nonatomic,weak) id Delegate;//接收委托,协议一般都用nonatomic,weak

@protocol BuyTicketDelegate

@optional //表示下面的方法不一定要实现

-(void)buyTicket;

@end

2.委托

3.代理方法的调用


//Aclass.h

@protocol BuyTicketDelegate;

@interface AClass : NSObject

@property(nonatomic,weak) id Delegate;//接收委托,协议一般都用nonatomic,weak

-(void)myBuyTicket;

@end


@protocol BuyTicketDelegate

@optional //表示下面的方法不一定要实现

-(void)buyTicket;

@end


//Aclass.m

-(void)myBuyTicket {

    if ([self.Delegate respondsToSelector:@selector(buyTicket)]) {

        [self.Delegate buyTicket];

    }


//HuangNiu.h

#import "AClass.h"

@interface HuangNiu : NSObject

-(void)testDelegate;

@end


//HuangNiu.m

-(void)testDelegate {

    AClass *classa = [[AClass alloc]init];

    classa.Delegate = self;//委托

    [classa myBuyTicket];

}

-(void)buyTicket {

    NSLog(@"我是黄牛,我正在帮你买票");

}


5.定时器

1.定时器的基本使用

2.定时器的精度

3.代码的执行时间


//main.m

#import

#import "MyTimer.h"

int main(int argc, const char * argv[]) {

    @autoreleasepool {

        MyTimer *timer = [[MyTimer alloc]init];

        [timer testTimer];

    }

    return 0;

}


//MyTimer.h

#import

@interface MyTimer : NSObject

-(void)testTimer;

@end


//MyTimer.m

#import "MyTimer.h"

@interface MyTimer() {

    NSTimer *timer1;

    NSTimer *timer2;

}

@end

@implementation MyTimer

-(void)testTimer {

//1. 参数一:中断间隔,单位是s 参数二:当前定时器的响应方法是哪个对象来响应 参数三:响应方法 参数四:需要传递的参数 参数五:是否重复

//    timer1 = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(myLog) userInfo:nil repeats:false];

//    [[NSRunLoop currentRunLoop]addTimer:timer1 forMode:NSDefaultRunLoopMode];

//    [[NSRunLoop currentRunLoop]run];

//2. 带参数定时器 + 非RunLoop方法

//    timer2 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(myLog:) userInfo:@"hello" repeats:false];//这个方法直接将定时器放入RunLoop当中

//    [timer2 fire];

// 3. 定时精度 0.01s = 10ms 只能粗略的计算,并不是准确的10ms

//    timer1 = [NSTimer timerWithTimeInterval:0.01 target:self selector:@selector(myLog) userInfo:nil repeats:true];

//    [[NSRunLoop currentRunLoop]addTimer:timer1 forMode:NSDefaultRunLoopMode];

//    [[NSRunLoop currentRunLoop]run];

//4. 如何快速的打印出当前代码执行时间

    NSDate *timeMark = [NSDate date];

    NSLog(@"hello");

    NSLog(@"hello");

    NSLog(@"hello");

    NSTimeInterval timeInterval = [timeMark timeIntervalSinceNow];//上面三个打印hello的时间差,是个负数

    float timeNow = 0 - timeInterval;

    NSLog(@"timeNow = %f",timeNow);

}

-(void)myLog {

    NSLog(@"我是一个定时器");

}

-(void)myLog:(NSTimer *)timer {

    NSLog(@"我是定时器2 = %@",timer2.userInfo);

}

@end



6.KVC(Key Value Coding)和KVO(键值观察)

1.kvc的基本使用

动态设置:

                setValue:属性值 forKey:属性名

                setValue:属性值 forKeyPath:属性路径

动态读取:

                valueForKey:属性名

                valueForKeyPath:属性路径

在一般修改一个对象的属性的时候,forKey和forKeyPath,没什么区别。如:

[Person setValue:@"lisiv" forKey:@"name"];         

[Person setValue:@"jack" forKeyPath:@"name"]; 

这两种都可以。

如果看层次结构深一点的。比如person还有其他属性,dog,car等等

就只能通过forKeyPath,它能使用点语法,深层次的去寻找我们需要的属性。如:

[Person setValue:@"kala" forKeyPath:@"Person.dog.name"]; 


2.kvo的基本使用

监听对象属性的变化

步骤:①注册    ②观察    ③移除观察


//KVOClass.h

#import

#import "Person.h"

@interface KVOClass : NSObject

@property(nonatomic,strong)Person *p1;

-(void)testKVO;

@end


//KVOClass.m

#import "KVOClass.h"

@implementation KVOClass

-(void)testKVO { 

     //1.注册

     self.p1 = [[Person alloc]init]; 

     [self.p1 setAge:15];

     [self.p1 addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; 

     [self.p1 setAge:18]; 

}

//3.移除-(void)dealloc {

     [self.p1 removeObserver:self forKeyPath:@"age"];

}

//2.观察

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    NSLog(@"我的年龄变化了");

}

@end


3.KVO监听股票价格(计时器模拟价格变动)


//Stock.h

@property(nonatomic,assign) float price;


//KVOClass.h

#import

#import "Stock.h"

@interface KVOClass : NSObject

@property(nonatomic,strong)Stock *p1;

@property(nonatomic,strong)NSTimer *timer;

-(void)testKVO;

@end


//KVOClass.h

#import "KVOClass.h"

float currentPrice;

@implementation KVOClass

-(void)testKVO { 

     //1.注册 

     self.p1 = [[Stock alloc]init];

     currentPrice = 3.6; 

     [self.p1 setPrice:currentPrice];

     [self.p1 addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; 

     self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(priceChange) userInfo:nil repeats:true];

     [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSDefaultRunLoopMode];

     [[NSRunLoop currentRunLoop]run]; 

}

-(void)priceChange {

     currentPrice += 0.1; 

     [self.p1 setPrice:currentPrice];

}

//3.移除

-(void)dealloc { 

     [self.p1 removeObserver:self forKeyPath:@"price"];

}

//2.观察

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    NSString *oldPriceString = [change valueForKey:@"old"];//old和new是约定俗成的

    NSString *newPriceString = [change valueForKey:@"new"];

    float oldPrice = oldPriceString.floatValue;

    float newPrice = newPriceString.floatValue;

    if (newPrice > oldPrice) {

        NSLog(@"当前股价正在上涨,当前股价为%0.2f",newPrice);

    }


}

@end

你可能感兴趣的:(类之间通信)