ios Bind綁定

來源:互聯網
上載者:User

不管是用mvc還是mvvm的架構,我們都需要一點就是model的改變能夠及時同步到相關組件中。就類似月觀察者模型,在ios中可以通過kvo來完成這樣的事情,但是每次都是用這個樣的方式,就回讓代碼混亂。在這裡可以採用THBinder在github來完成這個任務。同時我對這個代碼進行了一點處理,這樣就使用一個簡單的宏來完成,不要儲存THBinder執行個體了。


#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



同時需要在THBinder裡面加入一個方法,這樣就可以講binder儲存到需要被觀察的執行個體裡面。


- (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;}

在這裡,我用了reactivecocoa裡面的宏,來組織了這個TMBIND宏。這樣使用的時候就只要這個宏就ok了。在THBinder裡面會將生產的binder自動放到被觀察的執行個體裡面了。

////  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





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.