内联函数

内联函数是指用inline关键字修饰的函数。内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。编译时,类似宏替换,使用函数体替换调用处的函数名。C语言原本是不支持inline的,但C++中原生对inline的支持让很多C编译器也为C语言实现了一些支持inline语义的扩展。C99将inline正式放入到标准C语言中,并提供了inline关键字。和C++中的inline一样,C99的inline也是对编译器的一个提示,提示编译器尽量按照内联函数的定义去编译,去除函数调用带来的开销。

引入内联函数的主要原因

用它替代C中表达式形式的宏定义

表达式形式的宏定义示例:

#define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)

为什么要取代这种形式的宏定义?

总结: inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了它的缺点(隐患和局限性),同时又很好地继承了它的优点(效率会提高)

使用inline函数要注意

Objective-C中使用inline,主要是为了提高函数调用的效率

示例:

static inline NSString * imageURLKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"image_%lu", (unsigned long)state];
}

YYKit源码YYKitMacro.h组件中大量使用的内联函数

static inline void dispatch_async_on_main_queue(void (^block)()) {
    if (pthread_main_np()) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), block);
    }
}
dispatch_async_on_main_queue(^{
     ...
});

inline 会有 static来修饰,表示在当前文件中应用 如 static b, 在其它文件中也可以出现static b.不会导致重名的错误

inline和函数

inline和宏

inline说明

Objective-C项目中应用示例

// SwizzlingDefine.h
#ifndef NIM_SwizzlingDefine_h
#define NIM_SwizzlingDefine_h
#import <objc/runtime.h>
static inline void swizzling_exchangeMethod(Class clazz ,SEL originalSelector, SEL swizzledSelector){
    Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector);
    
    BOOL success = class_addMethod(clazz, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (success) {
        class_replaceMethod(clazz, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

#endif
#ifndef NIM_SwizzlingDefine_h
#define NIM_SwizzlingDefine_h

#endif

作用: 这是C++预编译头文件保护符,保证即使文件被多次包含,头文件也只定义一次.主要目的是防止头文件的重复包含和编译

Swift 没有内联函数一说,默认编译器自动对函数优化

// 调用示例
static func classInitial() {
    swizzleMethod
} 

private static let swizzleMethod: Void = {
    let originalSelector = #selector(UINavigationController.pushViewController(_:animated:))
    let swizzledSelector = #selector(hd_pushViewController)
        swizzlingForClass(UINavigationController.self, originalSelector: originalSelector, swizzledSelector: swizzledSelector)
}()

参考链接