标签:
以forkingdog的PorotocolKit举例
ProtocolKit Protocol extension for Objective-C Usage Your protocol: @protocol Forkable <NSObject> @optional - (void)fork; @required - (NSString *)github; @end Protocol extension, add default implementation, use @defs magic keyword @defs(Forkable) - (void)fork { NSLog(@"Forkable protocol extension: I‘m forking (%@).", self.github); } - (NSString *)github { return @"This is a required method, concrete class must override me."; } @end Your concrete class @interface Forkingdog : NSObject <Forkable> @end @implementation Forkingdog - (NSString *)github { return @"https://github.com/forkingdog"; } @end Run test [[Forkingdog new] fork]; Result [Console] Forkable protocol extension: I‘m forking (https://github.com/forkingdog).
我们可以看到关键字是@def 查看其定义是
// For a magic reserved keyword color, use @defs(your_protocol_name) #define defs _pk_extension // Interface #define _pk_extension($protocol) _pk_extension_imp($protocol, _pk_get_container_class($protocol)) // Implementation #define _pk_extension_imp($protocol, $container_class) protocol $protocol; @interface $container_class : NSObject <$protocol> @end @implementation $container_class + (void)load { _pk_extension_load(@protocol($protocol), $container_class.class); } // Get container class name by counter #define _pk_get_container_class($protocol) _pk_get_container_class_imp($protocol, __COUNTER__) #define _pk_get_container_class_imp($protocol, $counter) _pk_get_container_class_imp_concat(__PKContainer_, $protocol, $counter) #define _pk_get_container_class_imp_concat($a, $b, $c) $a ## $b ## _ ## $c
转化为oc语言定义就是
@protocol Forkable; @interface __PKContainer_Forkable_0 : NSObject <Forkable> @end @implementation __PKContainer_Forkable_0 @synthesize title = _title; + (void)load { //add protocol class method? _pk_extension_load(@protocol(Forkable), __PKContainer_Forkable_0.class); } -(NSString *)title { if (!_title) { _title = @"default title!"; } return _title; } - (void)fork { NSLog(@"Forkable protocol extension: I‘m forking (%@).", self.github); } - (NSString *)github { return @"This is a required method, concrete class must override me."; } @end
从这可以看出关键的代码 _pk_extension_load()
可以猜想其定义是
1 在load里注册自己包含那些扩展协议
2 在c方法里遍历所有的类 把有扩展的 方法的实现指过去
现在查看其函数实现 关键代码如下
__attribute__((constructor)) static void _pk_extension_inject_entry(void) { pthread_mutex_lock(&protocolsLoadingLock); unsigned classCount = 0; Class *allClasses = objc_copyClassList(&classCount); @autoreleasepool { for (unsigned protocolIndex = 0; protocolIndex < extendedProtcolCount; ++protocolIndex) { PKExtendedProtocol extendedProtcol = allExtendedProtocols[protocolIndex]; for (unsigned classIndex = 0; classIndex < classCount; ++classIndex) { Class class = allClasses[classIndex]; if (!class_conformsToProtocol(class, extendedProtcol.protocol)) { continue; } _pk_extension_inject_class(class, extendedProtcol); } } } pthread_mutex_unlock(&protocolsLoadingLock); free(allClasses); free(allExtendedProtocols); extendedProtcolCount = 0, extendedProtcolCapacity = 0; }
//将协议的方法添加到到类中(如果不存在就不添加了)//包括类方法和实例方法 static void _pk_extension_inject_class(Class targetClass, PKExtendedProtocol extendedProtocol) { for (unsigned methodIndex = 0; methodIndex < extendedProtocol.instanceMethodCount; ++methodIndex) { Method method = extendedProtocol.instanceMethods[methodIndex]; SEL selector = method_getName(method); if (class_getInstanceMethod(targetClass, selector)) { continue; } IMP imp = method_getImplementation(method); const char *types = method_getTypeEncoding(method); class_addMethod(targetClass, selector, imp, types); } Class targetMetaClass = object_getClass(targetClass); for (unsigned methodIndex = 0; methodIndex < extendedProtocol.classMethodCount; ++methodIndex) { Method method = extendedProtocol.classMethods[methodIndex]; SEL selector = method_getName(method); if (selector == @selector(load) || selector == @selector(initialize)) { continue; } if (class_getInstanceMethod(targetMetaClass, selector)) { continue; } IMP imp = method_getImplementation(method); const char *types = method_getTypeEncoding(method); class_addMethod(targetMetaClass, selector, imp, types); } }
由此可知猜想是正确的,方法告诉我们对于某一个含有该协议的类,如果其含有了协议里面的函数,则跳过,如果没有该函数就添加。
这里是下载地址
标签:
原文地址:http://www.cnblogs.com/nonato/p/4874246.html