自定义宏
- 处理NSLog事件(开发者模式打印,发布者模式不打印)
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr, "[%s(%d):%s]\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __func__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(FORMAT, ...) nil
#endif
- 只在OC语言的情况下引用
// 保证 #ifdef 中的内容只会在 ObjectivObjective-C,在 C/C++ 代码中不会被引用
#ifdef __OBJC__
// 定义宏或导入头文件
#endif
- 判断当前的iPhone设备/系统版本
//判断是否为iPhone
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
//判断是否为iPad
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//判断是否为ipod
#define IS_IPOD ([[[UIDevice currentDevice] model] isEqualToString:@"iPod touch"])
//获取系统版本
#define IOS_SYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
- 使用 ARC 和 MRC
#if __has_feature(objc_arc)
// ARC
#else
// MRC
#endif
- 宏与const 的使用
宏的用法:一般定义代码就用宏。
const用法:一般定义一个常量字符串就用const(如,服务器的地址)。
static NSString * const server_host = @"api.apple.com";
- 判断当前设备是模拟器还是真机
#if TARGET_IPHONE_SIMULATOR
// 模拟器
#elif TARGET_OS_IPHONE
// 真机
#endif
- 判断当前设备系统
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
// 这里写设备系统大于8.0 以上的代码
#else
// 这里写设备系统小于8.0以上的代码
#endif
#if __IPHONE_OS_VERSION_MIN_REQUIRED <= __IPHONE_7_0
// 这里写设备系统小于7.0以上的代码
#else
// 这里写设备系统大于7.0以上的代码
#endif
- 设置随机颜色
#define GRandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
- 静态库(.a文件)中有分类,调用分类中的方法 crash
/**
静态库中编写 Category 时的便利宏,用于解决 Category 方法从静态库中加载需要特别设置的问题。
加入这个宏后,不需要再在 Xcode 的 Other Liker Fliags 中设置链接库参数(-Objc / -all_load / -force_load)
*******************************************************************************
使用:在静态库中每个分类的 @implementation 前添加这个宏
Example:
#import "NSString+BRAdd.h"
BRSYNTH_DUMMY_CLASS(NSString_BRAdd)
@implementation NSString (BRAdd)
@end
*/
#ifndef BRSYNTH_DUMMY_CLASS
#define BRSYNTH_DUMMY_CLASS(_name_) \
@interface BRSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation BRSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif
// 在ios开发过程中,有时候会用到第三方的静态库(.a文件),OC没有为每个函数(或者方法)定义链接符号,它只为每个类创建链接符号。这样当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来,就会导致你调用类别中的方法时,会出现selector not recognized的错误,从而导致app闪退。使用这段宏定义他可以虚拟新建一个与名字category 相同.h.m 让编译器 编译通过。即可解决上面的问题。
- 合成弱引用或者强引用。
/**
Synthesize a weak or strong reference.
Example:
@weakify(self)
[self doSomething^{
@strongify(self)
if (!self) return;
...
}];
*/
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
- 断言
// 1.NSAssert / NSCAssert 的用法(如果条件为假,就会抛出异常)
// 前者适用于Objective-C的方法,后者适用于C的函数。
int a = 4;
NSAssert(a == 5, @"a must equal to 5"); //第一个参数是条件,如果条件为假,就会抛出异常并打印第二个参数的内容
// 注意:NSAssert 的定义中有self(即持有self的strong引用),在block中使用时要避免出现循环引用问题。NSCAssert 的用法与 NSAssert 一致,适用于C语言的函数,在OC中也可以使用,并且没有持有self,在block中使用不会出现循环引用问题
// 2.NSParameterAssert / NSCparameterAssert 的用法(是针对参数是否存在的断言)
// 前者适用于Objective-C的方法,后者适用于C的函数。
- (void)assertWithPara:(NSString *)str {
NSParameterAssert(str); //只需要一个参数,如果参数存在程序继续运行,如果参数为空,则程序停止并打印日志
//further code ...
}
// Xcode 已经默认将release环境下的断言取消了, 免除了忘记关闭断言造成的程序不稳定。
// 常用的几个自定义断言
#define BRAssertNil(condition, description, ...) NSAssert(!(condition), (description), ##__VA_ARGS__)
#define BRCAssertNil(condition, description, ...) NSCAssert(!(condition), (description), ##__VA_ARGS__)
#define BRAssertNotNil(condition, description, ...) NSAssert((condition), (description), ##__VA_ARGS__)
#define BRCAssertNotNil(condition, description, ...) NSCAssert((condition), (description), ##__VA_ARGS__)
#define BRAssertMainThread() NSAssert([NSThread isMainThread], @"This method must be called on the main thread")
#define BRCAssertMainThread() NSCAssert([NSThread isMainThread], @"This method must be called on the main thread")
系统宏
- NS_AVAILABLE_IOS 与 NS_DEPRECATED_IOS
// 在iOS系统的API中,我们经常会看到下面的一些宏
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attributes context:(nullable NSStringDrawingContext *)context NS_AVAILABLE(10_11, 7_0);
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:") __TVOS_PROHIBITED;
/**
含义:(AVAILABLE:可用; DEPRECATED:弃用)
NS_AVAILABLE(10_11, 7_0) 表示自 Mac10.11 和 iOS7.0 引入该函数,即 iOS7之后 使用这个函数
NS_AVAILABEL_IOS(6_0) 表示自 iOS6.0 引入该方法,若在iOS6.0之前的版本使用该函数,则会导致 Crash;
NS_DEPRECATED_IOS(2_0, 7_0, "替代函数") 表示该函数自 iOS2.0 引入,在 iOS7.0 被废弃。推荐 iOS7.0 之后使用替代函数。
NS_DEPRECATED(10_6, 10_9, 2_0, 7_0) 表示自 Mac10.6 和 iOS2.0 引入,在 Mac10.9 和 iOS7.0 被废弃
*/
- 忽略编译器警告宏
// 处理编译器警告(下面 #pragma 的作用是,去掉方法的警告提示)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
CGSize size = [self sizeWithFont:font constrainedToSize:maxSize lineBreakMode:lineBreakMode];
#pragma clang diagnostic pop
- 全局设置
nonnull
类型的宏
NS_ASSUME_NONNULL_BEGIN
/**
Provides extensions for `UIBarButtonItem`.
*/
@interface UIBarButtonItem (YYAdd)
/**
The block that invoked when the item is selected. The objects captured by block
will retained by the ButtonItem.
@discussion This param is conflict with `target` and `action` property.
Set this will set `target` and `action` property to some internal objects.
*/
@property (nullable, nonatomic, copy) void (^actionBlock)(id);
@end
NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_BEGIN
和 NS_ASSUME_NONNULL_END
两个宏之间的代码,所有指针对象都被假定为nonnull, 即不能为空,否则编辑器会报警告 Null passed to a callee that requires a non-null argument
。
该段代码使用了
NS_ASSUME_NONNULL_BEGIN
,NS_ASSUME_NONNULL_END
两个宏中间包含的属性,参数值,返回值,默认是
nonnull
类型。如果想要某个属性,参数值或者返回值为可选类型,则单独在该属性,参数值,或者返回值前单独标明
nullable
。
网友评论