iOS

@(03.自己的笔记)[iOS]

[TOC]

iOS

Runtime

OC_runtime运行时官方文档翻译

NSObject

isa

struct NSObject{  
   Class isa;  
 } 
 
typedef struct objc_class *Class; 
 
struct objc_class {  
     Class isa; 
     Class super_class;
    /* followed by runtime specific details... */ 
 }  

因此,一个实例对象有四个层次:
实例对象->对象的类->元类->NSObject对象

  • isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类(Class),而对象的类里也有个isa的指针, 指向meteClass(元类)元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环。
  • 对象的类结构存储类的普通成员变量与普通成员方法(-开头的方法).
  • metaclass 存储类的static类成员变量与static类成员方法(+开头的方法)

为什么有元类

因为可以给类发送消息,因此,类也是一个对象,为了调用类里的方法,类的isa指针必须指向包含这些类方法的类结构体。
这就引出了元类的定义:元类是类对象的类。
简单说就是:

  • 当你给对象发送消息时,消息是在寻找这个对象的类的方法列表。
  • 当你给类发消息时,消息是在寻找这个类的元类的方法列表。

下面举一个例子:



图中可以看出,D3继承D2,D2继承D1,D1最终继承NSObject。下图从D3的一个对象开始,排列出D3 D2 D1 NSObject 类对象,元类对象等关系。


SEL

SEL数据结构如下:

typedef struct objc_selector *SEL;
struct objc_selector 实际上不存在,是为了让SEL的值与字符串无法直接比较,从而隐藏实现的细节。

其实它就是映射到方法的C字符串,你可以通过Objc编译器命令@selector()或者Runtime系统的sel_registerName函数来获取一个SEL类型的方法选择器。
如果你知道selector对应的方法名是什么,可以通过NSString* NSStringFromSelector(SEL aSelector)方法将SEL转化为字符串,再用NSLog打印。

objc-sel.mm

static SEL __sel_registerName(const char *name, int lock, int copy) 
{
    SEL result = 0;
//1.检查锁:有锁->assert未锁,没有锁->assert资源正在写

    if (lock) selLock.assertUnlocked();
    else selLock.assertWriting();

    if (!name) return (SEL)0;

//2.检查buildins中是否有name对应的SEL

    result = search_builtins(name);
    if (result) return result;
    
//3.检查NXMap中是否有name对应的SEL

    if (lock) selLock.read();
    if (namedSelectors) {
        result = (SEL)NXMapGet(namedSelectors, name);
    }
    if (lock) selLock.unlockRead();
    if (result) return result;

//4.在NXMap中通过name创建SEL(写时加锁)
    // No match. Insert.
    if (lock) selLock.write();

    if (!namedSelectors) {
        namedSelectors = NXCreateMapTable(NXStrValueMapPrototype, 
                                          (unsigned)SelrefCount);
    }
    if (lock) {
        // Rescan in case it was added while we dropped the lock
        result = (SEL)NXMapGet(namedSelectors, name);
    }
    if (!result) {
        result = sel_alloc(name, copy);
        // fixme choose a better container (hash not map for starters)
        NXMapInsert(namedSelectors, sel_getName(result), result);
    }

    if (lock) selLock.unlockWrite();
    return result;
}
const char *sel_getName(SEL sel) 
{
//很直白的告诉了我们SEL本质就是一个const char *
    if (!sel) return "";
    return (const char *)(const void*)sel;
}

Objective-C

设计模式

架构

项目

XMPP

你可能感兴趣的:(iOS)