Avoid being rejected for respondsToSelector:, performSelector:

Posted by pacuran on Mon, 01 Jul 2019 18:05:31 +0200

Avoid being rejected for respondsToSelector:, performSelector:

Remember that many iOS developers received rejected emails using JSPatch some time ago.

Your app, extension, and/or linked framework appears to contain code designed explicitly with the capability to change your app's behavior or functionality after App Review approval, which is not in compliance with section 3.3.2 of the Apple Developer Program License Agreement and App Store Review Guideline 2.5.2. This code, combined with a remote resource, can facilitate significant changes to your app's behavior compared to when it was initially reviewed for the App Store. While you may not be using this functionality currently, it has the potential to load private frameworks, private methods, and enable future feature changes.
This includes any code which passes arbitrary parameters to dynamic methods such as dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations(), and running remote scripts in order to change app behavior or call SPI, based on the contents of the downloaded script. Even if the remote resource is not intentionally malicious, it could easily be hijacked via a Man In The Middle (MiTM) attack, which can pose a serious security vulnerability to users of your app.
Please perform an in-depth review of your app and remove any code, frameworks, or SDKs that fall in line with the functionality described above before submitting the next update for your app for review.
Best regards
App store Review

As a result, many developers are busy removing frames with JSPatch or updating new ones.
At that time, I remember that I also had a lot of problems with tripartite frameworks, such as Golden, such as bugly...

Removing hot updates became a big event in March.
Now, of course, calm has returned,

Of course, we will always remove hot update frameworks such as JSPatch, but some developers will not use JSPatch hot update at all, but applications will receive mail.
That's probably why

We noticed responseToSelector and performSelector,
Recall that we often use...
So many recumbent guns are here, and I was rejected after removing the frame just when JSPatch was restricted because of both methods.
So I came up with an alternative to both.

#import <Foundation/Foundation.h>

@interface NSObject (Extension)

-(BOOL)canRunToSelector:(SEL)aSelector;

- (id)runSelector:(SEL)aSelector withObjects:(NSArray *)objects;

@end
#import "NSObject+Extension.h"
#import <objc/runtime.h>

@implementation NSObject (Extension)

-(BOOL)canRunToSelector:(SEL)aSelector{
    unsigned int methodCount =0;
    Method  *methodList = class_copyMethodList([self class],&methodCount);
    NSString *selectorStr = NSStringFromSelector(aSelector);

    BOOL result = NO;
    for (int i = 0; i < methodCount; i++) {
        Method temp = methodList[i];
        const char* selectorName =sel_getName(method_getName(temp));
        NSString *tempSelectorString = [NSString stringWithUTF8String:selectorName];
        NSLog(@"%@",tempSelectorString);
        if ([tempSelectorString isEqualToString:selectorStr]) {
            result = YES;
            break;
        }
    }
    free(methodList);
    return result;
}

- (id)runSelector:(SEL)aSelector withObjects:(NSArray *)objects {
    NSMethodSignature *methodSignature = [self methodSignatureForSelector:aSelector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    [invocation setTarget:self];
    [invocation setSelector:aSelector];

    NSUInteger i = 1;

    if (objects.count) {
        for (id object in objects) {
            id tempObject = object;
            [invocation setArgument:&tempObject atIndex:++i];
        }
    }
    [invocation invoke];

    if (methodSignature.methodReturnLength) {
        id value;
        [invocation getReturnValue:&value];
        return value;
    }
    return nil;
}

@end

Through these two methods, I replaced the two dangerous methods mentioned in the email. Although not perfect, there is no problem with our application. Get on the shelf smoothly

The first method is to get all the instance method names of the current class and compare them with the method names provided.
The second method is to implement NSInvocation using another OC call method, which converts the original method and parameters to NSInvocation calls.

The two methods are not complex, and many people think about them for a moment.

Of course, writing this now has no effect on developers who have experienced JSPatch events since it's almost two months old, but I think it's still necessary to provide my implementation for developers who have just participated in development or who happened not to have encountered hot updates before.

Welcome to my iOS series blog, just started writing, you can also give some suggestions
Series: iOS Development - Preface + Outline

Topics: iOS hot update