Ios Bind binding

Source: Internet
Author: User

Whether using the mvc or mvvm architecture, we need to ensure that model changes can be synchronized to relevant components in a timely manner. Similar to the monthly Observer Model, kvo can be used in ios to accomplish such a thing, but every time this method is used, it will confuse the code. Here THBinder can be used to complete this task on github. At the same time, I have done some processing on this code, so that we can use a simple macro to complete the process. Do not save the THBinder instance.


#import "THBinder.h"#import "THObserver.h"#import 
 
  #import 
  
   #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,swizzleDeallocSelector))                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);}};IMP newDeallocIMP = imp_implementationWithBlock(newDealloc);if (!class_addMethod(classToSwizzle, deallocSelector, newDeallocIMP, "v@:")) {// 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 is called at the time of setting.originalDealloc = (__typeof__(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
  
 



At the same time, you need to add a method to the THBinder so that the binder can be saved to the instance to be observed.


- (id)initForBindingFromObject:(id)fromObject keyPath:(NSString *)fromKeyPath                      toObject:(id)toObject keyPath:(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:transformationBlock(change[NSKeyValueChangeNewKey])                         forKeyPath:myToKeyPath];            } copy];        } else {            changeBlock = [^(NSDictionary *change) {                [wToObject setValue:change[NSKeyValueChangeNewKey]                         forKeyPath:myToKeyPath];            } copy];        }                _observer = [THObserver observerForObject:fromObject                                          keyPath:fromKeyPath                                          options:NSKeyValueObservingOptionNew                                      changeBlock:changeBlock];                [fromObject setBinder:self keyPath:fromKeyPath];    }    return self;}

Here, I used the macro in reactivecocoa to organize the TMBIND macro. In this way, the macro is OK. In THBinder, the generated binder is automatically placed in 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.