Aprove answer
NSMutableArray *returnValues = [NSMutableArray array];
[_services enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    id returnValue = [NSNull null];
    if ([obj respondsToSelector:selector]) {
        [anInvocation invokeWithTarget:obj];

        const char *returnType = anInvocation.methodSignature.methodReturnType;

        if( !strcmp(returnType, @encode(void)) ){
            //If the return value is `void`, just set returnValue = [NSNull null]
        } else if( !strcmp(returnType, @encode(id)) ){
            // if the return type is derived data types(`id`)
            [anInvocation getReturnValue:&returnValue];
            //if the return value is basicdata type
            NSUInteger length = [anInvocation.methodSignature methodReturnLength];
            void *buffer = (void *)malloc(length);
            [anInvocation getReturnValue:buffer];
            if( !strcmp(returnType, @encode(BOOL)) ) {
                returnValue = [NSNumber numberWithBool:*((BOOL*)buffer)];  
            } else if( !strcmp(returnType, @encode(NSInteger)) ){
                returnValue = [NSNumber numberWithInteger:*((NSInteger*)buffer)];  
            returnValue = [NSValue valueWithBytes:buffer objCType:returnType];
    // If the `obj` can not responds to selector, or the return value is void(nil), we set the `returnValue = [NSNull null]`
    [returnValues addObject:returnValue];


for (NSObject *obj in dispatchArray) {
        [obj performSelector:@selector(test:) withObject:argument1];

Credit Goes to: stackoverflow.com

Related question with same questions but different answers