[help] the newcomer asked about KVO, thank you

Posted by TGLMan on Wed, 01 Jan 2020 01:50:55 +0100

Recently, I studied runtime. I saw a great God written runtime on the Internet to manually implement KVO. I tried it myself
But there are some problems. I want to ask you to post for the first time.


  • Listen for the name of the people (inherited from the NSobject) class in the ViewController.
  • Monitor class NSObject (KVO), specific monitor implementation.

*people class:

#import <Foundation/Foundation.h>

@interface people : NSObject

@property(nonatomic,copy)NSString *name;

  • NSObject (KVO)
#import <Foundation/Foundation.h>

@interface NSObject (KVO)

-(void)PE_addobserve:(NSObject *)observer forkeyPath:(NSString *)keypath options:(NSKeyValueObservingOptions)options context:(void *)context;

Concrete realization

#import "NSObject+KVO.h"

#import <objc/runtime.h>

#import <objc/message.h>

@implementation NSObject (KVO)

-(void)PE_addobserve:(NSObject *)observer forkeyPath:(NSString *)keypath options:(NSKeyValueObservingOptions)options context:(void *)context

    //Save observer
    objc_setAssociatedObject(self, (__bridge const void*)@"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    //Dynamically generate new objects
    NSString *oldstring=NSStringFromClass([self class]);

    NSString *newString=[@"PE_" stringByAppendingString:oldstring];

    const char* newname=[newString UTF8String];

    //Register new class, add method
    Class newclass=objc_allocateClassPair([self class], newname, 0);

    class_addMethod(newclass, @selector(setName:),(IMP)setName,"v@:@");


    object_setClass(self, newclass);


//Rewrite of set method
void setName(id self,SEL _cmd,NSString* name)

    //Save your own class
    Class myclass=[self class];

    //self points to the parent class
    object_setClass(self,class_getSuperclass([self class]));

//    struct objc_super sup;
//    sup.receiver=myclass;
//    sup.super_class=class_getSuperclass([self class]);

    //Parent class execution method

    //Get observer object
    id objc= objc_getAssociatedObject(self, (__bridge const void*)@"objc");

    //Inform observer of execution method
    objc_msgSend(objc, @selector(addObserver:forKeyPath:options:context:),self,name,NSKeyValueObservingOptionNew,nil);

    //self points back
    object_setClass(self, myclass);


*Treatment in VC

- (void)viewDidLoad {
    [super viewDidLoad];

    self.pe=[[people alloc]init];

//    self.pe.name=[[NSString alloc]init];

    [self.pe setValue:@"Huanglong" forKeyPath:@"name"];

    [self.pe PE_addobserve:self forkeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];

    UIButton *btn =[UIButton buttonWithType:UIButtonTypeCustom];

    btn.frame=CGRectMake(100,100, 200, 100);

    btn.backgroundColor=[UIColor brownColor];

    [btn addTarget:self action:@selector(btnclick) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:btn];

//    [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];

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

    self.pe.name=@"Little yellow dog";
//    [self.pe setValue: @ "little yellow dog" forKeyPath:@"name"];

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


    NSLog(@"I may have to change my name:%@",[self.pe valueForKeyPath:@"name"]);


But when I click the button, there is a memory error:

I try to change the attribute of name in people to strong. It's just an attempt

@property(nonatomic,strong)NSString *name;

Memory error persists:

When the second picture is screenshot, 4 is added to the method accidentally. The error is reported and the warning is not implemented, but it does not affect

Attempt to initialize is still not good

Xiaobai has a little claw for help

Attach source address: Source code

Topics: Attribute