KVC,KVO

 

 

kvc  kvo

 

 

观察者模式

1. 概述

  有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

2. 解决的问题

  将一个系统分割成一些相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。

 

 

【通知中心】

 

//注册一个观察者,从现在开始,self开始监听IWillKillYou的这个广播,只要这个工程中任意一个地方发送这个广播,self都能响应shasha。

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

//取消观察者身份

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

//发送的广播,只要是这个广播的观察者,都能收到广播,然后触发方法,没有个数限制

[[NSNotificationCenter defaultCenter] postNotificationName:@"IWillKillYou" object:str];

 

 

//视频播放完成时,系统会自动发送这个广播(自动放完,或者用户手动结束都会响应)

MPMoviePlayerPlaybackDidFinishNotification

 

 

【KVC】

 

//设置和获取成员变量的值(不管是公开还是私有的,通杀!!)

 

    //oc特有的kvc(key-value-coding)键值编码

    //通过kvc对属性赋值  value 为属性的值,key为属性的名称

    //kvc为oc动态运行时机制的一个特性,(先找有没有setName方法,没有 就找name变量,再没有,找_name)

    [_stu setValue:@"林俊杰" forKey:@“name"];

    //根据属性名称,获取属性的值

    NSLog(@"name=%@“,[_stu valueForKey:@“name"]);

 

//任何NSObject(或子类)对象 都可以使用kvc

//需要注意的是key必须是存在的,如果不存在程序就挂了

- (void)setValue:(id)value forKey:(NSString *)key;

- (id)valueForKey:(NSString *)key;

 

 

【KVO】

//kvo (key-value-observer)(键-值-观察) (对符合kvc操作的变量的观察)

 

    //让self成为_user中name属性的观察者,一旦有对name赋值的操作,self都能监测到,从而self可以进行后续的处理

    //addObserver:指定观察者 ;keyPath:要观察的属性

    //options NSKeyValueObservingOptionNew/NSKeyValueObservingOptionOld 对属性新旧值的观察

    [_user addObserver:self forKeyPath:@“name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

 

 

//self监测到name的赋值操作后,会触发此方法

//keyPath 观察的成员变量名(本例中为name)

//object 为被观察的对象 (_user)

//change 带有变量变化前后的值

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

{

    if ([object isKindOfClass:[User class]]) {

        //取到name属性的旧值

        NSString *old = [change objectForKey:@"old"];

        //获取name的新值

        NSString *new = [change objectForKey:@"new"];

 

        NSLog(@“%@====%@“,old,new);

    }

}

 

//取消观察者

[_user removeObserver:self forKeyPath:@“name"];

 

 

//添加和取消观察者

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context;

 

响应事件

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

 

 

【本地视频播放】

 

//导入系统框架 MediaPlayer.framework

#import <MediaPlayer/MediaPlayer.h>

 

NSString *videoPath = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"mp4"];

  //本地视频

    NSURL *url = [NSURL fileURLWithPath:videoPath];

    

        //初始化带有视频播放器的控制器

        _playController  =[[MPMoviePlayerViewController alloc] initWithContentURL:url];

        //弹出视频播放器的界面

        [self presentViewController:_playController animated:YES completion:nil];

 

//下面三个方法可不写

        //moviePlayer属性,为视频播放器,操作和音频类似,有准备,放,暂停等

        //指定播放的视频资源的类型,MPMovieSourceTypeFile(普通的文件类的视频资源)

        _playController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;

        //预备

        [_playController.moviePlayer prepareToPlay];

        //放

        [_playController.moviePlayer play];

 

        //监听播放完成事件(播放完成时会自动发送name:MPMoviePlayerPlaybackDidFinishNotification这个通知)

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playBack) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

    

 

- (void)playBack{

    //从通知中心,移除自身的观察者身份

    [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

    if (_playController) {

        //停止播放

        [_playController.moviePlayer stop];

        _playController = nil;

    }

}

 

 

//滚动字幕,跑马灯

    UIView *bgView = [[UIView alloc]initWithFrame:CGRectMake(20, 100, 150, 25)];

    bgView.clipsToBounds = YES;

    bgView.backgroundColor = [UIColor grayColor];

    [self.view addSubview:bgView];

    

    UILabel *runLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 150, 25)];

    runLabel.text = @"这句话只是为了展示一下跑马灯的效果";

    runLabel.textColor = [UIColor whiteColor];

    [bgView addSubview:runLabel];

    [runLabel sizeToFit];

    

    CGRect frame = runLabel.frame;

    frame.origin.x = bgView.frame.size.width;

    runLabel.frame = frame;

    

    [UIView beginAnimations:nil context:NULL];

    //动画时间(参数需要按需调整)

    [UIView setAnimationDuration:frame.size.width/20.0f];

    //重复次数

    [UIView setAnimationRepeatCount:CGFLOAT_MAX];

    //匀速

    [UIView setAnimationCurve:UIViewAnimationCurveLinear];

    //返回效果

    [UIView setAnimationRepeatAutoreverses:NO];

    

    frame.origin.x = -frame.size.width;

    runLabel.frame = frame;

    

    [UIView commitAnimations];

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#import "ViewController.h"

#import <MediaPlayer/MediaPlayer.h>

 

@interface ViewController ()

 

{

    MPMoviePlayerViewController *_mpvc;

}

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

}

 

- (IBAction)btnClick:(UIButton *)sender

{

    NSString *path = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"mp4"];

    

    //本地文件路径

    NSURL *url = [NSURL fileURLWithPath:path];

    

    //网络文件地址

    url = [NSURL URLWithString:@"http://love.local/iOS/1.mp4"];

    

    //创建一个自带视频播放器的vc

    _mpvc = [[MPMoviePlayerViewController alloc] initWithContentURL:url];

    

    //弹出播放视频的vc

    [self presentMoviePlayerViewControllerAnimated:_mpvc];

    

    //通知中心添加一个观察者self

    //self开始监听播放完成的广播,收到广播以后就调playingBack

    //当视频播放完成或者用户点击了done,系统都会发送这个广播

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playingBack) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

}

 

- (void)playingBack

{

    //移除观察者

    [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

    

    //播放完成以后,将播放器的内存释放

    _mpvc = nil;

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

@end

 

 

 

 

----------------------------------------------------------分割----------------------------------------------------------

 

 

#import <Foundation/Foundation.h>

 

@interface Dog : NSObject

 

{

    NSString *_name;

}

 

@property (nonatomic, copy) NSString *job;

 

@end

 

 

 

 

 

 

 

 

 

 

 

 

#import "Dog.h"

 

@interface Dog ()

 

{

    NSString *_long;

}

 

@end

 

 

 

@implementation Dog

 

{

    //实现部分也能声明全局的变量,只不过一般不这样干

    NSString *_height;

}

 

//使用kvc设置变量的时候,如果key不存在,会调用到这个方法里

- (void)setValue:(id)value forUndefinedKey:(NSString *)key

{

    NSLog(@"===%@",key);

}

 

//使用kvc查询变量的时候,如果key不存在,会调用到这个方法里

- (id)valueForUndefinedKey:(NSString *)key

{

    NSLog(@"get === %@",key);

    return nil;

}

 

@end

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#import "ViewController.h"

#import "Dog.h"

 

@interface ViewController ()

 

{

    Dog *bai;

}

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

    

    bai = [[Dog alloc] init];

    

    bai.job = @"qqq";

    NSLog(@"job = %@",bai.job);

    

    //key-value-coding   kvc

    //键-值-编码

    //功能就是访问成员变量(公有,私有通杀)

    //1,会先找setName:这个方法,有就调用

    //2,如果没有setter方法,就找_name这个变量

    //3,如果找不到_name,就找name

    //如果key不存在有2种情况

    //a,对象没实现容错方法,就会崩

    //b,对象实现了容错方法,会直接调用

    [bai setValue:@"www" forKey:@"age"];

    NSLog(@"2 = %@",[bai valueForKey:@"age"]);

    

    

    /**********开始kvo********/

    

    //给bai指向的对象添加一个观察者,self

    //self开始观察bai里面name(_name)这个变量,只要这个变量发生了改变,就会调用到观察者事件里

    [bai addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

}

 

//观察者事件

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

{

    NSLog(@"keyPath = %@, class = %@",keyPath,[object class]);

    

    NSLog(@"dic = %@",change);

}

 

 

- (IBAction)btnClick:(UIButton *)sender

{

    [bai setValue:[NSString stringWithFormat:@"%d==",arc4random_uniform(20)] forKey:@"name"];

}

 

- (void)dealloc

{

    //取消观察

    [bai removeObserver:self forKeyPath:@"name"];

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

 

@end

 

让明天,不后悔今天的所作所为
原文地址:https://www.cnblogs.com/-yun/p/4423134.html