ios Bind绑定
来源:互联网 发布:sql中查询重复的数据 编辑:程序博客网 时间:2024/05/22 08:22
不管是用mvc还是mvvm的架构,我们都需要一点就是model的改变能够及时同步到相关部件中。就类似月观察者模型,在ios中可以通过kvo来完成这样的事情,但是每次都是用这个样的方式,就回让代码混乱。在这里可以采用THBinder在github来完成这个任务。同时我对这个代码进行了一点处理,这样就使用一个简单的宏来完成,不要保存THBinder实例了。
#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,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
- (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]; <span style="color:#ff0000;"> [fromObject setBinder:self keyPath:fromKeyPath];</span> } 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
0 0
- ios Bind绑定
- bind绑定
- WinSock 绑定(bind())问题?
- jquery bind绑定
- boost::bind 函数绑定
- boost bind 绑定器
- linux socket bind绑定
- 参数绑定bind
- jquery bind的绑定
- bind参数绑定
- 参数绑定bind
- bind函数绑定
- bind函数绑定
- v-bind style绑定
- WPF Bind 绑定
- C++ bind参数绑定
- data-bind 绑定
- Javascript-bind绑定函数
- JVMS Specification(2)-Compiling for the Java Virtual Machine
- Animation Timing
- redmine Gantt 無法轉pdf
- JSP内置对象之四个作用域
- 常见排序算法总结
- ios Bind绑定
- Objective-c的@property 详解
- 大神博客
- SQLSERVER复制优化之一《改变包大小》
- 数据库原理中基本的数据库范式
- 32个重要的算法
- WSAStartup的版本选择问题
- django--将你的Models加入到Admin管理中
- 旋转卡壳(卡尺)算法