快速上手Runtime(三)之方法交换

开发过程中,我们经常会用到系统类,而它提供的方法又不能完全满足我们开发的需要,那么在此时,我们需要为系统自带的方法扩展一些功能,而且还要保证原有的功能可正常使用.假设咱们现在有这么一个需求,我们在调用系统的[UIImage imageNamed:@"runtime"];的时候,我们并不能判断有没有加载成功,所以我们想在加载图片的时候并判断是否加载成功。

方案1:

我们通常想到的就是分类,用分类添加一个方法,实现,然后在想要调用的地方导入头文件,去调用.

#import <UIKit/UIKit.h>

@interface UIImage (Method)

+(UIImage *)cdm_imageNamed:(NSString *)imageName;

@end

+(UIImage *)cdm_imageNamed:(NSString *)imageName
{
    //首先加载图片
    UIImage *image=[UIImage imageNamed:imageName];

    //然后实现功能【判断是否为空】

    if (image==nil) {
        NSLog(@"图片为空");
    }
    return image;
}

调用:

import "ViewController.h"
#import "UIImage+Method.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //分类实现:
    UIImage *image = [UIImage cdm_imageNamed:@"cdm"];

}

方案2:

利用runtime交换方法,我们调用系统的方法 实际是调用我们的方法:

步骤1.在分类加载的时候+(void)load;交换方法的实现

步骤2.方法交换之前首先获取方法,因为交换方法的两个参数就是方法

步骤3.方法交换

+(void)load
{
    // 交换方法实现,方法都是定义在类里面
    // class_getInstanceMethod:获取对象
    // class_getClassMethod:获取类方法
    // IMP:方法实现

    // imageNamed
    // Class:获取哪个类方法
    // SEL:获取方法编号,根据SEL就能去对应的类找方法

    Method imageMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));

    Method cmd_imageMethod = class_getClassMethod([UIImage class], @selector(cdm_imageNamed:));

    //方法交换
    method_exchangeImplementations(imageMethod, cmd_imageMethod);
}

如果此时你认为完事了,调用系统的imageNamed方法,会造成死循环。因为我们在自定义的方法中加载图片调用的就是系统的imageNamed的方法,此时应该修改代码如下:

//运行时

+(UIImage *)cdm_imageNamed:(NSString *)imageName
{
    //修改为我们自己的方法,防止死循环
    UIImage *image=[UIImage cdm_imageNamed:imageName];

    //然后实现功能【判断是否为空】
    if (image==nil) {
        NSLog(@"图片为空");
    }
    return image;
}

调用实现:

- (void)viewDidLoad {
    [super viewDidLoad];

    //分类实现:
//    UIImage *image = [UIImage cdm_imageNamed:@"cdm"];

    //运行时实现:
    //调用imageNamed:实际上是调用cdm_imageNamed:
    UIImage *image = [UIImage imageNamed:@"cdm"];

}

效果图:

Demo地址:https://github.com/domanc/Method_Exchange.git

时间: 2024-10-06 19:28:11

快速上手Runtime(三)之方法交换的相关文章

android快速上手(三)常用控件使用

完成了android的第一个程序HelloWorld,下面就开始控件的学习,下面是一些常见的控件. (一)TextView 简单的文本描述 (二)EditText 编辑框,输入文字信息 (三)Button 按钮,点击后会触发点击事件,可以对事件进行处理 (四)ImageView 图片控件,可以加载图片显示 (五)ListView 列表,需要跟适配器Adapter结合,适配器提供数据 (六)Toast 闪现提示语,常用于普通的提示文本,只显示一小段时间自动消失 (七)ScrollView 一般用于

iOS 为何使用runtime多次方法交换后却能按照交换顺序依次执行代码逻辑?

题目: 假设我们有一个ViewController, Category A(ViewController), Category B(ViewController), Category C(ViewController) 4个文件, 其中3个category中都实现了自定义viewDidLoad方法, 会对ViewController中的ViewDidLoad方法进行方法替换, 那么依次替换后(A B C)的方法执行顺序是什么呢? 记method_exchangeImplementations(M

【转】让你快速上手Runtime

一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用. 事实证明: 在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错. 在编译阶段,C语言调用未实现的函数就会报错. 二.runtime作用 1.发送消息 方法调用

快速上手Runtime(二)之给分类添加属性

我们都知道,分类是不能直接添加属性的,那么我们有时候又需要实现这个功能,那么我们应该怎么办才能为分类添加上属性呢. Runtime给分类添加属性原理 给一个类声明属性,其实本质就是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间. Runtime给分类添加属性步骤 1.在分类的.h文件中声明想要定义的属性 2.在分类的.m文件中实现getter和setter方法 3.引入runtime头文件,然后在setter方法中用objc_setAssociatedObject关联对象 比如给N

三种方法交换两个变量的值

#include<stdio.h> void Swap1(int x, int y)//使用了中间值 { int temp; temp = x; x = y; y = temp; printf("第一种%d,%d\n",x,y); } void Swap2(int x, int y)//未使用中间值 { x = x + y; y = x - y; x = x - y; printf("第二种%d,%d\n",x,y); } void Swap3(int

vuex 快速上手,具体使用方法总结(含使用例子)

网上有关vuex的文章很多,我这里只讲实用的: vuex 用处:管理全局状态(类似全局变量,每个组件都能访问到) vuex 用法: //下面是一个js文件,用最简单最全的例子展示了全局数据 city 和 cityID 的声明以及改变的方法: import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { city: '深圳', cityID: "1&quo

交换两个整数的三种方法

package com.zby.bubble; /** * <class description> 三种方法交换两个整数的值 * * @author zby * */ public class Exchange { public static void main(String[] args) { splitLine(); exchange1(Integer.MAX_VALUE, Integer.MAX_VALUE - 1); exchange1(99, 100); exchange1(Inte

C++ 快速上手

C++ 快速上手 (一)https://www.cnblogs.com/cosmo89929/archive/2012/12/22/2828745.html C++ 快速上手 (二)https://www.cnblogs.com/cosmo89929/archive/2012/12/22/2828774.html C++ 快速上手 (三)https://www.cnblogs.com/cosmo89929/archive/2012/12/22/2828786.html 原文地址:https://

从零开始学 Web 之 Ajax(三)Ajax 概述,快速上手

大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:http://www.cnblogs.com/lvonve/ CSDN:https://blog.csdn.net/lvonve/ 在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目.现在就让我们一起进入 Web 前端学习的冒险之旅吧! 一.Ajax 概述