我有一个 class 我想要一些方法转移到数组的 object
I have a class I want some method transfer to an array's object
如标题所说:我有一个ObjcClass
我想要一些可以重复使用的东西,
因为 class 可能有
-(void)test1:xxx -(void)test2:xxx argu:yyy
我不想那样做
[dispatchArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[obj test2:xxx argu:yyy];
}];
示例:
- (void)test:(NSString *)argument1 {
NSArray *dispatchArray = @[];//If the array is initialized with multiple objects
//I want each object to call the "test:" method unlike the following
// [dispatchArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// [obj performSelector:@selector(test:) withObject:argument1];
// // or [obj test:argument1];
// }];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[_services enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
if ([obj respondsToSelector:_cmd]) {
[obj application:application didFinishLaunchingWithOptions:launchOptions];
}
}];
return YES;
}
像这样,UIApplicationDelegate有很多方法,我不想写[obj application:application didFinishLaunchingWithOptions:launchOptions]; or [obj applicationWillResignActive:application]; 在每个方法中,相反我希望像 [obj respondsToSelector:_cmd] 这样的方法,我可以提出作为一般方法,如 [obj invokeWithMethod:_cmd arguments:_VA_LIST];
Whether these methods can be optimized,because they do the same thing to different method
看起来您只想遍历数组中的对象。这不是很安全。所有对象都必须提供一个 "test" 方法。如果它们都相同 Class 那会比使用 NSObject 更好。
for (NSObject *obj in dispatchArray) {
[obj performSelector:@selector(test:) withObject:argument1];
}
你应用委托的方法已经实现,你应该像以前一样实现。对于UIApplicationDelegate
协议中你的app delegate没有实现的方法,你可以使用消息转发来实现你的目标。如下覆盖您的应用委托的消息转发方法:
- (BOOL)respondsToSelector:(SEL)aSelector {
struct objc_method_description desc = protocol_getMethodDescription(objc_getProtocol("UIApplicationDelegate"), aSelector, NO, YES);
if (desc.name != nil) {
return YES;
}
return [super respondsToSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL selector = [anInvocation selector];
struct objc_method_description desc = protocol_getMethodDescription(objc_getProtocol("UIApplicationDelegate"), selector, NO, YES);
if (desc.name != nil) {
[_services enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj respondsToSelector:selector]) {
[anInvocation invokeWithTarget:obj];
}
}];
}
}
获取 return 个值:
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];
}else{
//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];
}]
如标题所说:我有一个ObjcClass
我想要一些可以重复使用的东西,
因为 class 可能有
-(void)test1:xxx -(void)test2:xxx argu:yyy
我不想那样做
[dispatchArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[obj test2:xxx argu:yyy];
}];
示例:
- (void)test:(NSString *)argument1 {
NSArray *dispatchArray = @[];//If the array is initialized with multiple objects
//I want each object to call the "test:" method unlike the following
// [dispatchArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// [obj performSelector:@selector(test:) withObject:argument1];
// // or [obj test:argument1];
// }];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[_services enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
if ([obj respondsToSelector:_cmd]) {
[obj application:application didFinishLaunchingWithOptions:launchOptions];
}
}];
return YES;
}
像这样,UIApplicationDelegate有很多方法,我不想写[obj application:application didFinishLaunchingWithOptions:launchOptions]; or [obj applicationWillResignActive:application]; 在每个方法中,相反我希望像 [obj respondsToSelector:_cmd] 这样的方法,我可以提出作为一般方法,如 [obj invokeWithMethod:_cmd arguments:_VA_LIST]; Whether these methods can be optimized,because they do the same thing to different method
看起来您只想遍历数组中的对象。这不是很安全。所有对象都必须提供一个 "test" 方法。如果它们都相同 Class 那会比使用 NSObject 更好。
for (NSObject *obj in dispatchArray) {
[obj performSelector:@selector(test:) withObject:argument1];
}
你应用委托的方法已经实现,你应该像以前一样实现。对于UIApplicationDelegate
协议中你的app delegate没有实现的方法,你可以使用消息转发来实现你的目标。如下覆盖您的应用委托的消息转发方法:
- (BOOL)respondsToSelector:(SEL)aSelector {
struct objc_method_description desc = protocol_getMethodDescription(objc_getProtocol("UIApplicationDelegate"), aSelector, NO, YES);
if (desc.name != nil) {
return YES;
}
return [super respondsToSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL selector = [anInvocation selector];
struct objc_method_description desc = protocol_getMethodDescription(objc_getProtocol("UIApplicationDelegate"), selector, NO, YES);
if (desc.name != nil) {
[_services enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj respondsToSelector:selector]) {
[anInvocation invokeWithTarget:obj];
}
}];
}
}
获取 return 个值:
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];
}else{
//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];
}]