• 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

     

    让明天,不后悔今天的所作所为
  • 相关阅读:
    js之iframe子页面与父页面通信
    js的event对象
    整洁代码的4个条件
    PYTHON 自然语言处理
    如何检测浏览器是否支持CSS3
    BootStrap前端框架使用方法详解
    如何使用repr调试python程序
    Python编程快速上手——Excel到CSV的转换程序案例分析
    C++和JAVA传统中积极的一面
    20个LINUX相关的网站
  • 原文地址:https://www.cnblogs.com/-yun/p/4423134.html
Copyright © 2020-2023  润新知