好玩的NSLog

在 iOS 开发中,NSLog 是我们最常用的日志输出方式,但它默认的输出信息较少,不能直观地看到日志来源的文件、行号以及时间。今天我们就用 Objective-C 的 Runtime 特性来交换方法(Method Swizzling) ,让 NSLog 更加强大!


一、方法交换的原理

Objective-C 的方法调用本质上是向对象发送消息 ,而 Runtime 允许我们动态替换方法的实现 ,这就是 Method Swizzling

具体步骤如下:

  1. 获取原方法的 Method 结构体。
  2. 获取新方法的 Method 结构体。
  3. 交换两个方法的实现。

二、实现增强版 NSLog

我们要做的是 替换 NSLog 的实现 ,让它输出 当前时间、文件名、方法名和行号,格式如下:

yaml 复制代码
2025-03-26 10:30:15.123 文件名.m:25 方法名 - 这是自定义的日志

1. 自定义 NSLog

Prefix.pchCommonMacros.h 里添加以下代码:

objc 复制代码
#define NSLog(format, ...) CustomNSLog(__FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__)

2. 交换 NSLog 实现

创建 NSLog+Swizzling.m 文件,代码如下:

objc 复制代码
#import <Foundation/Foundation.h>
#import <objc/runtime.h>

void CustomNSLog(const char *file, const char *function, int line, NSString *format, ...) {
    va_list args;
    va_start(args, format);
    
    NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
    va_end(args);
    
    NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent];
    NSString *logStr = [NSString stringWithFormat:@"[%@:%d %s] %@", fileName, line, function, message];

    // 调用原来的 NSLog
    NSLog(@"%@", logStr);
}

@implementation NSObject (Swizzling)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod = class_getInstanceMethod([NSObject class], @selector(NSLog));
        Method swizzledMethod = class_getInstanceMethod([NSObject class], @selector(CustomNSLog));

        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

@end

三、测试效果

使用 NSLog(@"Hello, world!"); 后,控制台输出:

ini 复制代码
2025-03-26 10:30:15.123 ViewController.m:20 -[ViewController viewDidLoad] Hello, world!

这样,我们就成功 增强了 NSLog,使其输出更详细的信息,方便排查问题。


四、注意事项

  1. 方法交换要慎用 ,特别是在 +load 方法 里,因为它会影响所有 NSLog 的调用。
  2. 避免影响第三方库 ,可以使用 #ifdef DEBUG 仅在 Debug 模式 开启。
  3. 避免递归调用 ,方法交换后,如果不小心 NSLog 里又调用了 NSLog,会导致死循环。

五、总结

今天我们通过 Method Swizzling 技术,增强了 NSLog,使其支持 文件名、方法名、行号 的输出。这不仅是一个好玩的技巧,也能提升日常开发的调试效率!你可以尝试把这个功能做成一个 小工具库,用于自己的项目。

纯好玩😄,如果觉得有用,记得 点赞 + 收藏 哦!

相关推荐
初级代码游戏7 小时前
iOS开发 SwiftUI 14:ScrollView 滚动视图
ios·swiftui·swift
初级代码游戏9 小时前
iOS开发 SwitftUI 13:提示、弹窗、上下文菜单
ios·swiftui·swift·弹窗·消息框
zhyongrui12 小时前
托盘删除手势与引导体验修复:滚动冲突、画布消失动画、气泡边框
ios·性能优化·swiftui·swift
Boxsc_midnight15 小时前
【openclaw+imessage】【免费无限流量】集成方案,支持iphone手机+macos
ios·智能手机·iphone
感谢地心引力1 天前
安卓、苹果手机无线投屏到Windows
android·windows·ios·智能手机·安卓·苹果·投屏
2501_915918411 天前
HTTPS 代理失效,启用双向认证(mTLS)的 iOS 应用网络怎么抓包调试
android·网络·ios·小程序·https·uni-app·iphone
Swift社区2 天前
Flutter 路由系统,对比 RN / Web / iOS 有什么本质不同?
前端·flutter·ios
zhyongrui2 天前
SnipTrip 发热优化实战:从 60Hz 到 30Hz 的性能之旅
ios·swiftui·swift
Andy Dennis2 天前
ios开发 xcode配置
ios·cocoa·xcode
JoyCong19982 天前
iOS 27 六大功能前瞻:折叠屏、AI Siri与“雪豹式”流畅体验,搭配ToDesk开启跨设备新协作
人工智能·ios·cocoa