美文网首页
链式编程思想和响应式编程思想初窥

链式编程思想和响应式编程思想初窥

作者: 952625a28d0d | 来源:发表于2017-04-21 00:29 被阅读32次

方法返回值必须有方法调用者

Masonry

  • 创建约束制造者MASContrains,并且绑定控件,生成一个保存所有约束的数组
  • 执行Mas_makeContrains传入的Block
  • 让约束制造者安装约束
    1:清空约束
    2:添加约束
  • 返回调用者本身

链式编程

#import <Foundation/Foundation.h>
#import "sumManager.h"


@interface NSObject (sum)

/**
 *  给NSObject添加一个类方法
 *
 *  @param block Block参数为sumManager
 *
 *  @return 结果
 */
+ (int)jyf_makeContraons:(void(^)(sumManager *mgr))block;

@end
#import "NSObject+sum.h"

@implementation NSObject (sum)

+ (int)jyf_makeContraons:(void (^)(sumManager *))block{
    
    // 首先初始化一个sumManager
    sumManager *mgr = [[sumManager alloc] init];
    
    // Block返回mgr对象
    block(mgr);
    
    // 返回结果
    return mgr.result;
}
#import <Foundation/Foundation.h>

@interface sumManager : NSObject

/**
 *  结果
 */
@property (nonatomic, assign) int result;

//- (instancetype)add:(int)value;
/**
 *  返回结果管理者Self
 */
- (sumManager *(^)(int))add;

@end
#import "sumManager.h"

@implementation sumManager

/**
 *  实现add方法 加值之后返回Self
 */
- (sumManager *(^)(int value))add{
    
    return ^(int value){
        _result += value;
        return self;
    };
}

@end

响应式编程

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()

@property (nonatomic, strong) Person *p;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Person *p = [[Person alloc] init];
    
    // 监听name属性
    [p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    _p = p;
}

// 一旦 p对象的name属性变化 哥们就来了
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"%@",self.p.name);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    static int i = 0;
    i++;
    _p.name = [NSString stringWithFormat:@"%d",i];
}

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


@end
  • KVC的实现过程?
    KVC的实质就是重写了属性的Set方法。。。。
    所以 在监听的时候 才会监听到。。。

  • 重写Set方法有两种情况
    1:重写分类

  • KVC底层实现
    1:自定义Person子类
    2: 重写setName方法,在内部恢复父类方法,通知观察者
    3:如何让外界调用自定义的Person子类方法?修改当前对象的isa指针,指向自定义的子类

自定义KVP的实现过程以及思想

  • 系统的是在你检测属性的时候创建了一个KVO分类的实现的,那我们就直接写一个

  • 仿照系统写一个分类方法

#import <Foundation/Foundation.h>

@interface NSObject (JYFKVO)

- (void)jyf_addObserver:(nonnull NSObject *)observer forKeyPath:(nonnull NSString *)keyPath options:(NSKeyValueObservingOptions)option context:(nullable void *)context;


@end
  • 实现
#import "NSObject+JYFKVO.h"

// 因为要通知外界 所以必然要发送消息
#import <objc/message.h>

@implementation NSObject (JYFKVO)

/**
 *  监听对象的某一个属性
 *
 *  @param observer 监听者
 *  @param keyPath  keyPath
 *  @param context  context
 */

// self ==> 被观察者(Person)
// observer ==> 观察者
- (void)jyf_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)option context :(void *)context{
    /**
     1:自定义子类对象
     2:重写被监听的对象的setName,在方法中我们来调用super的,调用完毕,通知观察者
     3:修改当前对象的isa指针,让它指向我们自定义的子类!!
     */
    
    // 1:动态生成一个类
    // 1.1:创建Self的子类!第一步:获取类名
    NSString *oldClassName = NSStringFromClass([self class]);
    
    // 新的类名
    NSString *newClassName = [@"jyfKVO_" stringByAppendingString:oldClassName];
    
    // 转成C字符串
    const char * newName = [newClassName UTF8String];
    
    // 创建一个类的Class对象
    Class MyClass = objc_allocateClassPair([self class], newName, 0);
    
    // 注册类 到我们的项目中
    objc_registerClassPair(MyClass);
    
    // 2:重写Set方法 添加set方法
    // v@:@ 表示没有返回值 没有参数
    class_addMethod(MyClass, @selector(setName:), (IMP)setName, "v@:@");
    
    // 3: 修改isa指针 把self的指针 改成我们自定义的子类
    object_setClass(self, MyClass);
    
    // 4:保存观察者对象
    objc_setAssociatedObject(self, @"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

// 1:调用super的set方法
// 2:通知我们的外界
void setName(id self, SEL _cmd, NSString * newName){
    
    // 复写 调用super的setname方法
    
    // 保存子类类型
    id class = [self class];
    
    // 改变self的isa指针
    object_setClass(self, class_getSuperclass(class));
    
    // 调用父类的set方法
    objc_msgSend(self, @selector(setName:),newName);
    
    // 拿到观察者
    id objc = objc_getAssociatedObject(self, @"objc");
    
    // 通知观察者
    objc_msgSend(objc, @selector(observeValueForKeyPath:ofObject:change:context:),self,@"name",nil,nil);
    
    // 改回子类类型
    object_setClass(self, class);
}

@end
  • 在这里打断点发现 走完我们自定义的监听方法,isa指针发生了变化 已经指向了我们的子类
Paste_Image.png
  • 使用消息机制 需要打开


    Paste_Image.png
  • 这样 我们就可以发现 能正常监听了 需要注意的是 监听完毕 需要将指针归还给旧类

相关文章

网友评论

      本文标题:链式编程思想和响应式编程思想初窥

      本文链接:https://www.haomeiwen.com/subject/egghzttx.html