需求如题所示。。。。。 我们都知道

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

在NSObject中帮selector传递的参数个数最多是 2个 ,当时有时候如果某种需求。。。需要2个以上的参数该如何搞一搞了 ??? 其实网上有很多的例子


#import "NSObject+ArrayObjects.h"@implementation NSObject (ArrayObjects)
-(id)performSelector:(SEL)aSelector withArray:(NSArray *)objects{if (aSelector == nil || objects == nil) {@throw [NSException exceptionWithName:@"NullExcetption" reason: @"aSelector or objects is null" userInfo:nil];return nil;}NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:aSelector];if(methodSignature == nil){@throw [NSException exceptionWithName:@"FunctionNotFoundExcetption" reason: [NSString stringWithFormat:@"the %@ not found",NSStringFromSelector(aSelector)] userInfo:nil];return nil;}else{NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];[invocation setTarget:self];[invocation setSelector:aSelector];//签名中方法参数的个数,内部包含了self和_cmd,所以参数从第3个开始NSInteger  signatureParamCount = methodSignature.numberOfArguments - 2;NSInteger requireParamCount = objects.count;NSInteger resultParamCount = MIN(signatureParamCount, requireParamCount);for (NSInteger i = 0; i < resultParamCount; i++) {id  obj = objects[i];[invocation setArgument:&obj atIndex:i+2];}[invocation invoke];id callBackObject = nil;if(methodSignature.methodReturnLength){[invocation getReturnValue:&callBackObject];}return callBackObject;}
}
@end

虽然这个一度娘就能度到,而且感觉很牛逼,其实是有bug和缺陷性的,然后对数组里面的数据有要求,我们都知道OC是兼容C代码的。。往里面放入block或结构体就瞎了。。。。。。 我在测试AFNetworking项目的时候发现上面代码存在问题,然后找到了一个比较好一点的解决方案 ,当然github上搞一搞的 ,感觉还可以没报错

#import <Foundation/Foundation.h>@interface NSObject (VKMsgSend)+ (id)VKCallSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...;+ (id)VKCallSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...;- (id)VKCallSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...;- (id)VKCallSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...;@end@interface NSString (VKMsgSend)- (id)VKCallClassSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...;- (id)VKCallClassSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...;- (id)VKCallClassAllocInitSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...;- (id)VKCallClassAllocInitSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...;@end
#import "VKMsgSend.h"#if TARGET_OS_IPHONE
#import <UIKit/UIApplication.h>
#endif#pragma mark : vk_nilObject@interface vk_pointer : NSObject@property (nonatomic) void *pointer;@end@implementation vk_pointer@end@interface vk_nilObject : NSObject@end@implementation vk_nilObject@end#pragma mark : staticstatic NSLock *_vkMethodSignatureLock;
static NSMutableDictionary *_vkMethodSignatureCache;
static vk_nilObject *vknilPointer = nil;static NSString *vk_extractStructName(NSString *typeEncodeString){NSArray *array = [typeEncodeString componentsSeparatedByString:@"="];NSString *typeString = array[0];__block int firstVaildIndex = 0;[array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {unichar c = [typeEncodeString characterAtIndex:idx];if (c=='{'||c=='_') {firstVaildIndex++;}else{*stop = YES;}}];return [typeString substringFromIndex:firstVaildIndex];
}static NSString *vk_selectorName(SEL selector){const char *selNameCstr = sel_getName(selector);NSString *selName = [[NSString alloc]initWithUTF8String:selNameCstr];return selName;
}static NSMethodSignature *vk_getMethodSignature(Class cls, SEL selector){if (!_vkMethodSignatureLock) {_vkMethodSignatureLock =  [[NSLock alloc] init];}[_vkMethodSignatureLock lock];if (!_vkMethodSignatureCache) {_vkMethodSignatureCache = [[NSMutableDictionary alloc]init];}if (!_vkMethodSignatureCache[cls]) {_vkMethodSignatureCache[(id<NSCopying>)cls] =[[NSMutableDictionary alloc]init];}NSString *selName = vk_selectorName(selector);NSMethodSignature *methodSignature = _vkMethodSignatureCache[cls][selName];if (!methodSignature) {methodSignature = [cls instanceMethodSignatureForSelector:selector];if (methodSignature) {_vkMethodSignatureCache[cls][selName] = methodSignature;}else{methodSignature = [cls methodSignatureForSelector:selector];if (methodSignature) {_vkMethodSignatureCache[cls][selName] = methodSignature;}}}[_vkMethodSignatureLock unlock];return methodSignature;
}static void vk_generateError(NSString *errorInfo, NSError **error){if (error) {*error = [NSError errorWithDomain:errorInfo code:0 userInfo:nil];}
}static id vk_targetCallSelectorWithArgumentError(id target, SEL selector, NSArray *argsArr, NSError *__autoreleasing *error){Class cls = [target class];NSMethodSignature *methodSignature = vk_getMethodSignature(cls, selector);NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];[invocation setTarget:target];[invocation setSelector:selector];NSMutableArray* _markArray;for (NSUInteger i = 2; i< [methodSignature numberOfArguments]; i++) {const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];id valObj = argsArr[i-2];switch (argumentType[0]=='r'?argumentType[1]:argumentType[0]) {#define VK_CALL_ARG_CASE(_typeString, _type, _selector) \case _typeString: {                              \_type value = [valObj _selector];                     \[invocation setArgument:&value atIndex:i];\break; \}VK_CALL_ARG_CASE('c', char, charValue)VK_CALL_ARG_CASE('C', unsigned char, unsignedCharValue)VK_CALL_ARG_CASE('s', short, shortValue)VK_CALL_ARG_CASE('S', unsigned short, unsignedShortValue)VK_CALL_ARG_CASE('i', int, intValue)VK_CALL_ARG_CASE('I', unsigned int, unsignedIntValue)VK_CALL_ARG_CASE('l', long, longValue)VK_CALL_ARG_CASE('L', unsigned long, unsignedLongValue)VK_CALL_ARG_CASE('q', long long, longLongValue)VK_CALL_ARG_CASE('Q', unsigned long long, unsignedLongLongValue)VK_CALL_ARG_CASE('f', float, floatValue)VK_CALL_ARG_CASE('d', double, doubleValue)VK_CALL_ARG_CASE('B', BOOL, boolValue)case ':':{NSString *selName = valObj;SEL selValue = NSSelectorFromString(selName);[invocation setArgument:&selValue atIndex:i];}break;case '{':{NSString *typeString = vk_extractStructName([NSString stringWithUTF8String:argumentType]);NSValue *val = (NSValue *)valObj;#define vk_CALL_ARG_STRUCT(_type, _methodName) \if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \_type value = [val _methodName];  \[invocation setArgument:&value atIndex:i];  \break; \}vk_CALL_ARG_STRUCT(CGRect, CGRectValue)vk_CALL_ARG_STRUCT(CGPoint, CGPointValue)vk_CALL_ARG_STRUCT(CGSize, CGSizeValue)vk_CALL_ARG_STRUCT(NSRange, rangeValue)vk_CALL_ARG_STRUCT(CGAffineTransform, CGAffineTransformValue)vk_CALL_ARG_STRUCT(UIEdgeInsets, UIEdgeInsetsValue)vk_CALL_ARG_STRUCT(UIOffset, UIOffsetValue)vk_CALL_ARG_STRUCT(CGVector, CGVectorValue)}break;case '*':{NSCAssert(NO, @"argument boxing wrong,char* is not supported");}break;case '^':{vk_pointer *value = valObj;void *pointer = value.pointer;id obj = *((__unsafe_unretained id *)pointer);if (!obj) {if (argumentType[1] == '@') {if (!_markArray) {_markArray = [[NSMutableArray alloc] init];}[_markArray addObject:valObj];}}[invocation setArgument:&pointer atIndex:i];}break;case '#':{[invocation setArgument:&valObj atIndex:i];}break;default:{if ([valObj isKindOfClass:[vk_nilObject class]]) {[invocation setArgument:&vknilPointer atIndex:i];}else{[invocation setArgument:&valObj atIndex:i];}}}}[invocation invoke];if ([_markArray count] > 0) {for (vk_pointer *pointerObj in _markArray) {void *pointer = pointerObj.pointer;id obj = *((__unsafe_unretained id *)pointer);if (obj) {CFRetain((__bridge CFTypeRef)(obj));}}}const char *returnType = [methodSignature methodReturnType];NSString *selName = vk_selectorName(selector);if (strncmp(returnType, "v", 1) != 0 ) {if (strncmp(returnType, "@", 1) == 0) {void *result;[invocation getReturnValue:&result];if (result == NULL) {return nil;}id returnValue;if ([selName isEqualToString:@"alloc"] || [selName isEqualToString:@"new"] || [selName isEqualToString:@"copy"] || [selName isEqualToString:@"mutableCopy"]) {returnValue = (__bridge_transfer id)result;}else{returnValue = (__bridge id)result;}return returnValue;} else {switch (returnType[0] == 'r' ? returnType[1] : returnType[0]) {#define vk_CALL_RET_CASE(_typeString, _type) \case _typeString: {                              \_type returnValue; \[invocation getReturnValue:&returnValue];\return @(returnValue); \break; \}vk_CALL_RET_CASE('c', char)vk_CALL_RET_CASE('C', unsigned char)vk_CALL_RET_CASE('s', short)vk_CALL_RET_CASE('S', unsigned short)vk_CALL_RET_CASE('i', int)vk_CALL_RET_CASE('I', unsigned int)vk_CALL_RET_CASE('l', long)vk_CALL_RET_CASE('L', unsigned long)vk_CALL_RET_CASE('q', long long)vk_CALL_RET_CASE('Q', unsigned long long)vk_CALL_RET_CASE('f', float)vk_CALL_RET_CASE('d', double)vk_CALL_RET_CASE('B', BOOL)case '{': {NSString *typeString = vk_extractStructName([NSString stringWithUTF8String:returnType]);#define vk_CALL_RET_STRUCT(_type) \if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \_type result;   \[invocation getReturnValue:&result];\NSValue * returnValue = [NSValue valueWithBytes:&(result) objCType:@encode(_type)];\return returnValue;\}vk_CALL_RET_STRUCT(CGRect)vk_CALL_RET_STRUCT(CGPoint)vk_CALL_RET_STRUCT(CGSize)vk_CALL_RET_STRUCT(NSRange)vk_CALL_RET_STRUCT(CGAffineTransform)vk_CALL_RET_STRUCT(UIEdgeInsets)vk_CALL_RET_STRUCT(UIOffset)vk_CALL_RET_STRUCT(CGVector)}break;case '*':{}break;case '^': {}break;case '#': {}break;}return nil;}}return nil;
};static NSArray *vk_targetBoxingArguments(va_list argList, Class cls, SEL selector, NSError *__autoreleasing *error){NSMethodSignature *methodSignature = vk_getMethodSignature(cls, selector);NSString *selName = vk_selectorName(selector);if (!methodSignature) {NSString* errorStr = [NSString stringWithFormat:@"unrecognized selector (%@)", selName];vk_generateError(errorStr,error);return nil;}NSMutableArray *argumentsBoxingArray = [[NSMutableArray alloc]init];for (NSUInteger i = 2; i < [methodSignature numberOfArguments]; i++) {const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];switch (argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {#define vk_BOXING_ARG_CASE(_typeString, _type)\case _typeString: {\_type value = va_arg(argList, _type);\[argumentsBoxingArray addObject:@(value)];\break; \}\vk_BOXING_ARG_CASE('c', int)vk_BOXING_ARG_CASE('C', int)vk_BOXING_ARG_CASE('s', int)vk_BOXING_ARG_CASE('S', int)vk_BOXING_ARG_CASE('i', int)vk_BOXING_ARG_CASE('I', unsigned int)vk_BOXING_ARG_CASE('l', long)vk_BOXING_ARG_CASE('L', unsigned long)vk_BOXING_ARG_CASE('q', long long)vk_BOXING_ARG_CASE('Q', unsigned long long)vk_BOXING_ARG_CASE('f', double)vk_BOXING_ARG_CASE('d', double)vk_BOXING_ARG_CASE('B', int)case ':': {SEL value = va_arg(argList, SEL);NSString *selValueName = NSStringFromSelector(value);[argumentsBoxingArray addObject:selValueName];}break;case '{': {NSString *typeString = vk_extractStructName([NSString stringWithUTF8String:argumentType]);#define vk_FWD_ARG_STRUCT(_type, _methodName) \if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \_type val = va_arg(argList, _type);\NSValue* value = [NSValue _methodName:val];\[argumentsBoxingArray addObject:value];  \break; \}vk_FWD_ARG_STRUCT(CGRect, valueWithCGRect)vk_FWD_ARG_STRUCT(CGPoint, valueWithCGPoint)vk_FWD_ARG_STRUCT(CGSize, valueWithCGSize)vk_FWD_ARG_STRUCT(NSRange, valueWithRange)vk_FWD_ARG_STRUCT(CGAffineTransform, valueWithCGAffineTransform)vk_FWD_ARG_STRUCT(UIEdgeInsets, valueWithUIEdgeInsets)vk_FWD_ARG_STRUCT(UIOffset, valueWithUIOffset)vk_FWD_ARG_STRUCT(CGVector, valueWithCGVector)}break;case '*':{vk_generateError(@"unsupported char* argumenst",error);return nil;}break;case '^': {void *value = va_arg(argList, void**);vk_pointer *pointerObj = [[vk_pointer alloc]init];pointerObj.pointer = value;[argumentsBoxingArray addObject:pointerObj];}break;case '#': {Class value = va_arg(argList, Class);[argumentsBoxingArray addObject:(id)value];
//                vk_generateError(@"unsupported class argumenst",error);
//                return nil;}break;case '@':{id value = va_arg(argList, id);if (value) {[argumentsBoxingArray addObject:value];}else{[argumentsBoxingArray addObject:[vk_nilObject new]];}}break;default: {vk_generateError(@"unsupported argumenst",error);return nil;}}}return [argumentsBoxingArray copy];
}@implementation NSObject (VKMsgSend)+ (id)VKCallSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...{va_list argList;va_start(argList, error);SEL selector = NSSelectorFromString(selName);NSArray *boxingAruments = vk_targetBoxingArguments(argList, [self class], selector, error);va_end(argList);if (!boxingAruments) {return nil;}return vk_targetCallSelectorWithArgumentError(self, selector, boxingAruments, error);
}+ (id)VKCallSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...{va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, [self class], selector, error);va_end(argList);if (!boxingArguments) {return nil;}return vk_targetCallSelectorWithArgumentError(self, selector, boxingArguments, error);
}- (id)VKCallSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error,...{va_list argList;va_start(argList, error);SEL selector = NSSelectorFromString(selName);NSArray* boxingArguments = vk_targetBoxingArguments(argList, [self class], selector, error);va_end(argList);if (!boxingArguments) {return nil;}return vk_targetCallSelectorWithArgumentError(self, selector, boxingArguments, error);
}- (id)VKCallSelector:(SEL)selector error:(NSError *__autoreleasing *)error,...{va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, [self class], selector, error);va_end(argList);if (!boxingArguments) {return nil;}return vk_targetCallSelectorWithArgumentError(self, selector, boxingArguments, error);
}@end@implementation NSString (VKMsgSend)-(id)VKCallClassSelector:(SEL)selector error:(NSError *__autoreleasing *)error, ...
{Class cls = NSClassFromString(self);if (!cls) {NSString* errorStr = [NSString stringWithFormat:@"unrecognized className (%@)", self];vk_generateError(errorStr,error);return nil;}va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, cls, selector, error);va_end(argList);if (!boxingArguments) {return nil;}return vk_targetCallSelectorWithArgumentError(cls, selector, boxingArguments, error);
}-(id)VKCallClassSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error, ...
{Class cls = NSClassFromString(self);if (!cls) {NSString* errorStr = [NSString stringWithFormat:@"unrecognized className (%@)", self];vk_generateError(errorStr,error);return nil;}SEL selector = NSSelectorFromString(selName);va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, cls, selector, error);va_end(argList);if (!boxingArguments) {return nil;}return vk_targetCallSelectorWithArgumentError(cls, selector, boxingArguments, error);
}-(id)VKCallClassAllocInitSelector:(SEL)selector error:(NSError *__autoreleasing *)error, ...
{Class cls = NSClassFromString(self);if (!cls) {NSString* errorStr = [NSString stringWithFormat:@"unrecognized className (%@)", self];vk_generateError(errorStr,error);return nil;}va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, cls, selector, error);va_end(argList);if (!boxingArguments) {return nil;}id allocObj = [cls alloc];return vk_targetCallSelectorWithArgumentError(allocObj, selector, boxingArguments, error);
}-(id)VKCallClassAllocInitSelectorName:(NSString *)selName error:(NSError *__autoreleasing *)error, ...
{Class cls = NSClassFromString(self);if (!cls) {NSString* errorStr = [NSString stringWithFormat:@"unrecognized className (%@)", self];vk_generateError(errorStr,error);return nil;}SEL selector = NSSelectorFromString(selName);va_list argList;va_start(argList, error);NSArray* boxingArguments = vk_targetBoxingArguments(argList, cls, selector, error);va_end(argList);if (!boxingArguments) {return nil;}id allocObj = [cls alloc];return vk_targetCallSelectorWithArgumentError(allocObj, selector, boxingArguments, error);
}@end

至于怎么使用 。。。。。。。。。

#import "ViewController.h"
#import "VKMsgSend.h"
#import <objc/message.h>
@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Class cls = NSClassFromString(@"testClassA");id abc = [[cls alloc]init];NSError *err;//this warning is ok Selector is in testClassANSString *return1 = [abc VKCallSelector:@selector(testfunction:withB:) error:&err,4,3.5f];NSLog(@"%@",return1);NSNumber *return3 = [abc VKCallSelectorName:@"testfunction:withB:withC:" error:nil,4,3.5,@"haha"];NSInteger tureReturn3 = [return3 integerValue];NSLog(@"%@",@(tureReturn3));NSString *return4 = [abc VKCallSelectorName:@"testfunction:withB:withC:withD:" error:nil,4,3.5,nil, CGRectMake(10, 10, 10, 10)];NSLog(@"%@",return4);NSError* testerr2;[abc VKCallSelectorName:@"testFunctionError:" error:nil,&testerr2];NSLog(@"see more test case in XCTest Target");NSLog(@"vk_msgSend_projTests");//这是一段展示 performselector 缺点和不足的代码,有注释中文解释[self performShow];//这是一段展示 objc_msgsend 缺点和不足的代码,有注释和中文解释[self msgsendShow];//这是对比展示 VKMsgSend的代码[self vkshow];
}-(void)performShow
{Class cls = NSClassFromString(@"testClassA");id abc = [[cls alloc]init];//-(NSString*)testfunction:(int)num withB:(float)boolvNSString * result = [abc performSelector:@selector(testfunction:withB:) withObject:@4 withObject:@3.5];NSLog(@"%@",result);//并且只支持id,如果你敢把基础数值类型封装成number传进去,数值还是错乱的//这样代码跑进去  int 传了个NSNumber进去 函数内指针全乱,参数值都飞了//3个参数就不支持了,打开注释你会发现,就没有传3个参数的方法
//    [abc performSelector:@selector(testfunction:withB:withC:) withObject:@4.5 withObject:@3 withObject:@"ssss"];
}-(void)msgsendShow
{Class cls = NSClassFromString(@"testClassA");id abc = [[cls alloc]init];
//    NSString *result = objc_msgSend(abc, @selector(testfunction:withB:), 4, 3.5);//很抱歉上面这样的方法,看着用的很方便,但是在iOS 64位下会直接崩溃,xcode8下是直接无法编译NSString *result2 =  ((NSString* (*)(id, SEL, int,float))objc_msgSend)(abc, @selector(testfunction:withB:), 4, 3.5);//看到没必须这么费劲的写一坨C语言的函数指针强转才可以NSLog(@"%@",result2);
}-(void)vkshow
{//理想状态下 旧的 objc_msgSend就已经很方便了,但是已经不能这么用了,那我就封装出了一个runtime工具Class cls = NSClassFromString(@"testClassA");id abc = [[cls alloc]init];NSError * error;//很方便吧[abc VKCallSelectorName:@"testfunction:withB:" error:&error,4,3.5];//支持所有基础类型,结构体,id类型,class类型,selector类型,block类型,还有指针类型 **//如果是使用类方法,还可以直接通过类名NSString[@"testClassA" VKCallClassSelectorName:@"testfunction:withB:withH" error:&error,4,3.5,@"aaa"];//如果是实例方法,可以直接通过类名NSString,调用init selector,哪怕initWithXX:XX:等自定义的初始化函数都可以id abcc = [@"testClassA" VKCallClassAllocInitSelectorName:@"init" error:nil];NSLog(@"%@",abcc);//省去了手写NSClassFromString 的事情}

当然,这里附上github地址 https://github.com/Awhisper/VKMsgSend

performSelector多个参数相关推荐

  1. performSelector和传递参数

    performSelector和直接调用方法的区别 performSelector: withObject:是在iOS中的一种方法调用方式.他可以向一个对象传递任何消息,而不需要在编译的时候声明这些方 ...

  2. OC performSelector和传递参数

    performSelector和直接调用方法的区别 performSelector: withObject:是在iOS中的一种方法调用方式.他可以向一个对象传递任何消息,而不需要在编译的时候声明这些方 ...

  3. Objective-C基础学习笔记(七)-类的本质与SEL

    一.分类-Category 1.思考:如何在不改变原来类的模型的前提下,扩展分类的方法? 两种方式: 1>继承:子类可继承父类原有的方法,并且增加自己的方法. 2>分类;  可以给某个类扩 ...

  4. 不一样的方式实现performSelector接收多个参数(转)

    原文链接:http://www.jianshu.com/p/0c45b496686a 字数682 阅读263 评论4 喜欢2 开发中偶尔有需求使用performSelector实现多个参数, 常规的方 ...

  5. 关于 performSelector 的一些小探讨

    本文首发在我的个人博客: blog.shenyuanluo.com,喜欢的朋友欢迎订阅. 考虑以下代码,最终会输出什么? 例子①: - (void)viewDidLoad {[super viewDi ...

  6. performSelector may cause a leak because its selector is unknown

    转自:http://www.jianshu.com/p/6517ab655be7 问题 我在 ARC 模式下编译出了这个 warning: "performSelector may caus ...

  7. Objective-C中一种消息处理方法performSelector: withObject:

    Objective-C中调用函数的方法是"消息传递",这个和普通的函数调用的区别是,你可以随时对一个对象传递任何消息,而不需要在编译的时候声明这些方法.所以Objective-C可 ...

  8. NSObject中的performSelector用法简介

    - (id)performSelector:(SEL)aSelector Description [说明] Sends a specified message to the receiver and ...

  9. iOS 网络与多线程--7.Performselector消息处理方法

    创建一个IOSApp类 IOSApp.h文件 1 #import <Foundation/Foundation.h> 2 3 @interface IOSApp : NSObject 4 ...

最新文章

  1. 双柱状图柱子数量比较多_微生物组数据冲击图和柱状图一条代码解决
  2. PHP语言教父Gutmans炮轰Java:已经输掉Web之战
  3. 8.16模拟:树上算法
  4. linux : 各个发行版中修改python27默认编码为utf-8
  5. Spring 4 xml 注解配置谅解 spring
  6. react 遍历对象_React 和 Vue 之间的相爱相杀
  7. 云上“超算中心” 阿里云推出弹性高性能计算平台E-HPC
  8. 数据源、元数据、数据元
  9. MySQL十四:单表最大2000W行数据
  10. JavaScript学习手册五:JS数组
  11. 更改html默认浏览器,怎么更改默认浏览器?默认浏览器设置在哪里
  12. java开发微信公众号,公众号与java后台获取连接,自动回复,关注获取用户信息,取消关注删除用户信息
  13. 统信UOS_arm64开发环境配置
  14. 小议关键字del与实例方法__del__(self)
  15. python keyboard hook_[python] PyMouse、PyKeyboard用python操作鼠标和键盘
  16. solrcloud入门详细使用教程
  17. 数据库分类,市场上常见数据库
  18. CodeForces - 711A 找座位 难度:C++入门 复杂度:简单 翻译难度:难
  19. While 循环语句 和do while循环语句
  20. 解决复制项目或者svn下载项目后项目名称不改变的问题:org.eclipse.wst.common.component

热门文章

  1. 多少达芬奇发明实际起作用
  2. 【阅读材料精选 From-to-Date:2019.05.25~2019.06.28】
  3. nginx配置https登录,同时支持wss协议
  4. 中产热衷投资移民:卖北京四环一套房能移民美国
  5. 德国的吃--一篇很有意思的文章
  6. matlab中求分段函数的分段点,matlab求解分段函数问题是如何用下面的算法求解下面的分段函数 爱问知识人...
  7. 前端页面响应速度与性能优化总结
  8. mysql 过滤emoji表情_用JS过滤Emoji表情的输入
  9. python做FPGA EG01约束文件文本格式批量更改
  10. c语言计算阶乘的倒数和,for循环计算某个数的阶乘、阶乘和及其倒数的阶乘和...