转载请注明出处。
本文是接着上一篇博客iOS---学习研究大牛Git高星项目YYCategories(一)
三、YYCategoriesMacro.h
一个宏定义类,我会把这一块的功能说一下。
tip1:
Q : 在项目的 .h 文件中,
#ifndef XXX_h
#define XXX_h
//程序段1
#endif  /* XXX_h */
的作用?A : 如果 XXX.h 不存在,就引入 XXX.h ,否则不用引入. 是为了防止该文件被重复引用.#什么是重复引用:
其实“被重复引用”是指一个头文件在同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的。比如:存在a.h文件#include "c.h"而此时b.cpp文件导入了#include "a.h" 和#include "c.h"此时就会造成c.h重复引用。#头文件被重复引用引起的后果:
有些头文件重复引用只是增加了编译工作的工作量,不会引起太大的问题,仅仅是编译效率低一些,但是对于大工程而言编译效率低下那将是一件多么痛苦的事情。
有些头文件重复包含,会引起错误,比如在头文件中定义了全局变量(虽然这种方式不被推荐,但确实是C规范允许的)这种会引起重复定义。

扩展:
Q : #if , #ifdef , #ifndef 的使用方法?A : #1,#2,#3.#1
#if condition(表达式1)
//程序段1
(#elif condition(表达式n)
//程序段n
)
...
(#else
//程序段3
)
#endif
说明 : 如果 表达式1(condition : true),则执行 程序段1,(否则如果 表达式2(condition : true),则执行 程序段n),(否则执行 程序段3). #2 #ifdef macro(标识符1) //程序段1 (#else //程序段2 ) #endif 说明 : 如果 有定义标识符1(#define macro),则执行 程序段1,(否则执行 程序段2). #3 #ifndef macro(标识符1) //程序段1 (#else //程序段2 ) #endif 说明 : 如果 没有定义标识符1(#define macro),则执行 程序段1,(否则执行 程序段2).与#2相反!

详细请看:Objective-C预编译处理

tip2:

#ifdef __cplusplus
#define YY_EXTERN_C_BEGIN  extern "C" {#define YY_EXTERN_C_END  }
#else
#define YY_EXTERN_C_BEGIN#define YY_EXTERN_C_END/*
功能在C++环境中有定义 __cplusplus 这个宏,如果在C++环境中, YY_EXTERN_C_BEGIN和 YY_EXTERN_C_END中间的代码,编译器用C语言的编译格式来编译.因为 C++ 为了实现函数重载会把函数名和参数等联合起来合成一个中介的函数名,如果 C 函数也被这样编译会出问题.*/

tip3:

/**Add this macro before each category implementation, so we don't have to use-all_load or -force_load to load object files from static libraries that onlycontain categories and no classes.More info: http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html .*******************************************************************************Example:YYSYNTH_DUMMY_CLASS(NSString_YYAdd)*/
#ifndef YYSYNTH_DUMMY_CLASS
#define YYSYNTH_DUMMY_CLASS(_name_) \
@interface YYSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation YYSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif

这个宏定义的功能上面已经讲得很清楚了。在每个类别实现之前添加这个宏,这样我们就不必使用-all_load或-force_load来从只包含类别而不包含类的静态库加载对象文件。

在用第三方库、类或者静态库时,我们常常在Xcode的Build Settings下Other Linker Flags里面加入-ObjC标志。

原因:

Unix的标准静态库实现和Objective-C的动态特性之间有一些冲突:Objective-C没有为每个函数(或者方法)定义链接符号,它只为每个类创建链接符号。这样当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来,就会导致你调用类别中的方法时,出现"selector not recognized",也就是找不到方法定义的错误。为了解决这个问题,引入了-ObjC标志,它的作用就是将静态库中所有的和对象相关的文件都加载进来。

不要以为这样就可以解决所有问题了,在64位的Mac系统或者iOS系统下,链接器有一个bug,会导致只包含有类别的静态库无法使用-ObjC标志来加载文件。变通方法是使用-all_load 或者-force_load标志,它们的作用都是加载静态库中所有文件,不过all_load作用于所有的库,而-force_load后面必须要指定具体的文件他们加载的位置也是在Xcode的Build Settings下Other Linker Flags里面。

所以一般加了这两个的都是存在一些扩展类。

只要加入了这个宏定义我们就不需要在添加这两个方法了。

使用方法:
YYSYNTH_DUMMY_CLASS(NSArray_YYAdd)

tip4:

/**Synthsize a dynamic object property in @implementation scope.It allows us to add custom properties to existing classes in categories.@param association  ASSIGN / RETAIN / COPY / RETAIN_NONATOMIC / COPY_NONATOMIC@warning #import <objc/runtime.h>*******************************************************************************Example:@interface NSObject (MyAdd)@property (nonatomic, retain) UIColor *myColor;@end#import <objc/runtime.h>@implementation NSObject (MyAdd)YYSYNTH_DYNAMIC_PROPERTY_OBJECT(myColor, setMyColor, RETAIN, UIColor *)@end*/
#ifndef YYSYNTH_DYNAMIC_PROPERTY_OBJECT
#define YYSYNTH_DYNAMIC_PROPERTY_OBJECT(_getter_, _setter_, _association_, _type_) \
- (void)_setter_ : (_type_)object { \[self willChangeValueForKey:@#_getter_]; \objc_setAssociatedObject(self, _cmd, object, OBJC_ASSOCIATION_ ## _association_); \[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \return objc_getAssociatedObject(self, @selector(_setter_:)); \
}
#endif

这是一个给category 动态添加属性的宏。

使用方法:

.h中
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>#ifndef YYSYNTH_DYNAMIC_PROPERTY_OBJECT
#define YYSYNTH_DYNAMIC_PROPERTY_OBJECT(_getter_, _setter_, _association_, _type_) \
- (void)_setter_ : (_type_)object { \
[self willChangeValueForKey:@#_getter_]; \
objc_setAssociatedObject(self, _cmd, object, OBJC_ASSOCIATION_ ## _association_); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \
return objc_getAssociatedObject(self, @selector(_setter_:)); \
}
#endif@interface NSObject (MyAdd)@property (nonatomic, retain) NSString *myName;@end.m中
#import "NSObject+MyAdd.h"
#import <objc/runtime.h>@implementation NSObject (MyAdd)YYSYNTH_DYNAMIC_PROPERTY_OBJECT(myName, setMyName, RETAIN, NSString *);@end

效果如图

这样就可以为扩展类添加属性了。

参考链接:学习yykit 一些小小总结

tip5:

/**Synthsize a dynamic c type property in @implementation scope.It allows us to add custom properties to existing classes in categories.@warning #import <objc/runtime.h>*******************************************************************************Example:@interface NSObject (MyAdd)@property (nonatomic, retain) CGPoint myPoint;@end#import <objc/runtime.h>@implementation NSObject (MyAdd)YYSYNTH_DYNAMIC_PROPERTY_CTYPE(myPoint, setMyPoint, CGPoint)@end*/
#ifndef YYSYNTH_DYNAMIC_PROPERTY_CTYPE
#define YYSYNTH_DYNAMIC_PROPERTY_CTYPE(_getter_, _setter_, _type_) \
- (void)_setter_ : (_type_)object { \[self willChangeValueForKey:@#_getter_]; \NSValue *value = [NSValue value:&object withObjCType:@encode(_type_)]; \objc_setAssociatedObject(self, _cmd, value, OBJC_ASSOCIATION_RETAIN); \[self didChangeValueForKey:@#_getter_]; \
} \
- (type)_getter_ { \_type_ cValue = { 0 }; \NSValue *value = objc_getAssociatedObject(self, @selector(_setter_:)); \[value getValue:&cValue]; \return cValue; \
}
#endif

这是一个添加c类型属性的宏。和上面类似。

转载于:https://www.cnblogs.com/weicyNo-1/p/9208872.html

iOS---学习研究大牛Git高星项目YYCategories(二)相关推荐

  1. iOS---学习研究大牛Git高星项目YYCategories(三)

    转载请注明出处!!! 本文是接着上一篇博客iOS---学习研究大牛Git高星项目YYCategories(二) 大神果真是大神,一个简单的宏定义类,就有如此多的需要注意的地方.在一篇文章中写篇幅过长就 ...

  2. iOS---学习研究大牛Git高星项目YYCategories(一)

    转载请注明出处!!!  进行iOS开发已经很久了,但是一直没有静下心研究Git上一些大神写的优秀工程.现在下定决心开始从零开始,仔细研读并敲写一遍大神工程.首先我准备研究的是 ibireme 大神的Y ...

  3. 出处大神git_iOS---学习研究大牛Git高星项目YYCategories(一)

    进行iOS开发已经很久了,但是一直没有静下心研究Git上一些大神写的优秀工程.现在下定决心开始从零开始,仔细研读并敲写一遍大神工程.首先我准备研究的是 ibireme 大神的YYKit工程.这个工程比 ...

  4. iOS---学习研究大牛Git高星项目YYCategories(四)

    今天开始研究YYCategories的Foundation扩展类. 它包含了作者对14个Foundation框架的扩展.在详细研究每一个扩展类前我发现了一个小知识点. NS_ASSUME_NONNUL ...

  5. 年度盘点!必看AI顶会论文、Github高星项目大合集(附链接)

    目前,国外计算机界评价学术水平主要是看在顶级学术会议上发表的论文,特别是在机器学习.计算机视觉和人工智能领域,顶级会议才是王道.本期我们盘点了2019年人工智能领域的顶会,如最核心的顶会AAAI.IJ ...

  6. 独家 | 年度盘点!必看AI顶会论文、Github高星项目大合集(附链接)

    目前,国外计算机界评价学术水平主要是看在顶级学术会议上发表的论文,特别是在机器学习.计算机视觉和人工智能领域,顶级会议才是王道.本期我们盘点了2019年人工智能领域的顶会,如最核心的顶会AAAI.IJ ...

  7. Git学习系列之Git基本操作提交项目(图文详解)

    前面博客 Git学习系列之Git基本操作克隆项目(图文详解) 然后可以 cd 切换到 LispGentleIntro 目录, 新增或者修改某些文件.这里只是模拟一下操作, 实际情况可能是 使用 Ecl ...

  8. 过万 star 高星项目的秘密——GitHub 热点速览 Vol.39

    作者:HelloGitHub-小鱼干 虽然国外十一并不过国庆,但是本周的 GitHub 也稍显疲软,GitHub 周榜的获 star 超过 1k 的项目寥寥无几,本周新开源的项目更是屈指可数.用 C ...

  9. Git学习系列之Git基本操作克隆项目(图文详解)

    不多说,直接上干货! 想必,能进来看我写的这篇博文的朋友,肯定是了解过. 比如SVN的操作吧,最常见的是 检出(Check out ...), 更新 (Update ...), 以及 提交(Commi ...

最新文章

  1. Java反射原理剖析一
  2. mysql root 提权_mysql以ROOT权限提权方法
  3. [C/C++] C++声明和定义的区别
  4. sass和compass基础用法
  5. jq上传file到php,jQuery文件上传
  6. ubuntu的mysql教程 pdf_Ubuntu上的MySQL字符集设置技巧
  7. js中比较到期时间和当前时间
  8. Ripple 20:严重漏洞影响全球数十亿IoT设备,复杂软件供应链使修复难上加难
  9. ajax请求传递参数的方式,Ajax请求 一般处理程序参数传递的几种方式
  10. 原创 | 混沌工程(Chaos Engineering)初识
  11. 【Unity 资源分享】☀️ | Unity 华丽炫酷特效资源分享!万年魂环拿到手软,让你直达封号斗罗~
  12. k3 设置 虚拟服务器,金蝶k3远程服务器设置
  13. RIGHT-BICEP单元测试——“二柱子四则运算升级版”
  14. 2.2 华为-软件工程师-7.21笔试题
  15. USRP B210驱动安装
  16. Blender建模笔记 | 大帅老猿threejs特训
  17. 二叉树遍历(非递归)
  18. “没有40K当什么程序员?”
  19. 一心多用多线程-线程创建的三种方式
  20. G. The Galactic Olympics

热门文章

  1. OP_PUSH_TX技术背后的故事
  2. android高德地图轨迹纠偏,RoutePath-(高德地图)根据定位点绘制路线+轨迹纠偏
  3. mysql联合查询注入防护,SQL注入之BypassWaf
  4. ubuntu清理缓存
  5. 硅谷的程序员, 入职第一天都在干什么?
  6. 如何快速打造强势品牌?
  7. 计算机辅助设计绘图员四级,计算机辅助设计绘图员-标准及考试大纲.pdf
  8. java窗体背景图片_java 窗体设置背景图片问题 (附上登陆界面代码,我想加个背景图...
  9. 华为任正飞关于“活下去”的呼声不断刷屏,《Android市场寒气十足,该如何存活》?
  10. 普通人最缺乏的深度思考能力,该如何培养?