常用的底层语法(objc_get,class_get,_cmd,objc_msgSend)

一,关联 objc_get

1)建立关联:objc_setAssociatedObject;该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略;当源对象销毁,关联的对象也会被销毁

源对象: 即绑定者

关键字: 是一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字

关联的对象: 绑定到源对象身上的对象

关联策略: 表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。这种关联策略是通过使用预先定义好的常量来表示的。OBJC_ASSOCIATION_ASSIGN、OBJC_ASSOCIATION_RETAIN_NONATOMIC、OBJC_ASSOCIATION_COPY_NONATOMIC等

2)获取相关联对象:objc_getAssociatedObject:该函数需要两个参数:源对象,关键字

3)断开关联:断开关联是使用objc_setAssociatedObject函数,传入关联的对象为nil值即可。

使用函数objc_removeAssociatedObjects可以断开所有关联。通常情况下不建议使用这个函数,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。

例子:

static char objKey;

NSArray * array =[[NSArray alloc] initWidthObjects:@"One", @"Two", @"Three", nil];

objc_setAssociatedObject(array, &objKey, @“对象”, OBJC_ASSOCIATION_RETAIN);

NSString * associatedObject = (NSString *)objc_getAssociatedObject(array, &objKey);

二,class_get

1)获得实例方法: Method m1 = class_getInstanceMethod([对象 class], @selector(对象方法));

2)获得类方法: Method m2 = class_getClassMethod([类 class], @selector(类方法));

3)方法互调: method_exchangeImplementations(m1, m2); 即执行方法m1变成执行是m2,执行方法m2变成执行是m1

例子:

  1. Person * p1 = [[Person alloc] init];
  2. Method m1 = class_getInstanceMethod([p1 class], @selector(对象方法));
  3. Method m2 = class_getClassMethod([Person class], @selector(类方法));
  4. NSLog(@"测试前:");
  5. [p1 对象方法];
  6. [Person 类方法];
  7. method_exchangeImplementations(m1, m2);
  8. NSLog(@"测试后:");
  9. [p1 对象方法];
  10. [Person 类方法];

输出:

  1. 2015-11-04 13:37:08.539 02-runtime[2776:69899] 测试前:
  2. 2015-11-04 13:37:08.539 02-runtime[2776:69899] this is a 对象方法 method
  3. 2015-11-04 13:37:08.539 02-runtime[2776:69899] this is a 类方法 method
  4. 2015-11-04 13:37:08.540 02-runtime[2776:69899] 测试后:
  5. 2015-11-04 13:37:08.540 02-runtime[2776:69899] this is a 类方法 method
  6. 2015-11-04 13:37:08.540 02-runtime[2776:69899] this is a 对象方法 method

三,_cmd的用法

_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。NSStringFromSelector(_cmd)得到是方法的名称

例如

static char kExtendVarKey; // 键名

- (void)someCategoryMethod

{

NSString *extendVar = objc_getAssociatedObject(self, &kExtendVarKey);

if(!extendVar){

extendVar = @"someText";

objc_setAssociatedObject(self, &kExtendVarKey, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);

}

}

等同于下面代码

- (void)someCategoryMethod

{

NSString *extendVar = objc_getAssociatedObject(self, _cmd);

if(!extendVar){

extendVar = @"someText";

objc_setAssociatedObject(self, _cmd, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);

}

}

四,objc_msgSend:该函数至少有两个参数:objc_msgSend(消息的接受者, selector, param1, param2, …);

1)概念:其实每个类中都有一张方法列表去存储这个类中有的方法,当发出objc_msgSend方法时候,就会顺着列表去找这个方法是否存在,如果不存在,则向该类的父类继续查找,直到找到位置。如果始终没有找到方法,那么就会进入到消息转发机制;objc_msgSend被分为2个过程:1)在cache中寻找SEL。2)在MethodTable寻找SEL。

例子

id returnValue = [someObject messageName:parameter]; ======》 id returnValue = objc_msgSend(someObject,@selector(messageName),paramter)

Id returnValue = [super messageName:parameter]; ======》 id returnValue = objc_msgSendSuper(someObject,@selector(messageName),paramter)

时间: 2024-10-07 11:02:20

常用的底层语法(objc_get,class_get,_cmd,objc_msgSend)的相关文章

golang: 常用数据类型底层结构分析

虽然golang是用C实现的,并且被称为下一代的C语言,但是golang跟C的差别还是很大的.它定义了一套很丰富的数据类型及数据结构,这些类型和结构或者是直接映射为C的数据类型,或者是用C struct来实现.了解golang的数据类型和数据结构的底层实现,将有助于我们更好的理解golang并写出质量更好的代码. 基础类型 源码在:$GOROOT/src/pkg/runtime/runtime.h .我们先来看下基础类型: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1

grep,awk和sed的常用命令和语法

Grep的常用命令语法 1. 双引号引用和单引号引用在g r e p命令中输入字符串参数时,最好将其用双引号括起来.例如:“m y s t r i n g”.这样做有两个原因,一是以防被误解为 s h e l l命令,二是可以用来查找多个单词组成的字符串,例如:“jet plane”,如果不用双引号将其括起来,那么单词 p l a n e将被误认为是一个文件,查询结果将返回“文件不存在”的错误信息.在调用变量时,也应该使用双引号,诸如: g r e p“$ M Y VA R”文件名,如果不这样,

关系数据库常用SQL语句语法大全

创建表 语法 CREATE TABLE <表名>(<列名> <数据类型>[列级完整性约束条件] [,<列名> <数据类型>[列级完整性约束条件]]…); 列级完整性约束条件有NULL[可为空].NOT NULL[不为空].UNIQUE[唯一],可以组合使用,但是不能重复和对立关系同时存在. 示例 -- 创建学生表 CREATE TABLE Student ( Id INT NOT NULL UNIQUE PRIMARY KEY, Name VAR

常用CSS缩写语法总结

使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.css缩写的主要规则如下: 颜色 16进制的色彩值,如果每两位的值相同,可以缩写一半,例如: #000000可以缩写为#000;#336699可以缩写为#369; 盒尺寸 通常有下面四种书写方法: property:value1; 表示所有边都是一个值value1: property:value1 value2; 表示top和bottom的值是value1,right和left的值是value2 property:value1 value2

STL中常用的c++语法

函数调用操作(c++语法中的左右小括号)可以被重载,STL的特殊版本都以仿函数形式呈现.如果对某个class进行operator()重载,它就成为一个仿函数. #include <iostream> using namespace std; template<class T> struct Plus { T operator()(const T& x, const T& y)const { return x + y; } }; template<class T

PHP流程控制中不常用的替代语法

准备做个wordpress的主题,结果看到了如下的语法: <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <?php if ( is_home() && ! is_

mysql常用基础操作语法(十二)~~常用数值函数【命令行模式】

数值函数是常用函数之一,也是学习mysql必会的,常用的有如下一些: 1.ceil:返回大于某个数的最小整数值: 2.floor:和上一个相反,返回小于某个数的最大整数值: 3.round:返回某个数值四舍五入后的数值: 如上图,round的第二个参数代表需要保留的小数位. 4.truncate:返回某个数值被截断后的数值: 这里与round不同的是,不管需要保留的小数位后边一位是什么都会直接抛弃,同样的第二个参数代表需要保留的小数位. 注:以上的例子中都是整数,但这些函数也可以一样的处理负数.

ORACLE 常用的SQL语法和数据对象

一.数据控制语句 (DML) 部分 1.INSERT (往数据表里插入记录的语句) INSERT INTO 表名(字段名1, 字段名2, ……) VALUES ( 值1, 值2, ……);  INSERT INTO 表名(字段名1, 字段名2, ……) SELECT (字段名1, 字段名2, ……) FROM 另外的表名; 字符串类型的字段值必须用单引号括起来, 例如: ’GOOD DAY’  如果字段值里包含单引号’ 需要进行字符串转换, 我们把它替换成两个单引号''.  字符串类型的字段值超

mysql常用基础操作语法(九)~~外连接查询【命令行模式】

1.左外连接left outer join或者left jion,outer可以省略不写,下边的右连接和全连接也一样: 左外连接的意思是,以left join左边的表中的数据为基准,即左边的表中有的必须要全部显示出来,如下图: 这里第一个查询中,company表在左边,因此就以company为基准,所以显示的结果中除了depart_id相同的6条数据外,还把company中存在的另外一条也显示出来. 而第二个查询中,emp在左边,就以emp为基准,因此显示的结果中除了depart_id相同的6条