runtime-objc_msgSend
来源:互联网 发布:ip地址和端口的关系 编辑:程序博客网 时间:2024/06/05 04:07
[TOC]
前言: 本文十分基础
这篇文章讲讲怎么用objc_msgSend
,配合一个小小的案例,不光光讲怎样用,我会把我是如何学到objc_msgSend
这一系列的过程.很多时候,我们看别人的文章,只会给你将结果,很少会讲这个结果究竟是怎样得出来的,OK,言归正传.
runtime
,大家都知道这个运行时库,在运行的时候,会把OC代码转为C,然后执行.OK,熟记于心,怎样转?我不会,那么objc_msgSend
我也知道这个API,是runtime
库里面的,可是大家是如何知道的?我不知道.
起因
最近在看一本书,书上讲到把OC代码转换为C源码,这里有个终端命令clang -rewrite-objc <filename.m>
我试着在终端上敲如下命令:
中间打红的部分是路径,最简单的办法就是把.m文件直接拖到终端.我敲下回车,发现报错,'UIKit/UIKit.h' file not found
这个问题我现在还没找到解决的办法.
上面的不行,我去创建了一个新工程:
这里选择Command Line Tool.
然后这里只有一个main.m文件,我在这个文件里面添了简单的几行代码,main.m文件看起来是下面这个样子:
#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) { @autoreleasepool { NSString * str = @"123"; [str stringByAppendingString:@"456"]; } return 0;}
OK,我这里有个细节,就是在桌面创建了一个名为clang的文件夹,如果你直接打开终端,那么你的所在的路径是在根目录下的用户.为什么要说这个,因为你使用clang -rewrite-objc <filename.m>
这个命令,它会在当前目录下生产一个main.cpp的文件.这个就是我们的目标文件.
首先打开终端,输入如命令clang -rewrite-objc main.m
,这里我直接把工程里面的main.m文件复制到桌面的clang
文件夹里面了,然后按下回车,我这里会输出很多warning:
运行到这里就OK了,我们可以用open .
命令打开clang
文件夹,会看到里面多了个main.m文件.
我这里生成的main.m文件有3M大,我猜想是把Foundation框架都转成了C源码.9.5W行代码��.
直接command+↓
跳到文件的最下面,可以看到int main()
这个main函数,函数体内,就是我关注的东西了.
我是如何找到这个main函数在最下面?是我看书上的图片,显示的就是int main(...
,我就直接搜索了一下这个int main
的位置,代码如下:
int main(int argc, const char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; NSString * str = (NSString *)&__NSConstantStringImpl__var_folders_6q_7tzk06yx4fd147m641v6dnsw0000gn_T_main_4f05b0_mi_0; ((NSString *(*)(id, SEL, NSString *))(void *)objc_msgSend)((id)str, sel_registerName("stringByAppendingString:"), (NSString *)&__NSConstantStringImpl__var_folders_6q_7tzk06yx4fd147m641v6dnsw0000gn_T_main_4f05b0_mi_1); } return 0;}
OK,到了这一步,C语言的源码暴露在我们面前了,到这里,就可以比葫芦画瓢,试着用objc_msgSend
来做一些没有objc_msgSend
它不能做的事情咯.
#import "ViewController.h"#import "UIAlertAction+SLAlertAction.h"#import <objc/message.h>@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ __block UIAlertController *alertVc = [self tipWithTitle:@"你好吗" Message:@"我不好"]; [self presentViewController:alertVc animated:YES completion:nil]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"aaa"); alertVc.title = @"heelo"; ((UIAlertAction *(*)(id, SEL, NSString *))(void *)objc_msgSend)((id)alertVc.actions.firstObject, @selector(setTitle:), @"hello"); });}- (UIAlertController *)tipWithTitle:(NSString *)title Message:(NSString *)message{ UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *firm = [UIAlertAction sl_alertActionWithType:HYBVerifyAlertActionConfirm navController:nil refuseMessage:nil]; UIAlertAction *cancel = [UIAlertAction sl_alertActionWithType:HYBVerifyAlertActionCancel navController:nil refuseMessage:nil]; [alertVc addAction:cancel]; [alertVc addAction:firm]; return alertVc;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
UIAlertAction
的title
是个只读属性,但是我想在弹窗弹出,3秒后进行修改取消
两字为heelo
.这里我用了一个UIAlertAction的分类.其实就是添加了一个取消一个确定按钮.
我们可以使用objc_msgSend来修改.
只需要对比着((NSString *(*)(id, SEL, NSString *))(void *)objc_msgSend)((id)str, sel_registerName("stringByAppendingString:"), (NSString *)&__NSConstantStringImpl__var_folders_6q_7tzk06yx4fd147m641v6dnsw0000gn_T_main_4f05b0_mi_1);
这行代码敲就可以了!
嗯..
- runtime objc_msgSend
- runtime-objc_msgSend
- runtime-class_addMethod\objc_msgSend\NSInvocation
- Runtime之objc_msgSend函数
- iOS笔记-runtime objc_msgSend
- runtime objc_msgSend消息发送
- Objective-C Runtime 【objc_msgSend函数】
- Objective-C Runtime分析(三)-objc_msgSend
- runtime简单理解之消息传递 objc_msgSend
- objc_msgSend
- Xcode6调试runtime机制的objc_msgSend函数时报错
- runtime简单学习之消息传递objc_msgSend(二)
- Objective-C Runtime Programming Guide 笔记02 objc_msgSend Function
- objc_msgsend crash
- objc_msgSend函数
- objc_msgSend () 错误
- objc_msgSend函数
- objc_msgSend crash
- 实战Java虚拟机之二“虚拟机的工作模式”
- 实战Java虚拟机之三“G1的新生代GC”
- Android 相机使用 Camera
- C# 详解特性
- Chrome OS,互联操作系统(WebOS)典型案例
- runtime-objc_msgSend
- 寒假训练——HDU - 2532 Engine 模拟
- 开启新的篇章
- MySQL数据库设置远程访问权限方法小结 简单,粗暴,有截图
- MacOS下Rails+Nginx+SSL环境的搭建(上)
- NGINX轻松管理10万长连接 --- 基于2GB内存的CentOS 6.5 x86-64
- 关于swift3.0中基于viewConroller修改当前UIStausBarStyle
- Python学习笔记(综述)
- fpga项目整理