《iOS编程实战》读书笔记 24章1.2节

1,方法、属性和协议都存储在类定义的可写字段中,这些信息可以在运行时被改变,这也是分类的实现原理。ivar存储在只读字段,所以不能被修改,这是分类不能添加ivar的原因。

123.png

问题:ivar只读字段被修改了会造成什么情况,有什么方法还原这种情况?

2,查询runtime有关的函数,可以查找文档Objective-C Runtime Reference。

3,打印NSObject能响应的方法列表。

void printObjectMethods(){

  unsigned int count = 0;

  Method *methods = class_copyMethodList([NSObject class], &count);

  for (unsigned int i = 0; i<count; i++) {
    
    SEL sel = method_getName(methods[i]);
    
    const char *name = sel_getName(sel);
    
    printf("%s\n",name);
    
  }

  free(methods);
}

</br>

问题:运行时环境没有引用计数(自动或者手动都没有),所以没有等价的retain或release方法。如果从带有copy的函数得到一个值,就应该调用free。如果用了不到copy单词的函数,千万不要调用free。
(缓冲区的概念还需要理解下)

4,模拟消息分配器机制。

static const void *myMsgSend(id receiver,const char *name){

  SEL selector = sel_registerName(name);

  IMP methodIMP = class_getMethodImplementation(object_getClass(receiver), selector);

  return methodIMP;

}


void RunMyMsgSend(){

  Class class = (Class)objc_getClass("NSObject");

  id object = class_createInstance(class, 0);

  myMsgSend(object, "init");

  id description = (id)myMsgSend(object, "description");

  const char * cstr = myMsgSend(description, "UTF8String");

  printf("%s\n",cstr);


}

问题:
(1)当模拟UTF8String的方法时会崩溃,报野指针。
(2)书中显示:IMP是一个指向某个函数的函数指针,该函数接受一个对象、一个选择器喝一个可变长参数列表,返回一个对象。但是当使用的时候加入参数会报错。

5,在Object-C中可以利用methodForSelector:来使用这种技术,从而避开objc_msgSend这个复杂的消息分派器。如果需要在iPhone上对同一个方法调用几千次,这么做才有意义,而在MAC上,除非调用几百万次,否则看不到性能提升。苹果高度优化了objc_msgSend,但是对于一个调用次数多的建大方法,这么做可以将性能提升5%-10% 。

问题:这种性能提升应该如何测试呢?

6,下面的例子说明如何测试性能。

const NSUInteger kTotalCount = 10000000;

typedef void (*voidImp)(id,SEL,...);

void FastCall(){

  NSMutableString *string = [NSMutableString string];

  NSTimeInterval totalTime = 0;

  NSDate *start = nil;

  NSUInteger count = 0;

  //用objc_msgSend
  start = [NSDate date];

  for (count = 0; count<kTotalCount; count++) {
    
      [string setString:@"stuff"];
  }

  totalTime = -[start timeIntervalSinceNow];

  printf("w/ objc_msgSend = %f\n",totalTime);


  //跳过objc_msgSend
  start = [NSDate date];

  SEL selector = @selector(setString:);

  voidImp setStringMethod = (voidImp)[string methodForSelector:selector];

  for (count = 0; count<kTotalCount; count++) {
    
      setStringMethod(string,selector,@"stuff");
  }

  totalTime = -[start timeIntervalSinceNow];

  printf("w/o objc_msgSend = %f\n",totalTime);

}

总结:
因为IMP返回id,ARC会保留返回值,之后再释放。不过,这个方法什么都没有返回。这个开销会比普通的消息传递系统大,有些情况下多余的retain还会造成崩溃,这就是我们要添加额外的voidIMP的原因。通过把setStringMethod函数指针声明为返回void,编译器就会跳过retain。

问题:
(1)函数指针与指针函数概念是什么?
函数指针:指向函数的指针。
指针函数:返回值是指针的函数。

以下内容来自互联网资料:
在指针函数中,有这样一类函数,它们也返回指针,但是这个指针不是指向int、char之类的基本类型,而是指向函数。比如,下面的语句:

 int (*ff(int))(int *, int);

我们用上面介绍的方法分析一下,ff首先与后面的“()”结合,即:

 int (*(ff(int)))(int *, int);                   // 用括号将ff(int)再括起来

也就意味着,ff是一个函数。
接着与前面的“*”结合,说明ff函数的返回值是一个指针。然后再与后面的“()”结合,也就是说,该指针指向的是一个函数。
一般来说,用typedef关键字会使该声明更简单易懂。

     int (*PF)(int *, int);

也就是说,PF是一个函数指针“变量”。当使用typedef声明后,则PF就成为了一个函数指针“类型”,即:

     typedef int (*PF)(int *, int);

这样就定义了返回值的类型。然后,再用PF作为返回值来声明函数:

     PF ff(int);

在通俗一点,就是可以将函数名直接赋值给函数指针,应该就是让函数指针指向此函数,调用的时候用函数指针调用就可以。

pFunc p_func; //此处定义了一个函数指针
p_func = count1; //把count1函数的地址赋值给p_func
int count1(char *p) {
 ...
}

(2)代码中进行了voidIMP强制转换,这个还是有点模糊。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,284评论 0 6
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,678评论 0 9
  • “这个世界” ——重新学习笑来老师《通往财富自由之路》笔记专题(15) 一、讲了什么 这篇文章打磨的概念是“这个世...
    从零再次起步阅读 115评论 0 0
  • 老妈今年七十岁了,去年末听闻自己患癌也好是纠结挣扎了一番。 多亏我家女人生性耐操。 手术、化疗,几番折腾后,老太太...
    止末阅读 492评论 0 2
  • 牵心时务人堪困,一段清宵梦里长。 枕绕余音随旧曲,夜来风露发新霜。 匀妆浅黛烧心字,翠帐红帷笼玉香。 殷勤总望蓬山...
    平生恨阅读 109评论 0 1