iOS bind binding

Source: Internet
Author: User

Whether it's an MVC or an MVVM architecture, we all need to be able to synchronize the model changes to the relevant parts in time. Just like the monthly observer model, you can do this in iOS with KVO, but it's always a way to get the code out of order. Here you can use Thbinder on GitHub to accomplish this task. At the same time I do a bit of this code, so I use a simple macro to complete, do not save the Thbinder instance.


#import "THBinder.h" #import "THObserver.h" #import <objc/runtime.h> #import <objc/message.h> #define Tmbinddictorykey "__tmbinddictorykey" #define Bindkey (Target,keypath) [NSString stringwithformat:@ "_ _binder__%@ ", Keypath]static nsmutableset *swizzledclasses () {static dispatch_once_t oncetoken;static NSMutableSet * swizzledclasses = Nil;dispatch_once (&oncetoken, ^{swizzledclasses = [[Nsmutableset alloc] init];}); return swizzledclasses;} static void swizzledeallocifneeded (Class classtoswizzle) {@synchronized (swizzledclasses ()) {NSString *classname =        Nsstringfromclass (Classtoswizzle); if ([Swizzledclasses () containsobject:classname]) return; SEL deallocselector = Sel_registername ("Dealloc"); SEL swizzledeallocselector = Sel_registername ("Swizzledelloc"); __block void (*originaldealloc) (__unsafe_unretained        ID, SEL) = NULL; ID newdealloc = ^ (__unsafe_unretained ID self) {if (Class_respondstoselector (Classtoswizzle,swizzledeallocselec TOR)) Objc_msgsend (Self,swizzledeallocselector), if (Originaldealloc = = NULL) {struct Objc_super superinfo = {. Receiver = Self,.super_class = Class_getsuperclass (classtoswizzle)};objc_msgsendsuper (&superinfo, Deallocselector);} else {originaldealloc (self, deallocselector);}};i MP newdeallocimp = Imp_implementationwithblock (Newdealloc); if (!class_addmethod (Classtoswizzle, DeallocSelector, Newdeallocimp, "[email protected]:") {//The class already contains a method implementation. Method Deallocmethod = Class_getinstancemethod (Classtoswizzle, deallocselector);//We need to store original Implementation before setting new implementation//in case method was called at the time of Setting.originaldealloc = (__ty peof__ (Originaldealloc)) method_getimplementation (Deallocmethod);//We need to store original implementation again, in case it just Changed.originaldealloc = (__typeof__ (originaldealloc)) method_setimplementation (Deallocmethod,        NEWDEALLOCIMP);} [SwizzledclassES () addobject:classname];}} @interface NSObject (supportbinding)-(void) Setbinder: (ID) Binder KeyPath: (nsstring*) keypath; @end @implementation NSObject (supportbinding)-(void) swizzledelloc{nsmutabledictionary* binddict = Objc_getassociatedobject (self,    Tmbinddictorykey); [Binddict enumeratekeysandobjectsusingblock:^ (id key, Nsarray *obj, BOOL *stop) {[obj enumerateobjectsusingblock:^ (thbinder* binder, Nsuinteger idx, BOOL *stop) {[Binder stopbinding]        ;    }];    }]; Objc_setassociatedobject (self, tmbinddictorykey, nil, objc_association_retain_nonatomic);} -(void) Setbinder: (ID) Binder KeyPath: (nsstring*) keypath{nsmutabledictionary* binddict = Objc_getassociatedobject (    Self,tmbinddictorykey);        if (!binddict) {binddict = [nsmutabledictionary new];    Objc_setassociatedobject (self, tmbinddictorykey, binddict, objc_association_retain_nonatomic);    } nsstring* keyName = Bindkey (self, keypath);  ID object = [binddict valueforkey:keyname];      if ([object Containsobject:binder]) {return;    } if (!object) {object = [Nsmutablearray new];    } [Object Addobject:binder];    [Binddict Setvalue:object Forkey:keyname]; Swizzledeallocifneeded (Self.class);} @end



You also need to add a method to the Thbinder so that you can say that the binder is stored in an instance that needs to be observed.


-(ID) Initforbindingfromobject: (ID) fromobject keypath: (NSString *) Fromkeypath Toobject: (ID) toobject K  Eypath: (NSString *) Tokeypath Transformationblock: (thbindertransformationblock) transformationblock{if (self = [Super Init])        {__weak id wtoobject = toobject;                NSString *mytokeypath = [Tokeypath copy];        Thobserverblockwithchangedictionary Changeblock; if (transformationblock) {changeblock = [^ (nsdictionary *change) {[Wtoobject setvalue:transform            Ationblock (Change[nskeyvaluechangenewkey]) Forkeypath:mytokeypath];        } copy]; } else {changeblock = [^ (nsdictionary *change) {[Wtoobject setvalue:change[nskeyvaluechangenew            Key] Forkeypath:mytokeypath];        } copy]; } _observer = [Thobserver observerforobject:fromobject Keypath:fro     Mkeypath                                     Options:nskeyvalueobservingoptionnew Changeblock           : Changeblock]; <span style= "color: #ff0000;" > [Fromobject setbinder:self keypath:fromkeypath];</span>} return self;}

Here, I used the Reactivecocoa inside the macro, to organize the Tmbind macro. It is OK to use this macro as long as it is used. In the Thbinder, the produced binder is automatically placed into the observed instance.

  binder.h//  kvodemo////  Created by Tommy on 14-6-13.//  Copyright (c) 2014 Com.taobao. All rights reserved.//#ifndef kvodemo_binder_h#define kvodemo_binder_h#import "EXTKeyPathCoding.h" #import " THObserver.h "#import" THBinder.h "//one-way bind#define tmbind (_fromobject_,_fromkeypath_,_toobject_,_tokeypath_)     [Thbinder binderfromobject:_fromobject_ keypath: @keypath (_fromobject_, _fromkeypath_) toobject:_toobject_ KeyPath: @keypath (_toobject_,_tokeypath_)] #define Tmbind_with_transformblock (_fromobject_,_fromkeypath_,_ Toobject_,_tokeypath_,_transfromblock_)     [Thbinder binderfromobject:_fromobject_ KeyPath: @keypath (_fromObject _, _fromkeypath_) toobject:_toobject_ keypath: @keypath (_toobject_,_tokeypath_) Transformationblock:_transfromblock _]; #endif





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.