Objective-C 对象

Objective-C 对象模型

首先要了解一下Objective-C中关于类和对象的定义,Cocoa中大部分对象都是NSObject的子类(NSProxy是一个例外),继承了NSObject的方法。NSObject定义如下:

@interface NSObject <NSObject> 
{
    Classisa;
}

NSObject可见一个对象的内存布局中第一个元素是指向类结构Class的isa指针。Class类结构定义如下:

typedef struct objc_class *Class;
typedef struct objc_object
{
    Class isa;
} *id;

Class 是类结构体的别名,而id是一个objc_object对象结构体指针,objc_object内存布局中第一个元素是指向objc_class类结构体的指针。所以id可以指向任何内存布局以objc_class类结构体指针开始的对象。类结构体objc_class定义具体如下:

struct objc_class 
{
    Class isa;
    Class super_class                                        
    const char *name                                         
    long version                                             
    long info                                                
    long instance_size                                       
    struct objc_ivar_list *ivars                             
    struct objc_method_list **methodLists                    
    struct objc_cache *cache                                 
    struct objc_protocol_list *protocols                     
}

objc_class类结构体的各成员介绍如下:

isa:是一个类结构体objc_class的指针。内存以objc_class为开始的数据类型对当做对象来看待,所以说类也是对象,普通的对象叫实例对象而类叫做类对象,类对象的isa指针指向的类叫做metaclass(元类)元类也是一个对象,元类的isa指向rootmetaclass(根元类), 根元类的isa指向本身,这样就成了一个闭环。类对象存储普通成员变量和普通方法,metaclass存储静态成员变量和静态方法,也就是类变量和类方法。

super_class: 指向父类的指针。类对象和元类对象有着同样的继承关系。关于继承和isa的关系如这篇文章所示。

name: C常量字符串,表示类的名字。可以在运行期,通过这个名称查找到该类例如id objc_getClass(constchar *aClassName)或该类的元类id objc_getMetaClass(const char*aClassName)。

version: 类版本信息。可以在运行期对其进行修改(class_setVersion)或获取(class_getVersion)。

info: 运行期使用的一些表示位。

CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含实例方法和变量;

CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;

CLS_INITIALIZED(0x4L) 表示该类已经被运行期初始化了,这个标识位只被objc_addClass 所设置;

CLS_POSING (0x8L) 表示该类被 pose 成其他的类;(poseclass 在ObjC 2.0中被废弃了);

CLS_MAPPED (0x10L)为ObjC运行期所使用

CLS_FLUSH_CACHE(0x20L) 为ObjC运行期所使用

CLS_GROW_CACHE(0x40L) 为ObjC运行期所使用

CLS_NEED_BIND(0x80L) 为ObjC运行期所使用

CLS_METHOD_ARRAY(0x100L) 该标志位指示 methodlists 是指向一个 objc_method_list 还是一个包含 objc_method_list 指针的数组,methodlists指向指针的数组的意义是方便以Category的形式添加方法。

instance_size: 该类的实例变量大小(包括从父类继承下来的实例变量)。

ivars: 指向 objc_ivar_list 的指针,存储每个实例变量的内存地址,如果该类没有任何实例变量则为 NULL

methodLists: 与 info 的一些标志位有关,CLS_METHOD_ARRAY标识位决定其指向的东西(是指向单个objc_method_list还是一个 objc_method_list 指针数组),如果 info 设置了 CLS_CLASS 则 objc_method_list  存储实例方法,如果设置的是 CLS_META 则存储类方法。

cache:指向objc_cache的指针,用来缓存最近使用的方法,以提高方法调用过程中的查找速度。

protocols: 指向 objc_protocol_list 的指针,存储该类声明要遵守的正式协议。

动态添加属性(isa swizzling)

动态的添加属性主要在Category通过以下两个方法使两个对象关联起来。

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

关联策略policy有:

enum 
{
    OBJC_ASSOCIATION_ASSIGN = 0,
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
    OBJC_ASSOCIATION_RETAIN = 01401,
    OBJC_ASSOCIATION_COPY = 01403
};

具体例子如下:

#import <Foundation/Foundation.h>
#include <objc/runtime.h>
static const void *objectName = @"objectName";
@interface NSObject (Test)
@property (nonatomic, strong) NSString *objectName;
@end
@implementation NSObject (Test)
- (NSString *)objectName
{
    return objc_getAssociatedObject(self, objectName);
}
- (void)setObjectName:(NSString *)name
{
    objc_setAssociatedObject(self, objectName, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
int main (int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSObject *object = [[NSObject alloc] init];
        [object setObjectName:@"ObjectName"];
        NSLog(@"%@",object.objectName);
        [object release];
    }
    return 0;
}

Method Swizzling

Method Swizzling可以搞定一件事情,那就是可以不通过继承来重写某个方法。而且还可以调用原来的方法。通常的做法是在category中添加一个方法(当然也可以是一个全新的class)。可以通过method_exchangeImplementations这个运行时方法来交换实现。示例如下:

#import  <objc/runtime.h>
@interface NSMutableArray (LoggingAddObject)
- (void)logAddObject:(id)aObject;
@end
@implementation NSMutableArray (LoggingAddObject)
+ (void)load
{
    Method addobject = class_getInstanceMethod(self, @selector(addObject:));
    Method logAddobject = class_getInstanceMethod(self, @selector(logAddObject:));
    method_exchangeImplementations(addObject, logAddObject);
}
- (void)logAddObject:(id)aobject
{
    [self logAddObject:aObject];
    NSLog(@"Added object %@ to array %@", aObject, self);
}
@end
时间: 2024-12-19 03:03:23

Objective-C 对象的相关文章

Objective C block背后的黑魔法

前言 block在Objective C开发中应用非常广泛,我们知道block会捕获外部对象,也知道使用block要防止循环引用. "知其然而不知其所以然"是一件很痛苦的事情,那么block这套机制在OC中是如何实现的呢?本文通过从C/C++到汇编层面分析block的实现原理. Clang clang是XCode的编译器前端,编译器前端负责语法分析,语义分析,生成中间代码(intermediate representation ). 比如当你在XCode中进行build一个.m文件的时

Objective C ARC 使用及原理

手把手教你ARC ,里面介绍了ARC的一些特性, 还有将非ARC工程转换成ARC工程的方法 ARC 苹果官方文档 下面用我自己的话介绍一下ARC,并将看文档过程中的疑问和答案写下来.下面有些是翻译,但不是全部,请一定要看一遍官方文档 不考虑 iOS4 的 ARC 规则 简单地说,ARC在编译时刻为代码在合适的位置加上retain 和 release. 复杂点,它还提供其它一些功能,还为解决一些问题,添加了一些关键字和功能,后面会说. ARC强制要求的新规则 不可以调用dealloc, 不可以实现

Objective - c Foundation 框架详解2

Objective - c  Foundation 框架详解2 Collection Agency Cocoa provides a number of collection classes such as NSArray and NSDictionary whose instances exist just to hold onto other objects. cocoa 提供了一系列的集合类,例如,NSarray,NSdictionary.它们存在的目的就是为了保持其他对象. 1.1.1N

Block 简介

1.Blocks简介 Block字面意思就是代码块 iOS4.0.Mac OS X 10.6开始Apple引入的特性 Block是Objective C语言中的对象 但是与NSObject有所区别 Block是特殊的Objective C对象 Block 对象提供了一个使用 C 语言和 C 派生语言(如 Objective-C 和 C++)来创建表达式作为一个特别的函数.在其他语言和环境中,一个block对象有时候被称为“闭包(closure)”.在这里,它们通常被口语化为”块(blocks)”

动态方法决议 和 消息转发

如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 对应的 IMP:这个是需要对类对象的结构熟悉,不清楚的可以参考我的下一篇文章<object-c 类结构解析>,如果没有找到且实现了动态方法决议机制就会进行决议,如果没有实现动态方法决议机制或决

IOS升级之 Objective-c新特性

采用现代objective - c 来源:http://www.cnblogs.com/chensheng12330/p/3950004.html 多年来,objective - c语言已经发展和演变. 虽然核心概念和实践保持不变,部分语言经历了重大的变化和改进. 这些现代化提高类型安全.内存管理.性能.和其他方面的objective - c,使你更容易编写正确的代码. 采用这些变化是很重要的在你的现有的和未来的代码来帮助它变得更加一致的,可读的,有弹性. Xcode提供了一个工具来帮助使你的一

Objective-C 学习记录4

字符串的一些方法使用: 1.创建字典的NSString可变字符串,和NSMutableString不可变字符串.都是objective的对象. char *str是字母数组. 2.字符串格式化:stringWithFormat,,格式化任何int,char double,float等的内型. 3.stringWithString字符串赋值和这个类似, NSString *str = @"我就是我!"; 4.字符串转化为UTF-8的格式 stringWithUTF8String 5.两个

Objc基础学习记录3

在学习Objective-c中, 数组 1.NSArray, 这是一个不可变的数组,不能修改和删除其中的对象,可以存储任意objective的对象指针. 不能存储int,char类型的,,需要转换为需要的类型. 要快速枚举数组中的值,用in. 1 for (NSString *eleement in myArray) 2 NSLog(@"myArray is %@",element); 2.NSMutableArray 这是一个可变的数组,可以向其中添加和删除对象. a.添加addOb

关于iOS中的kvo错误 _NSSetObjectValueAndNotify

Foundation`_NSSetObjectValueAndNotify: ... 0x116156dfb <+27>:  callq  0x116340498               ; symbol stub for: object_getClass 0x116156e00 <+32>:  movq   %rax, %rdi 0x116156e03 <+35>:  callq  0x1163404a4               ; symbol stub f

c语言和oc对比

1)源文件对比 思考&实现1: 1)在C语言中,我们遇到不同后缀的文件有哪些? .c .o .out .h 2.基本语法对比 1)数据类型对比学习 2)变量的定义对比 3)流程控制语句对比 1)if else 2)switch 3)while 4)do while 5)for 新增:增强型for循环,可以快速遍历数组.字典等集合 4)函数(方法)定义和声明对比 C语言中函数的声明和实现 i.函数声明: int sum(int a,int b); ii.函数定义 int sum(int a,int