iOS的hook方案: Method Swizzling

iOS 小技能:Method Swizzling (交换方法的IMP) 前言如果使用恰当,Method swizzling 还是很安全的.一个简单安全的方法是,仅在load中swizzle。 这里写链接内容Objective-C的hook方案在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用Objective-C的动态特性,可以实现在运行时偷换selector对应的方法实现,达到给方法挂钩的目的。 每个类都................................................... 阅读详情

在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有更加灵活的方法吗?在Objective-C编程中,如何实现hook呢?标题有点大,计划分几篇来总结。

本文主要介绍针对selector的hook,主角被标题剧透了———— Method Swizzling 。



Method Swizzling 原理


在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用Objective-C的动态特性,可以实现在运行时偷换selector对应的方法实现,达到给方法挂钩的目的。

每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针,指向具体的Method实现。





我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP,

我们可以利用 class_replaceMethod 来修改类,

我们可以利用 method_setImplementation 来直接设置某个方法的IMP,
……

归根结底,都是偷换了selector的IMP,如下图所示:








Method Swizzling 实践



举个例子好了,我想钩一下NSArray的lastObject 方法,只需两个步骤。

第一步:给NSArray加一个我自己的lastObject

  1. #import "NSArray+Swizzle.h"  
  2.   
  3.   
  4. @implementation NSArray (Swizzle)  
  5.   
  6.   
  7. - (id)myLastObject  
  8. {  
  9.     id ret = [self myLastObject];  
  10.     NSLog(@"**********  myLastObject *********** ");  
  11.     return ret;  
  12. }  
  13. @end  

乍一看,这不递归了么?别忘记这是我们准备调换IMP的selector,[self myLastObject] 将会执行真的 [self lastObject] 。



第二步:调换IMP
  1. #import   
  2. #import "NSArray+Swizzle.h"  
  3.   
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7.     @autoreleasepool {  
  8.           
  9.         Method ori_Method =  class_getInstanceMethod([NSArray class], @selector(lastObject));  
  10.         Method my_Method = class_getInstanceMethod([NSArray class], @selector(myLastObject));  
  11.         method_exchangeImplementations(ori_Method, my_Method);  
  12.           
  13.         NSArray *array = @[@"0",@"1",@"2",@"3"];  
  14.         NSString *string = [array lastObject];  
  15.         NSLog(@"TEST RESULT : %@",string);  
  16.           
  17.         return 0;  
  18.     }  
  19. }  


控制台输出Log:
  1. 2013-07-18 16:26:12.585 Hook[1740:c07] **********  myLastObject ***********   
  2. 2013-07-18 16:26:12.589 Hook[1740:c07] TEST RESULT : 3  


结果很让人欣喜,是不是忍不住想给UIWebView的loadRequest: 加 TODO 了呢? 




Method Swizzling 的封装



之前在github上找到的RNSwizzle,推荐给大家,可以搜一下。
  1. //  
  2. //  RNSwizzle.m  
  3. //  MethodSwizzle  
  4.   
  5.   
  6. #import "RNSwizzle.h"  
  7. #import   
  8. @implementation NSObject (RNSwizzle)  
  9.   
  10.   
  11. + (IMP)swizzleSelector:(SEL)origSelector   
  12.                withIMP:(IMP)newIMP {  
  13.   Class class = [self class];  
  14.   Method origMethod = class_getInstanceMethod(class,  
  15.                                               origSelector);  
  16.   IMP origIMP = method_getImplementation(origMethod);  
  17.     
  18.   if(!class_addMethod(self, origSelector, newIMP,  
  19.                       method_getTypeEncoding(origMethod)))  
  20.   {  
  21.     method_setImplementation(origMethod, newIMP);  
  22.   }  
  23.     
  24.   return origIMP;  
  25. }  
  26. @end  




Method Swizzling 危险不危险



针对这个问题,我在 stackoverflow 上看到了满意的答案,这里翻译一下,总结记录在本文中,以示分享:


使用 Method Swizzling 编程就好比切菜时使用锋利的刀,一些人因为担心切到自己所以害怕锋利的刀具,可是事实上,使用钝刀往往更容易出事,而利刀更为安全。
Method swizzling 可以帮助我们写出更好的,更高效的,易维护的代码。但是如果滥用它,也将会导致难以排查的bug。 


背景


好比设计模式,如果我们摸清了一个模式的门道,使用该模式与否我们自己心里有数。单例模式就是一个很好的例子,它饱受争议但是许多人依旧使用它。Method Swizzling也是一样,一旦你真正理解它的优势和弊端,使用它与否你应该就有你自己的观点。


讨论


这里是一些 Method Swizzling的陷阱:
  • Method swizzling is not atomic
  • Changes behavior of un-owned code
  • Possible naming conflicts
  • Swizzling changes the method's arguments
  • The order of swizzles matters
  • Difficult to understand (looks recursive)
  • Difficult to debug


我将逐一分析这些点,增进对Method Swizzling的理解的同时,并搞懂如何应对。


Method swizzling is not atomic


我所见过的使用method swizzling实现的方法在并发使用时基本都是安全的。95%的情况里这都不会是个问题。通常你替换一个方法的实现,是希望它在整个程序的生命周期里有效的。也就是说,你会把 method swizzling 修改方法实现的操作放在一个加号方法 +(void)load里,并在应用程序的一开始就调用执行。你将不会碰到并发问题。假如你在 +(void)initialize初始化方法中进行swizzle,那么……rumtime可能死于一个诡异的状态。


Changes behavior of un-owned code


这是swizzling的一个问题。我们的目标是改变某些代码。swizzling方法是一件灰常灰常重要的事,当你不只是对一个NSButton类的实例进行了修改,而是程序中所有的NSButton实例。因此在swizzling时应该多加小心,但也不用总是去刻意避免。

想象一下,如果你重写了一个类的方法,而且没有调用父类的这个方法,这可能会引起问题。大多数情况下,父类方法期望会被调用(至少文档是这样说的)。如果你在swizzling实现中也这样做了,这会避免大部分问题。还是调用原始实现吧,如若不然,你会费很大力气去考虑代码的安全问题。



Possible naming conflicts


命名冲突贯穿整个Cocoa的问题. 我们常常在类名和类别方法名前加上前缀。不幸的是,命名冲突仍是个折磨。但是swizzling其实也不必过多考虑这个问题。我们只需要在原始方法命名前做小小的改动来命名就好,比如通常我们这样命名:
 
  1. @interface NSView : NSObject  
  2. - (void)setFrame:(NSRect)frame;  
  3. @end  
  4.   
  5.   
  6. @implementation NSView (MyViewAdditions)  
  7.   
  8.   
  9. - (void)my_setFrame:(NSRect)frame {  
  10.     // do custom work  
  11.     [self my_setFrame:frame];  
  12. }  
  13.   
  14.   
  15. + (void)load {  
  16.     [self swizzle:@selector(setFrame:) with:@selector(my_setFrame:)];  
  17. }  
  18.   
  19.   
  20. @end  


这段代码运行正确,但是如果my_setFrame: 在别处被定义了会发生什么呢?

这个问题不仅仅存在于swizzling,这里有一个替代的变通方法:

  1. @implementation NSView (MyViewAdditions)  
  2.   
  3.   
  4. static void MySetFrame(id self, SEL _cmd, NSRect frame);  
  5. static void (*SetFrameIMP)(id self, SEL _cmd, NSRect frame);  
  6.   
  7.   
  8. static void MySetFrame(id self, SEL _cmd, NSRect frame) {  
  9.     // do custom work  
  10.     SetFrameIMP(self, _cmd, frame);  
  11. }  
  12.   
  13.   
  14. + (void)load {  
  15.     [self swizzle:@selector(setFrame:) with:(IMP)MySetFrame store:(IMP *)&SetFrameIMP];  
  16. }  
  17.   
  18.   
  19. @end  

看起来不那么Objectice-C了(用了函数指针),这样避免了selector的命名冲突。 


最后给出一个较完美的swizzle方法的定义:
  1. typedef IMP *IMPPointer;  
  2.   
  3.   
  4. BOOL class_swizzleMethodAndStore(Class class, SEL original, IMP replacement, IMPPointer store) {  
  5.     IMP imp = NULL;  
  6.     Method method = class_getInstanceMethod(class, original);  
  7.     if (method) {  
  8.         const char *type = method_getTypeEncoding(method);  
  9.         imp = class_replaceMethod(class, original, replacement, type);  
  10.         if (!imp) {  
  11.             imp = method_getImplementation(method);  
  12.         }  
  13.     }  
  14.     if (imp && store) { *store = imp; }  
  15.     return (imp != NULL);  
  16. }  
  17.   
  18.   
  19. @implementation NSObject (FRRuntimeAdditions)  
  20. + (BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store {  
  21.     return class_swizzleMethodAndStore(self, original, replacement, store);  
  22. }  
  23. @end  



Swizzling changes the method's arguments



我认为这是最大的问题。想正常调用method swizzling 将会是个问题。

  1. [self my_setFrame:frame];  


直接调用my_setFrame: , runtime做的是

  1. objc_msgSend(self, @selector(my_setFrame:), frame);  

runtime去寻找my_setFrame:的方法实现, _cmd参数为 my_setFrame: ,但是事实上runtime找到的方法实现是原始的 setFrame: 的。

一个简单的解决办法:使用上面介绍的swizzling定义。




The order of swizzles matters



多个swizzle方法的执行顺序也需要注意。假设 setFrame: 只定义在NSView中,想像一下按照下面的顺序执行:
  1. [NSButton swizzle:@selector(setFrame:) with:@selector(my_buttonSetFrame:)];  
  2. [NSControl swizzle:@selector(setFrame:) with:@selector(my_controlSetFrame:)];  
  3. [NSView swizzle:@selector(setFrame:) with:@selector(my_viewSetFrame:)];  

What happens when the method on NSButton is swizzled? Well most swizzling will ensure that it's not replacing the implementation of setFrame: for all views, so it will pull up the instance method. This will use the existing implementation to re-define setFrame: in the NSButton class so that exchanging implementations doesn't affect all views. The existing implementation is the one defined on NSView. The same thing will happen when swizzling on NSControl (again using the NSView implementation).

When you call setFrame: on a button, it will therefore call your swizzled method, and then jump straight to the setFrame: method originally defined on NSView. The NSControl and NSView swizzled implementations will not be called.

But what if the order were:
  1. [NSView swizzle:@selector(setFrame:) with:@selector(my_viewSetFrame:)];  
  2. [NSControl swizzle:@selector(setFrame:) with:@selector(my_controlSetFrame:)];  
  3. [NSButton swizzle:@selector(setFrame:) with:@selector(my_buttonSetFrame:)];  

Since the view swizzling takes place first, the control swizzling will be able to pull up the right method. Likewise, since the control swizzling was before the button swizzling, the button will pull up the control's swizzled implementation of setFrame:. This is a bit confusing, but this is the correct order. How can we ensure this order of things?

Again, just use load to swizzle things. If you swizzle in load and you only make changes to the class being loaded, you'll be safe. The load method guarantees that the super class load method will be called before any subclasses. We'll get the exact right order!


这段贴了原文,硬翻译太拗口……总结一下就是: 多个有继承关系的类的对象swizzle时,从子类对象开始 。 如果先swizzle父类对象,那么后面子类对象swizzle时就无法拿到真正的原始方法实现了。 


(感谢评论中 qq373127202 的提醒,在此更正一下,十分感谢)

多个有继承关系的类的对象swizzle时,先从父对象开始。 这样才能保证子类方法拿到父类中的被swizzle的实现。在+(void)load中swizzle不会出错,就是因为load类方法会默认从父类开始调用。



Difficult to understand (looks recursive)


(新方法的实现)看起来像递归,但是看看上面已经给出的 swizzling 封装方法, 使用起来就很易读懂.
这个问题是已完全解决的了!




Difficult to debug


debug时打出的backtrace,其中掺杂着被swizzle的方法名,一团糟啊!上面介绍的swizzle方案,使backtrace中打印出的方法名还是很清晰的。但仍然很难去debug,因为很难记住swizzling影响过什么。给你的代码写好文档(即使只有你一个人会看到)。养成一个好习惯,不会比调试多线程问题还难的。




结论


如果使用恰当,Method swizzling 还是很安全的.一个简单安全的方法是,仅在load中swizzle。 和许多其他东西一样,它也是有危险性的,但理解它了也就可以正确恰当的使用它了。

原文链接:http://blog.sina.com.cn/s/blog_a343f32b0101en4o.html

动力学约束下的运动规划算法——状态栅格规划器(State Lattice Planner) A*、RRT等算法建立的用于路径搜索的图模型是不考虑机器人的动力学约束的,其构建的图模型的两个相邻节点之间的路径可能是不可行的,或者很难被机器人跟踪的,现在我们想要使得图中相邻两个节点间的连接是一种满足动力学约束的可行的连接,那么如何构建一个这样的图呢? 构建这样的图通常有两种方法:第一种是基于控制空间的采样(正向方法) 阅读详情

相关推荐

SpringBoot多线程查询实战-查询库中所有数据多线程实现

但是,在数据量较大且服务器资源足够的情况下,多线程方法通常能够显著提高查询效率。此外,由于它是同步执行的,没有利用并行处理的能力,所以在处理大量数据时可能会比较慢。这个方法采用了分页查询的方式,每次只获取一部分数据,从而避免了内存溢出的问题。然而,它也是同步执行的,没有利用多线程或并行处理的能力。如果每次分页查询的数据量仍然很大,或者需要查询的轮数很多,那么这种方法的效率可能仍然会受到限制。​ ​ ​在比较这三种方式的效率时,我们需要考虑几个关键因素:数据量的大小、查询操作的复杂性、以及并行处理的能力。

勇敢牛牛,不怕困难! 4809

Objective-C的hook方案(一): Method Swizzling

Objective-C的hook方案(一): Method Swizzling 在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有更加灵活的方法吗?在Objective-C编程中,如何实现hook呢?标题有点大,计划分几篇来总结。 本文主要介绍针对selector的hook,主角被标题剧透了———— Method Swizzling 。...

nayao-net 538

【2023版】基于JT808/JT1078协议的车载视频监控平台开发实战-开源架构解析

本文详细解析了基于JT808/JT1078协议的车载视频监控平台开发实战,涵盖协议核心作用、开源架构设计、开发避坑指南及二次开发建议。重点介绍了JT1078协议在音视频传输中的优化方案,以及海量位置数据存储、高可用架构等关键技术点,为开发者提供全面的实战参考。

weixin_26965807的博客 236

利用Objective-C运行时hook函数的三种方法

方法一,hook已有公开头文件的类: 首先写一个Utility函数: [cpp] view plaincopy #import   inline void exchangeMethod(Class aClass, SEL oldSEL, SEL newSEL)  {      Method oldMethod = class_getInstanceMethod(aClas

lusonglin121的专栏 1449

中文实体关系抽取数据集大盘点:从百度Duie2.0到医疗CBLUE,哪个更适合你的NLP项目?

本文全面分析了中文实体关系抽取领域的主流数据集,包括百度DuIE 2.0、医疗CBLUE等,帮助开发者根据项目需求选择最适合的数据集。文章详细对比了各数据集的特点、适用场景及优化策略,为自然语言处理项目提供实用指南。

weixin_29284657的博客 121

CLCD 中国生命周期基础数据库使用攻略

CLCD 是公共建筑碳排放计算的理想选择,其本地化数据可显著提高计算准确性。

hy行者勇哥的博客 2686

Method-Swizzling 方法交换

method-swizzling 是什么? method-swizzling的含义是方法交换,其主要作用是在运行时将一个方法的实现替换成另一个方法的实现,这就是我们常说的iOS黑魔法, 在OC中就是利用method-swizzling实现AOP,其中AOP(Aspect Oriented Programming,面向切面编程)是一种编程的思想,区别于OOP(面向对象编程) OOP和AOP都是一种编程的思想 OOP编程思想更加倾向于对业务模块的封装,划分出更加清晰的逻辑单元; 而AOP是面向切面进行提取封装,

开源世界 3423

【无人机路径规划】基于强化学习实现多无人机路径规划

【无人机路径规划】基于强化学习实现多无人机路径规划

k8291121的博客 1656

【iOS】方法交换(Method Swizzling)

上文讲到了iOS的消息发送机制,在消息机制中我们了解到了SEL、IMP等方法知识,由此延伸到iOS黑魔法方法交换,本篇着重讲解iOS的方法交换的应用场景与原理这篇文章主要总结了的各种应用场景,例如防止按钮被多次点击,进行hook操作以及数组与KVO的兜底操作,应用场景非常广泛,值得深入学习iOS Crash防护系统-IronManiOS KVO 崩溃防护笔记。

weixin_72437555的博客 2370

11、AUTOSAR配置全解析:从运行实体到通信接口

本博客详细解析了在Simulink中使用AUTOSAR字典配置AUTOSAR运行实体(Runnables)、运行实体间变量(IRVs)、参数以及多种通信接口的过程。内容涵盖运行实体及其事件的配置、IRV和参数的属性设置,以及发送-接收接口、模式切换接口、客户端-服务器接口、非易失性数据接口、参数接口和触发接口的详细配置方法。通过这些步骤,开发者可以高效地构建符合AUTOSAR标准的汽车电子软件系统。

e3f4g5的博客 123

iOS第三方库调试实战:iOS-Debug-Hacks教你解决SDK冲突问题

在iOS开发过程中,集成第三方SDK是提升开发效率的常用手段,但SDK之间的兼容性问题往往成为项目迭代的绊脚石。iOS-Debug-Hacks作为一套专注于iOS项目高级调试技巧的实践方案,不仅涵盖动态调试、静态分析和反编译等核心能力,更能帮助开发者快速定位并解决第三方库冲突问题。本文将通过真实案例,详解如何利用iOS-Debug-Hacks提供的调试工具和方法论,高效解决SDK集成中的常见冲突。

gitblog_00594的博客 303

实测可复现|2026 Cloudflare盾v4.0反反爬全实战:从JS/WASM逆向到JA3指纹伪装,手把手突破拦截(附完整逆向代码+避坑手册)

本文以2026年Cloudflare盾v4.0(集成Shield Synapse v2.0)为核心,全程以实战复盘为视角,拆解了从JS/WASM混合逆向、全维度指纹伪装(JA3+浏览器指纹)、人类行为模拟,到代理池搭建的全流程,整合了完整可复现的代码,所有步骤和踩坑点均为实测所得,无任何AI套话,新手也能跟着复现,最终实现爬取成功率从12%提升至95%+。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1686

iOS Hook技术终极对决:fishhook vs Method Swizzling 完全指南

在iOS开发中,Hook技术是调试、监控和扩展应用功能的重要工具。面对fishhook和Method Swizzling这两种主流方案,开发者常常陷入选择困境。本文将为你详细解析两者的差异,帮助你做出最佳技术选型。 ## 什么是iOS Hook技术? Hook技术允许开发者在运行时修改程序的行为,通过拦截和替换函数或方法的执行来实现功能扩展。无论是性能监控、行为分析还是功能增强,Hook都是i

gitblog_01185的博客 425

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

iOS黑魔法-Method Swizzling(全局hook,行为统计)

转自:http://www.jianshu.com/p/ff19c04b34d0 需求 就拿我们公司项目来说吧,我们公司是做导航的,而且项目规模比较大,各个控制器功能都已经实现。突然有一天老大过来,说我们要在所有页面添加统计功能,也就是用户进入这个页面就统计一次。我们会想到下面的一些方法: 手动添加 直接简单粗暴的在每个控制器中加入统计,复制、粘贴、复制、粘贴...

爱技术....爱生活! 5478

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

iOS开发 Method Swizzling黑魔法处理异常问题

class_addMethod如果类没有该方法,为其添加方法,则返回YES;如果有该方法,则返回NO,所以我们在交互前可以加入这个进行判断。} else {防止出现问题,防止直接替换的时候调用过程中出现unrecognized selector sent to instance的崩溃问题。

一名开发者 1245

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

ios runtime:Method Swizzling

什么是Method Swizzling Method Swizzling (方法交换),顾名思义,及时将两个方法的实现交换,即由原来的A-AImp、B - BImap对应关系变成了A-BImap、B-AImap。 什么情况下要将两个方法的实现交换 1、hook:在开发中,经常用到系统提供的API,但出于某些需求,我们可能会对其方法的实现不太满意。就想去修改它已达到更好的效果,当特定的消息发出时,会...

大大的爬虫 261

IOS Method Swizzling 替换方法 Objective-C的hook方案

Objective-C的hook方案(一):  Method Swizzling 在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有更加灵活的方法吗?在Objective-C编程中,如何实现hook呢?标题有点大,计划分几篇来总结。 本文主要介绍针对selector的hook,主角被标题剧透了———— Meth

iOS 刘通超 3045

Objective-C Method Swizzling 最佳实践

????????关注后回复“进群”,拉你进程序员交流群????????作者 | 杨萧玉来源 | 玉令天下的博客http://yulingtianxia.com/blog/2017/0...

iOS_开发 332

iOS运行时以及HOOK的理解:runtime和method swizzling

iOS运行时以及HOOK的理解:runtime和method swizzling

骑着蜗牛找马儿 1847

如何在 PPT Agent 中开启人工审计断点:逐页把关 PPT 的完整指南

PPT Agent 是一个把演示文稿生成当作软件工程来做的 AI PPT 生成框架,能从资料检索、大纲策划一路自动跑完到逐页渲染导出 PPTX。但自动跑通不等于放心交付——PPT Agent 内置了**人工审计断点**机制,允许你在关键节点停下来看截图、审策划、发改单,逐页把关每一张幻灯片。下面带你完整走一遍开启与使用流程。 ## 为什么 PPT 生成流程需要人工审计断点 🎯 PPT Age

gitblog_00026的博客 388

IOPaint 快速上手:一条命令抹掉水印、多余物体和文字

上周接到一个活:把几十张带水印的图库素材清理出来,其中还混着路人甲和压在画面上的大字。用传统工具一张一张抠,一天也做不完,接缝还难看得像补丁。后来我换用 IOPaint——一个免费开源的 AI 图像修复工具,涂个掩码就能把水印、多余物体、文字直接抹掉,还能用 Stable Diffusion 类模型替换内容、向外扩图。 ## 一条命令启动 Web 界面 装好就跑,模型会在首次启动时自动下载:

gitblog_00665的博客 1051

关于不同类的Method Swizzling

iOS的Method Swizzling是一个非常有意思的run time应用案例.用它可以实现AOP,也可以用来hook很多API,进行很多hack的操作相关资料很多,总体来讲就是调换两个Method的Imp,也就是调换函数指针.在很多AOP的案例中,使用这种方式hook住关键方法,在递归调用方法前/后实现AOP.例如:在一个UIViewController的category中,可以这样+ (vo

heiby的博客 1696

终极fishhook性能评测:5种iOS Hook方法效率深度对比

fishhook是一款轻量级库,能够在iOS模拟器和设备上动态重新绑定Mach-O二进制文件中的符号,为开发者提供了类似OS X上`DYLD_INTERPOSE`的功能。在调试和跟踪libSystem调用方面,fishhook展现出独特的价值,例如帮助审计文件描述符的双重关闭问题。本文将对fishhook与其他四种常见Hook方法进行性能深度对比,为iOS开发者选择最适合的Hook方案提供参考。

gitblog_00897的博客 1008

coreboot IPMI KCS 驱动:BMC 通信与 ACPI/SMBIOS 表生成实战指南

本指南基于 [Documentation/drivers/ipmi_kcs.md](https://link.gitcode.com/i/750594599988252c9074fd1b87b670d5) 与 [src/drivers/ipmi/](https://link.gitcode.com/i/755a7bd7a928db9a92b2c5cd0fa47a40) 下的源码实现,系统讲解 co

gitblog_00367的博客 940
上一篇: NSLog常用的代码
下一篇: iOS AVAudioSession、AudioSession Category选择和声音通道听筒、扬声器切换
堇羊
博客等级 码龄16年 2粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值