封装测试一段代码的运行时间

调用时非常方便,计算时间用了私有API

.m文件中
#import "testTime.h"
#import <objc/runtime.h>

typedef void(^callback)(id result);

//默认情况下,系统自带的IMP被定义为无参数无返回值的函数
/*重新定义IMP,有参数,带返回值和不带返回值*/
typedef void (*_VIMP) (id, SEL, ...);
typedef id(*_IMP) (id, SEL, ...);

static size_t const iterations = 100;
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));

@implementation testTime


void invokeMethodNoRetForEffctive(id target, SEL action, ...){

    //目标方法
    Method m1 = class_getInstanceMethod([target class], action);

    int numberOfArguments = method_getNumberOfArguments(m1);

    NSMutableArray *arr = [[NSMutableArray alloc] init];
    va_list params;  //定义一个指向个数可变的参数列表指针;
    id argument;
    //使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个 固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是va_start(arg_ptr, c)。
    va_start(params, action);
    while ((argument = va_arg(params, id))) {//返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr指向参数列表中下一个参数
        [arr addObject:argument];
    }
    va_end(params);//释放列表指针

    //获取目标方法的指针  改方法无返回值
    _VIMP someMethod = (_VIMP)method_getImplementation(m1);
//  extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));

    uint64_t t_1 = dispatch_benchmark(iterations, ^{

        switch (numberOfArguments) {
            case 2:
                someMethod(target,action);
                break;
            case 3:
                someMethod(target,action,arr[0]);
                break;
            case 4:
                someMethod(target,action,arr[0],arr[1]);
                break;
            case 5:
                someMethod(target,action,arr[0],arr[1],arr[2]);
                break;
            case 6:
                someMethod(target,action,arr[0],arr[1],arr[2],arr[3]);
                break;
            case 7:
                someMethod(target,action,arr[0],arr[1],arr[2],arr[3],arr[4]);
                break;
            default:
                break;
        }

    });
    NSLog(@"该方法总共耗时:--》 %llu ns",t_1);

//  invokeMethodHasRetForEffctive(yh_self, name, 'q', 111, nil);

}

void invokeMethodHasRetForEffctive(id target, SEL action, ...){

    //目标方法
    Method m1 = class_getInstanceMethod([target class], action);

    int numberOfArguments = method_getNumberOfArguments(m1);

    NSMutableArray *arr = [[NSMutableArray alloc] init];
    va_list params;  //定义一个指向个数可变的参数列表指针;
    id argument;
    va_start(params, action);
    //返回参数列表中指针arg_ptr所指的参数,返回类型为type(type有很多是不支持的,比如char,bool),并使指针arg_ptr指向参数列表中下一个参数
    while ((argument = va_arg(params, id))) {
        [arr addObject:argument];
    }
    va_end(params);//释放列表指针

    //获取目标方法的指针  改方法无返回值
    _IMP someMethod = (_IMP)method_getImplementation(m1);


    uint64_t t_1 = dispatch_benchmark(iterations, ^{

        switch (numberOfArguments) {
            case 2:
                someMethod(target,action);
                break;
            case 3:
                someMethod(target,action,arr[0]);
                break;
            case 4:
                someMethod(target,action,arr[0],arr[1]);
                break;
            case 5:
                someMethod(target,action,arr[0],arr[1],arr[2]);
                break;
            case 6:
                someMethod(target,action,arr[0],arr[1],arr[2],arr[3]);
                break;
            case 7:
                someMethod(target,action,arr[0],arr[1],arr[2],arr[3],arr[4]);
                break;
            default:
                break;
        }

    });
    NSLog(@"该方法总共耗时:--》 %llu ns",t_1);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
    getMethodArgType(target, @selector(todoSomething:with:), 111, YES);
#pragma clang diagnostic pop

}

void getMethodArgType(id target, SEL action, ...){

    NSMutableArray *argList = [[NSMutableArray alloc] init];
    /*如果用va_arg(ap, type)这个宏作可变参数获取的话,有很多类型是不支持的,比如char,bool等*/
    /*用NSNSInvocation做参数获取,支持所有参数类型*/

    NSMethodSignature * methodSignature  = [[target class] instanceMethodSignatureForSelector:action];
    //通过签名初始化
//  NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    va_list params;  //定义一个指向个数可变的参数列表指针;
    va_start(params, action);
    for (int i=2; i<[methodSignature numberOfArguments]; i++) {

//      const char *argumentType = method_copyArgumentType(m1, i);
        const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];
        switch(argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {

                #define JP_FWD_ARG_CASE(_typeChar, _type) \
                case _typeChar: {   \
                _type arg;  \
                arg = va_arg(params, _type);    \
                [argList addObject:@(arg)]; \
                break;  \
                }
                JP_FWD_ARG_CASE('c', int)
                JP_FWD_ARG_CASE('C', unsigned int)
                JP_FWD_ARG_CASE('s', int)
                JP_FWD_ARG_CASE('S', unsigned int)
                JP_FWD_ARG_CASE('i', int)
                JP_FWD_ARG_CASE('I', unsigned int)
                JP_FWD_ARG_CASE('l', long)
                JP_FWD_ARG_CASE('L', unsigned long)
                JP_FWD_ARG_CASE('q', long long)
                JP_FWD_ARG_CASE('Q', unsigned long long)
                JP_FWD_ARG_CASE('f', double)
                JP_FWD_ARG_CASE('d', double)
                JP_FWD_ARG_CASE('B', int)
            default: {

                id argument;
                (argument = va_arg(params, id));
                [argList addObject:argument];

                break;
            }
        }

    }
    va_end(params);//释放列表指针

    //通过签名初始化
    NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    [invocation setTarget:target];
    [invocation setSelector:action];
    for (int i=2; i<[methodSignature numberOfArguments]; i++) {
        const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];
        switch(argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {

                #define YH_SET_ARG_CASE(_typeChar, _type, _typeValue) \
                case _typeChar: {   \
                _type argg = [argList[i-2] _typeValue];  \
                [invocation setArgument:&argg atIndex:i]; \
                break;  \
                }
                YH_SET_ARG_CASE('c', char, charValue)
                YH_SET_ARG_CASE('C', unsigned char, unsignedCharValue)
                YH_SET_ARG_CASE('s', short, shortValue)
                YH_SET_ARG_CASE('S', unsigned short, unsignedShortValue)
                YH_SET_ARG_CASE('i', int, intValue)
                YH_SET_ARG_CASE('I', unsigned int, unsignedIntValue)
                YH_SET_ARG_CASE('l', long, longValue)
                YH_SET_ARG_CASE('L', unsigned long, unsignedLongValue)
                YH_SET_ARG_CASE('q', long long, longLongValue)
                YH_SET_ARG_CASE('Q', unsigned long long, unsignedLongLongValue)
                YH_SET_ARG_CASE('f', float, floatValue)
                YH_SET_ARG_CASE('d', double, doubleValue)
                YH_SET_ARG_CASE('B', BOOL, boolValue)

            default: {

                id argument =argList[i-2];
                [invocation setArgument:&argument atIndex:i];
                break;
            }
        }

    }

    uint64_t t_1 = dispatch_benchmark(iterations, ^{
        [invocation invoke];
    });
    NSLog(@"该方法总共耗时:--》 %llu ns",t_1);
}
@end

然后在.h文件中声明函数
/*SEL 函数无返回值*/
void invokeMethodNoRetForEffctive(id target, SEL action, ...);
/*SEL 函数有返回值*/
void invokeMethodHasRetForEffctive(id target, SEL action, ...);

void getMethodArgType(id target, SEL action, ...);
然后在其他地方调用
    invokeMethodNoRetForEffctive(self, @selector(insertObj:lala:), @"qwerq",@"111111", nil);
    invokeMethodHasRetForEffctive(self, @selector(frc:lala:), @"qwerq",@"111111", nil);
    //block也可以作为参数传递
    callback call= ^(id result){
        NSLog(@"111--callback");
    };

@selector(frc:lala:), @"qwerq",call, nil);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在React中使用Axios进行网络请求时,可以使用TypeScript进行封装以提高代码的可读性和维护性。 首先,我们可以创建一个axios实例,并对其进行一些全局配置,如设置基本的URL地址、超时时间等。可以在一个单独的文件中,比如`api.ts`中进行封装: ```typescript import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; const instance = axios.create({ baseURL: 'https://api.example.com', timeout: 5000 }); // 添加请求拦截器 instance.interceptors.request.use( (config: AxiosRequestConfig) => { // 在发送请求之前可以进行一些处理,比如添加token等 return config; }, (error: any) => { return Promise.reject(error); } ); // 添加响应拦截器 instance.interceptors.response.use( (response: AxiosResponse) => { // 在拿到响应数据之后可以进行一些处理,比如统一处理错误等 return response; }, (error: any) => { return Promise.reject(error); } ); export default instance; ``` 接下来,我们可以创建一个`api.ts`文件,封装各种不同的接口请求: ```typescript import axios from './axios'; export const getUserInfo = () => axios.get('/user/info'); export const updateUser = (data: any) => axios.post('/user/update', data); export const deleteUser = (userId: number) => axios.delete(`/user/${userId}`); ``` 使用时,我们只需要在组件中引入对应的接口请求函数即可: ```typescript import { useEffect, useState } from 'react'; import { getUserInfo } from './api'; const UserInfo = () => { const [userInfo, setUserInfo] = useState<any>(null); useEffect(() => { getUserInfo() .then((response) => { setUserInfo(response.data); }) .catch((error) => { console.log(error); }); }, []); return ( <div> {userInfo && ( <div> <h1>User Info:</h1> <p>Name: {userInfo.name}</p> <p>Email: {userInfo.email}</p> </div> )} </div> ); }; export default UserInfo; ``` 通过封装,我们能够将网络请求和业务逻辑分离,提高代码的可维护性和可测试性。此外,使用TypeScript进行类型检查,可以在编码阶段捕获一些潜在的错误,减少运行时错误的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值