runtime运行时
OC程序开发过程
#import预处理指令有两个作用:(1)与#include一样,拷贝文件内容(2)可以自动防止文件的内容被重复拷贝
程序编译连接过程:
源文件(.m)---(编译)---->目标文件(.0)-----(链接)---->可执行文件(.out)
Foundation框架。如果要使用框架中的所有头文件那么应该怎么办?包含框架的主头文件。主头文件是一个框架中最主要的头文件,每个框架的主头文件名和框架名一致。
如#import<foundation/foundation.h>
运行过程如下:
(1)编写OC源文件 .m .c
(2)编译文件 cc -c xx.m xxx.c
(3)链接 cc xx.o xxx.o -framework Foundation
(4)运行 ./a.out
文件编译
在工作中,通常把不同的类放到不同的文件中,每个类的声明和实现分开,声明写在.h头文件中,实现写在相应的.m文件中去,类名是什么,文件名的前缀就是什么。
假设有两个类,分别是Person类和Dog类,则通常有下面五个文件:
(1)Person.h Person类的声明文件
(2)Person.m Person类的实现文件
(3)Dog.h Dog类的声明文件
(4)Dog.m Dog类的实现文件
(5)Main.m 主函数(程序入口)
在主函数以及类的实现文件中要使用#import包含相应的头文件。
补充:import有两个作用:一是和include一样,完完全全的拷贝文件的内容;二是可以自动防止文件内容的重复拷贝(即使文件被多次包含,也只拷贝一份)。
在使用命令行进行编译链接文件的时候,通常是把.m文件单文件编译,然后再把所有的目标文件链接,但是在Xcode中,是把所有的.m文件都进行编译链接的,如果出现重复定义的错误,那大部分问题根源应该就是文件内容被重复包含或者是包含.m文件所引起的。
源文件中不论是使用include还是import,都不能包含.m或者是.c文件,只能放声明。因此,在OC中通常把类拆分开来,拆分成声明和实现两个部分。
提示:这也是编程思想的一种体现,可以说.h和.m文件时完全独立的,只是为了要求有较好的可读性,才要求两个文件的文件名一致,这也是把接口和实现分离,让调用者不必去关心具体的实现细节。
Xcode是写一行编译一行,有简单的修复功能,红色是错误提示,黄色警告。如果在程序中声明了一个变量,但是这个变量没有被使用也会产生警告信息。在调试程序的时候,如果发现整个页面都没有报错,但是一运行就错误,那么一定是链接报错。
RunTime运行时
runtime实现的机制是什么,怎么用,一般用于干嘛? 这个问题我就不跟大家绕弯子了,直接告诉大家, runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如说,下面一个创建对象的方法中, 举例: OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
NSObject
@interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;//class
}
NSObject 只有一个成员isa 为class类型。
/**
* Describes the instance variables declared by a class.
*
* @param cls The class to inspect.
* @param outCount On return, contains the length of the returned array.
* If outCount is NULL, the length is not returned.
*
* @return An array of pointers of type Ivar describing the instance variables declared by the class.
* Any instance variables declared by superclasses are not included. The array contains *outCount
* pointers followed by a NULL terminator. You must free the array with free().
*
* If the class declares no instance variables, or cls is Nil, NULL is returned and *outCount is 0.
*/ /**
* 描述类声明的实例变量
*
* @param cls 要检查的类
* @param outCount 有返回 包含返回数组的长度
* 如果 outCount 为空,长度没有返回
*
* 返回一个ivar类型的指针数组 ,描述这个类声明的实例变量
* 任何父类声明的实例变量是不包括的 这个数组仅仅包含指针
*如果指针为空,你必须用free()释放
*
* 如果这个类声明的不是实例变量,或者类为空 返回NULL outCount为0
*/ OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
“遍历当前类所有的成员变量”
==================================================
/* Working with Instance Variables */ /**
* Returns the name of an instance variable.
*
* @param v The instance variable you want to enquire about.
*
* @return A C string containing the instance variable's name.
*/
/* 操作实例变量 */ /**
* 返回实例变量的名字.
*
* @param v 你想要查询的实例变量
*
* @return 一个C语言 字符串 包含实例变量的名字
*/
OBJC_EXPORT const char *ivar_getName(Ivar v)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
“打印成员变量名字”
================================================== /**
* Returns the type string of an instance variable.
*
* @param v The instance variable you want to enquire about.
*
* @return A C string containing the instance variable's type encoding.
*
* @note For possible values, see Objective-C Runtime Programming Guide > Type Encodings.
*/
/**
* 返回一个实例变量的类型字符串。
*
* @param V 你想查询的实例变量。
*
* @return一个C语言字符串,包含实例变量的类型的 。
*
* @有价值的资料,看Objective-C编程指南>类型编码。
*/ OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); - (void)viewDidLoad {
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor whiteColor]]; // 获得Person类中的所有成员变量 unsigned int count;
Ivar *ivars = class_copyIvarList([runModel class], &count);
for (int i = 0; i<count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
const char *type = ivar_getTypeEncoding(ivar);
NSLog(@"%s %s", name, type);
} } ========================控制台打印结果========================
2016-07-22 16:15:22.086 runrunrun[20039:3797680] _age i
2016-07-22 16:15:22.086 runrunrun[20039:3797680] _name @"NSString"
2016-07-22 16:15:22.087 runrunrun[20039:3797680] _height @"NSString"
2016-07-22 16:15:22.087 runrunrun[20039:3797680] _weight @"NSString"
2016-07-22 16:15:22.087 runrunrun[20039:3797680] _sex @"NSNumber"
// Created by Music on 16/7/12.
// Copyright © 2016年 citibank. All rights reserved.
// #import <Foundation/Foundation.h> @interface runModel : NSObject @property (nonatomic ,copy)NSString *name;
@property (nonatomic ,copy)NSString *height;
@property (nonatomic ,copy)NSString *weight;
@property (nonatomic ,assign)int age;
@property (nonatomic ,strong)NSNumber *sex; @end
分类加属性 应用运行时策略 #import "runModel.h"
#import "Person.h" @interface runModel (cate)
@property (nonatomic ,strong)Person *height;
- (void)test;
@end =============================
#import "runModel+cate.h"
#import <objc/runtime.h>
@implementation runModel (cate) - (void)test
{
NSLog(@"执行test分类方法");
} static double HeightKey; - (void)setHeight:(Person *)height
{
objc_setAssociatedObject(self, &HeightKey, height, OBJC_ASSOCIATION_ASSIGN);
} - (Person *)height
{
return objc_getAssociatedObject(self, &HeightKey);
} @end
=================================== runModel *model = [[runModel alloc] init];
model.height = p101;
NSLog(@"---->>>%@",model.height);
runtime方法总结
1 获取类成员变量名,方法名称
unsigned int count;
Ivar *ivars = class_copyIvarList([runModel class], &count);
2 关联(分类添加属性)
objc_setAssociatedObject(self, &HeightKey, height, OBJC_ASSOCIATION_ASSIGN);
objc_getAssociatedObject(self, &HeightKey);
3 运行时添加方法
class_addMethod(self, sel, (IMP)nameGetter, "@@:");
4 消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector{}
5 方法交换
/** 获取原始setBackgroundColor方法 */
Method originalM = class_getInstanceMethod([self class], @selector(setBackgroundColor:)); /** 获取自定义的pb_setBackgroundColor方法 */
Method exchangeM = class_getInstanceMethod([self class], @selector(pb_setBackgroundColor:)); /** 交换方法 */
method_exchangeImplementations(originalM, exchangeM);
方法相关操作函数
Runtime提供了一系列的方法来处理与方法相关的操作。包括方法本身及SEL。本节我们介绍一下这些函数。
方法
// 调用指定方法的实现
id method_invoke ( id receiver, Method m, ... ); // 调用返回一个数据结构的方法的实现
void method_invoke_stret ( id receiver, Method m, ... ); // 获取方法名
SEL method_getName ( Method m ); // 返回方法的实现
IMP method_getImplementation ( Method m ); // 获取描述方法参数和返回值类型的字符串
const char * method_getTypeEncoding ( Method m ); // 获取方法的返回值类型的字符串
char * method_copyReturnType ( Method m ); // 获取方法的指定位置参数的类型字符串
char * method_copyArgumentType ( Method m, unsigned int index ); // 通过引用返回方法的返回值类型字符串
void method_getReturnType ( Method m, char *dst, size_t dst_len ); // 返回方法的参数的个数
unsigned int method_getNumberOfArguments ( Method m ); // 通过引用返回方法指定位置参数的类型字符串
void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len ); // 返回指定方法的方法描述结构体
struct objc_method_description * method_getDescription ( Method m ); // 设置方法的实现
IMP method_setImplementation ( Method m, IMP imp ); // 交换两个方法的实现
void method_exchangeImplementations ( Method m1, Method m2 );
runtime运行时的更多相关文章
- iOS - OC RunTime 运行时
1.运行时的使用 向分类中添加属性 // 包含运行时头文件 #import <objc/runtime.h> /* void objc_setAssociatedObject(id obj ...
- RunTime 运行时
简单介绍RunTime 运行时的用法 以下操作都需要导入头文件 #import <objc/message.h> #pragma mark -- 发消息 //OC方法调用的本质就是让对象发 ...
- iOS RunTime运行时(1):类与对象
Objective-C语言是一门动态语言,他将很多静态语言在编译和链接期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码更具有灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一下 ...
- RunTime运行时在iOS中的应用之UITextField占位符placeholder
RunTime运行时机制 runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API. 在我们平时编写的Objective-C代码中, 程序运行过程时, 其实最终 ...
- runtime运行时,类、对象、isa指针
先查看一段OC源码,关于类的定义: /// An opaque type that represents an Objective-C class. typedef struct objc_class ...
- iOS运行时Runtime浅析
运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行.例如[target doSomething];会被转化成objc)msgSend(target,@select ...
- 【原】iOS动态性(五)一种可复用且解耦的用户统计实现(运行时Runtime)
声明:本文是本人 编程小翁 原创,转载请注明. 为了达到更好的阅读效果,强烈建议跳转到这里查看文章. iOS动态性是我的关于iOS运行时的系列文章,由浅入深,从理论到实践.本文是第5篇.有兴趣可以看看 ...
- iOS 运行时runtime控制私有变量以及私有方法
OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法.利用runtime机制让我们可以在程序运行时动态修改类.对象中的所有属性.方法,就算是私有方法以及私有属性都是可以动 ...
- Objective C运行时(runtime)
#import <objc/runtime.h> void setBeingRemoved(id __self, SEL _cmd) { NSLog(@"------------ ...
随机推荐
- 【原】作为前端需要了解的B/S架构
其实B/S架构是属于后台方面的东西,不过作为一个前端,也是需要了解一下滴 C/S架构简要介绍 在了解什么是B/S架构之前,我们有必要了解一下什么是C/S架构: C/S架构是第一种比较早的软件架构,主要 ...
- chose.jquery 联动
<!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- IDF-CTF-牛刀小试-啥?
本人属于Web安全这一块的小白,稍微了作了一下知识补充就开始了CTF,其中的有很多不懂但看多了网上大牛的解题办法和思路.便开始有了一些要想动手记录的冲动,希望大家共同进步学习,本文能对读者有所帮助~ ...
- nginx_mysql_redis配置
#Nginx所用用户和组,window下不指定 #user nobody; #工作的子进程数量(通常等于CPU数量或者2倍于CPU) worker_processes 2; #错误日志存放路径 #er ...
- webpack踩坑之路——图片的路径与打包
转自:http://www.cnblogs.com/ghost-xyx/p/5812902.html 刚开始用webpack的同学很容易掉进图片打包这个坑里,比如打包出来的图片地址不对或者有的图片并不 ...
- Web API系列(二)接口安全和参数校验
以前简单介绍过web api 的设计,但是还是有很多朋友问我,如何合理的设计和实现web api.比如,接口安全,异常处理,统一数据返回等问题.所以有必要系统的总结总结 web api 的设计和实现. ...
- session
小结
- ump_player在线直播播放器
ump_player在线直播播放器封装,可以支持加载在线直播流 https://github.com/Mrxdh/EveryExercise/blob/master/ump_player%E5%9 ...
- 仿淘宝分页按钮效果简单美观易使用的JS分页控件
分页按钮思想: 1.少于9页,全部显示 2.大于9页,1.2页显示,中间页码当前页为中心,前后各留两个页码 附件中有完整例子的压缩包下载.已更新到最新版本 先看效果图: 01输入框焦点效果 ...
- Android常用组件之ListView
使用ListAdapter是ListView的适配器. 使用ListView.setAdapter()方法来设置ListView的适配器. 简单的使用 adapter = new ArrayAdapt ...