OC中一些预定义宏

作者: 大刘 | 来源:发表于2022-06-26 22:14 被阅读0次

Created by 大刘 liuxing8807@126.com

看一些内置的宏(C/C++, OC可用),比如:

__LINE__     是整数类型;
__FILE__     宏是字符串类型;
__TIME__     宏是字符串类型;
__FUNCTION__ 宏是字符串类型;
__DATE__     宏是字符串类型;

采用#define定义宏,宏的优劣很明显,但使用宏在某些场景下确实可以起到一些作用;

举其中的一些示例:

__FUNCTION__

C语言中获取函数名,一般是__func__,GCC还支持FUNCTION.同时,PRETTY_FUNCTION`对函数的打印会带上参数

#include <stdio.h>

void sayHello(char *str) {
    printf("%s: hello %s\n", __PRETTY_FUNCTION__, str); // void sayHello(char *): hello daliu
}

int main(int argc, const char * argv[]) {
    printf("%s %s %s\r\n",__func__,__FUNCTION__,__PRETTY_FUNCTION__); // main main int main(int, const char **)
    sayHello("daliu");
    return 0;
}

__COUNTER__

__COUNTER__也是C的一个宏,它的值从0开始,每次调用就会加1,因为一般可以用来做为UniqueId的一部分.

From Doc:

COUNTER
This macro expands to sequential integral values starting from 0. In conjunction with the ## operator, this provides a convenient means to generate unique identifiers. Care must be taken to ensure that COUNTER is not expanded prior to inclusion of precompiled headers which use it. Otherwise, the precompiled headers will not be used.

上面讲通常搭配连接符##使用,示例:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

#define ZZ_CONCAT(A, B) ZZ_CONCAT2(A, B)
#define ZZ_CONCAT2(A, B) A##B

#define SKILL \
+ (void)ZZ_CONCAT(skill_, __COUNTER__) { \
    NSLog(@"%@", NSStringFromSelector(_cmd)); \
}

@interface Person : NSObject

@end

NS_ASSUME_NONNULL_END
#import "Person.h"
#import <objc/runtime.h>

@implementation Person

+ (void)load {
    [self printClassMethod:self];
}

// 打印类方法
+ (void)printClassMethod:(Class)cls {
    unsigned int methodCount = 0;
    // object_getClass(cls) 获取元类对象,类方法存储在元类对象中
    Method *methods = class_copyMethodList(object_getClass(cls), &methodCount);

    for (unsigned int i = 0; i < methodCount; i++) {
        Method method = methods[i];
        NSString *methodName = NSStringFromSelector(method_getName(method));
        NSLog(@"方法名: %@", methodName);
    }

    free(methods);
}

SKILL
SKILL
SKILL
SKILL
SKILL
SKILL

@end

程序打印:

方法名: printClassMethod:
方法名: skill_0
方法名: skill_1
方法名: skill_2
方法名: skill_3
方法名: skill_4
方法名: skill_5
方法名: load

__LINE__

__LINE__表示当前行,是整数类型,示例:

line.png

可以在很多场景下使用__LINE__做一些事情,比如自定义Log并打印出代码的哪一行出现了问题,就可以使用这种方式:

#ifdef DEBUG
#define ZZLog(fmt, ...) NSLog((@"🙍♂️ ZZ log method: %s line: %d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define ZZLog(fmt, ...)
#endif

需要注意的是,这里的__LINE__所代指的行号是宏展开的地方,而不是宏定义的地方;而且宏有个特点是它实际上是一行,宏定义中使用了\只是代码显示的分隔,但实际上仍是一行,因此__LINE__仍是当前宏展开的那一行,示例:

#import <Foundation/Foundation.h>
#import "Test.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [Test test];
    }
    return 0;
}
1   //
2   //  Test.h
3   //  TestLine
4   //
5   //  Created by daliu.
6   //
7   
8   #import <Foundation/Foundation.h>
9   
10  NS_ASSUME_NONNULL_BEGIN
11  
12  #define PRINT_LINE_METHOD \
13  + (void)printCurrentLine { \
14      NSLog(@"current line is: %d", __LINE__); \
15  }
16  
17  @interface Test : NSObject
18  
19  + (void)test;
20  
21  @end
22  
23  NS_ASSUME_NONNULL_END
1   //
2   //  Test.m
3   //  TestLine
4   //
5   //  Created by daliu on 2020/12/5.
6   //
7   
8   #import "Test.h"
9   
10  @implementation Test
11  
12  PRINT_LINE_METHOD
13  // 因为宏展开所在的行是第12行,即在第12行相当于: + (void)printCurrentLine { NSLog(@"current line is: %d", __LINE__); }
14  // 所以打印结果是 current line is: 12
15  
16  + (void)test {
17      [self printCurrentLine];
18  }
19  
20  @end

相关文章

  • swift&&OC

    宏定义 OC中的宏定义 swift中的宏定义 OC中宏定义的方式,在swift中是不可用的,在swift中,宏定义...

  • 在swift中使用宏定义

    在OC中我们习惯将一些常用变量或者方法使用宏定义全局访问,然而swift因为命名空间的缘故,不需要像OC那样进行宏...

  • OC&swift中的宏定义

    在使用OC和swift进行混编时,我们经常会需要在swift中使用OC中的宏定义,但是这些宏定义经常会提示无法找到...

  • swift中的全局常量和全局方法

    类似于OC中的宏定义 全局常量 全局方法

  • Swift 与 OC 预编译宏定义

    在我们开发过程中,经常使用到预编译的宏定义,例如 OC 代码中 #ifdef DEBUG 这种宏定义的,还有多个 ...

  • 将OC中宏定义改为Swift版“宏定义”

    其实,swift并不支持宏定义,实质上是一些全局常量和函数,所以我们可以通过这个途径实现类似于OC中的宏定义,以减...

  • PCH文件(OC和Swift)

    大家都知道在OC中我们经常使用PCH文件定义一些全局的宏定义,这样使用起来很方便。但是在Swift中创建PCH文件...

  • PCH文件(Objective-C和Swift)

    大家都知道在OC中我们经常使用PCH文件定义一些全局的宏定义,这样使用起来很方便。但是在Swift中创建PCH文件...

  • 3、Swift-“宏定义”的实现

    OC中的宏定义 C语言的宏定义, 并不是很严谨, 任何代码段都可以进行宏定义, 甚至是无效的无序的乱码也可以. 因...

  • OC宏定义

    usr/include #空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #un...

网友评论

    本文标题:OC中一些预定义宏

    本文链接:https://www.haomeiwen.com/subject/ihogvrtx.html