objective c - Key Value Observing context not work -
in objective-c, when using key-value observing, have bank class accountdomestic property , person property. person added observe accountdomestic property. have static void *bankcontext = & bankcontext
in bank class context. however, after change accountdomestic property, old , new value not shown correctly due mismatch of context , bankcontext in -(void)observevalueforkeypath:(nsstring *)keypath ofobject:(id)object change:(nsdictionary<nsstring *,id> *)change context:(void *)context
method in person.
the code following, first bank class:
bank.h #import <foundation/foundation.h> #import "person.h" static void * const bankcontext = &bankcontext; @class person; @interface bank : nsobject @property (nonatomic, strong) nsnumber* accountdomestic; @property (nonatomic, strong) person* person; -(instancetype)initwithperson:(person *)person; @end bank.m @implementation -(instancetype)initwithperson:(person *)person{ if(self = [super init]){ _person = person; [self addobserver:_person forkeypath:nsstringfromselector(@selector(accountdomestic)) options:nskeyvalueobservingoptionold|nskeyvalueobservingoptionnew context:bankcontext]; } return self; } -(void)dealloc{ [self removeobserver:_person forkeypath:nsstringfromselector(@selector(accountdomestic))]; } @end
then person class:
person.h #import <foundation/foundation.h> #import "bank.h" @interface person : nsobject @end person.m #import "person.h" @implementation person -(void)observevalueforkeypath:(nsstring *)keypath ofobject:(id)object change:(nsdictionary<nsstring *,id> *)change context:(void *)context{ nslog(@"context: %p",context); nslog(@"bankcontext: %p",bankcontext); if(context == bankcontext){ if([keypath isequaltostring:nsstringfromselector(@selector(accountdomestic))]){ nsstring *oldvalue = change[nskeyvaluechangeoldkey]; nsstring *newvalue = change[nskeyvaluechangenewkey]; nslog(@"--------------------------"); nslog(@"accountdomestic old value: %@", oldvalue); nslog(@"accountdomestic new value: %@", newvalue); } } } @end
at last viewcontroller class
viewcontroller.h #import <uikit/uikit.h> @interface viewcontroller : uiviewcontroller @end viewcontroller.m #import "viewcontroller.h" #import "bank.h" #import "person.h" @interface viewcontroller () @property (nonatomic, strong) bank *bank; @property (nonatomic, strong) person *person; @property (nonatomic, strong) nsnumber *delta; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; self.person = [[person alloc] init]; self.delta = @10; self.bank = [[bank alloc] initwithperson:self.person]; } - (ibaction)accountdomesticincreasebuttondidtouch:(id)sender { self.bank.accountdomestic = self.delta; int temp = [self.delta intvalue]; temp += 10; self.delta = [nsnumber numberwithint:temp]; } @end
after click button, new , old value of accountdomestic not shown. can see context , bankcontext value not equal picture shown below:
does have idea of that?
the reason there 2 bankcontext
s. in bank.h
, have
static void * const bankcontext = &bankcontext;
this file included in both bank.m
, person.m
, both files (compilation units) define pointer bankcontext
, marked static
generates no external linkage (so can have 2 same name).
the direct solution ensure there 1 bankcontext
. in bank.h
:
extern void * const bankcontext;
and in bank.m
:
void * const bankcontext = &bankcontext;
that said, think better restructure code isn’t necessary. setup of responsibilities makes me wary (one object telling become observer), , i’m surprised compiles correctly since there appear cyclic imports (bank.h
, person.h
import each other).
Comments
Post a Comment