runtime让某对象执行特定多参数方法

+ (id)dw_target:(id)target performSel:(SEL)sel arguments:(id)firstObj,... NS_REQUIRES_NIL_TERMINATION {
    //获取信号量
    NSMethodSignature *signature = [target methodSignatureForSelector:sel];
    
    NSAssert(signature, @"method : %@ does not implementation",NSStringFromSelector(sel));
    
    NSInteger numberOfArguments = signature.numberOfArguments;
    
    //配置invocation并执行 获取返回参数
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.selector = sel;
    invocation.target = target;
    
    //获取可变参数
    va_list list;
    va_start(list, firstObj);
    int i = 0;
    for (id temp = firstObj;temp != nil;temp = va_arg(list, id)){
        if (i >= numberOfArguments - 2){
            break;
        }
        [invocation setArgument:&temp atIndex:i + 2];
        i++;
    }
    [invocation retainArguments];
    va_end(list);
    
    if ([invocation.target respondsToSelector:invocation.selector]) {
        [invocation invokeWithTarget:invocation.target];
    }else{
        return nil;
    }
    
    const char *returnType = signature.methodReturnType;

    id  returnValue;

    if( !strcmp(returnType, @encode(void)) ){
        returnValue =  nil;
    }else if( !strcmp(returnType, @encode(id)) ){
        [invocation getReturnValue:&returnValue];
    }else{
        NSUInteger length = [signature methodReturnLength];
        
        void *buffer = (void *)malloc(length);
        [invocation getReturnValue:buffer];
        
        if (strcmp(returnType, @encode(char)) == 0) {
            returnValue = [NSNumber numberWithChar:*((char*)buffer)];
        } else if (strcmp(returnType, @encode(int)) == 0) {
            returnValue = [NSNumber numberWithInt:*((int *)buffer)];
        } else if (strcmp(returnType, @encode(short)) == 0) {
            returnValue = [NSNumber numberWithShort:*((short *)buffer)];
        } else if (strcmp(returnType, @encode(long)) == 0) {
            returnValue = [NSNumber numberWithLong:*((long *)buffer)];
        } else if (strcmp(returnType, @encode(long long)) == 0) {
            returnValue = [NSNumber numberWithLongLong:*((long long *)buffer)];
        } else if (strcmp(returnType, @encode(unsigned char)) == 0) {
            returnValue = [NSNumber numberWithUnsignedChar:*((unsigned char *)buffer)];
        } else if (strcmp(returnType, @encode(unsigned int)) == 0) {
            returnValue = [NSNumber numberWithUnsignedInt:*((unsigned int *)buffer)];
        } else if (strcmp(returnType, @encode(unsigned short)) == 0) {
            returnValue = [NSNumber numberWithUnsignedShort:*((unsigned short *)buffer)];
        } else if (strcmp(returnType, @encode(unsigned long)) == 0) {
            returnValue = [NSNumber numberWithUnsignedLong:*((unsigned long *)buffer)];
        } else if (strcmp(returnType, @encode(unsigned long long)) == 0) {
            returnValue = [NSNumber numberWithUnsignedLongLong:*((unsigned long long *)buffer)];
        } else if (strcmp(returnType, @encode(float)) == 0) {
            returnValue = [NSNumber numberWithFloat:*((float *)buffer)];
        } else if (strcmp(returnType, @encode(double)) == 0) {
            returnValue = [NSNumber numberWithDouble:*((double *)buffer)];
        } else if (strcmp(returnType, @encode(BOOL)) == 0) {
            returnValue = [NSNumber numberWithBool:*((BOOL *)buffer)];
        } else {
            returnValue = [NSValue valueWithBytes:buffer objCType:returnType];
        }

    }
    return returnValue;

}

使用方法:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    
    NSValue *value = [NSObject dw_target:self.originalDelegate performSel:_cmd arguments:collectionView,collectionViewLayout, nil];
    UIEdgeInsets insets = UIEdgeInsetsZero;
    [value getValue:&insets];
    return insets;
}




- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    
    NSNumber *value = [NSObject dw_target:self.originalDelegate performSel:_cmd arguments:collectionView,collectionViewLayout,@(section), nil];

    if (!value) {
        return CGFLOAT_MIN;
    }
    return [value floatValue];
}

你可能感兴趣的:(runtime让某对象执行特定多参数方法)