深入理解Objective-C:Category

2018-09-29  本文已影响12人  sajiner

category简介

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};

即category的底层其实就是一个结构体,里边有类名、类、实例方法、类方法、协议信息、属性信息

Category的加载处理过程

源码层面分析

void _objc_init(void)
{
    static bool initialized = false;
    if (initialized) return;
    initialized = true;
    
    // fixme defer initialization until an objc-using image is found?
    environ_init();
    tls_init();
    static_init();
    lock_init();
    exception_init();

    _dyld_objc_notify_register(&map_images, load_images, unmap_image);
}
void
map_images(unsigned count, const char * const paths[],
           const struct mach_header * const mhdrs[])
{
    rwlock_writer_t lock(runtimeLock);
    return map_images_nolock(count, paths, mhdrs);
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)test1;
@end


#import "Person.h"
@interface Person (Test1) 
- (void)test1;
@end

/// 在main.m文件中
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Person+Test1.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        [person test1]; /// 此句调用的是 Person+Test1 文件中的 test1 方法
    }
    return 0;
}

Category中的+load方法

源码分析+load方法的加载过程
static void schedule_class_load(Class cls)
{
    if (!cls) return;
    assert(cls->isRealized());  // _read_images should realize

    if (cls->data()->flags & RW_LOADED) return;

    // Ensure superclass-first ordering
    schedule_class_load(cls->superclass);

    add_class_to_loadable_list(cls);
    cls->setInfo(RW_LOADED); 
}

Category中的+initinitialize方法

void _class_initialize(Class cls)
{
    Class supercls;
    bool reallyInitialize = NO;
    // Make sure super is done initializing BEFORE beginning to initialize cls.
    // See note about deadlock above.
    supercls = cls->superclass;
    if (supercls  &&  !supercls->isInitialized()) {
        _class_initialize(supercls);
    }
 }

+load和+initialize的区别

关联对象

void objc_setAssociatedObject(id object, const void * key,
                                id value, objc_AssociationPolicy policy)

2> 获得关联对象

id objc_getAssociatedObject(id object, const void * key)

1> 移除所有的关联对象

void objc_removeAssociatedObjects(id object)
上一篇 下一篇

猜你喜欢

热点阅读