iOS 런타임의 간단한 사용
메시지 보내기
개발 사용 장면: 노출되지 않은 방법, 전제 조건, 이 방법은 이미 실현되었다.
#import
objc_msgSend 호출 방법 방법 방법 설명 필요 없음objcmsgSend 매개 변수
#import
@interface CallMeBoy : NSObject
//-(void)callMeNow;
//+(void)callMeNow;
//-(NSString *)callMeNowWithName:(NSString *)name;
@end
#import "CallMeBoy.h"
@implementation CallMeBoy
-(void)callMeNow{
NSLog(@"-%s",__func__);
}
+(void)callMeNow{
NSLog(@"+%s",__func__);
}
-(NSString *)callMeNowWithName:(NSString *)name{
if ([name isEqualToString:@" "]) {
return @"GLW";
}
return @"HZ";
}
@end
1. 대상 방법 호출
CallMeBoy *callMe = [[CallMeBoy alloc] init];
//1
[callMe callMeNow];
// ( )
objc_msgSend(callMe,@selector(callMeNow));
((void (*) (id, SEL)) (void *)objc_msgSend)(callMe, @selector(callMeNow));
((void (*) (id, SEL)) (void *)objc_msgSend)(callMe, sel_registerName("callMeNow"));
//
NSString *str = [callMe callMeNowWithName:@" "];
NSString *str1 = objc_msgSend(callMe, @selector(callMeNowWithName:), @" ");
NSString *str2 = ((NSString* (*)(id,SEL,NSString *))objc_msgSend)(callMe, @selector(callMeNowWithName:), @" ");
NSLog(@"%@--%@--%@",str,str1,str2);
2. 클래스 방법 호출
//2
[CallMeBoy callMeNow];//
[[CallMeBoy class] callMeNow];//
objc_msgSend([CallMeBoy class],@selector(callMeNow));
objc_msgSend([CallMeBoy class],sel_registerName("callMeNow"));
((void (*) (id, SEL)) (void *)objc_msgSend)([CallMeBoy class], @selector(callMeNow));
((void (*) (id, SEL)) (void *)objc_msgSend)([CallMeBoy class], sel_registerName("callMeNow"));
2. 교환 방법
개발 사용 장면: 시스템 자체의 방법 기능이 부족하고 시스템 자체의 방법에 기능을 확장하고 원래의 기능을 유지한다.
예:
[UIImage imageNamed:@" "];
이 그림은 비어 있을 때 인쇄2017-08-17 14:27:35.599 SocketGG[13015:1396365]
창설UIImage
분류#import "UIImage+image.h"
코드는 다음과 같다.#import
@interface UIImage (image)
@end
#import "UIImage+image.h"
#import
@implementation UIImage (image)
+(void)load{
//
// imageWithName
Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
// imageNamed
Method imageName = class_getClassMethod(self, @selector(imageNamed:));
// ,
method_exchangeImplementations(imageWithName, imageName);
}
// imageNamed, , super.
//
+ (instancetype)imageWithName:(NSString *)name {
// imageWithName, imageName
UIImage *image = [self imageWithName:name];
if (image == nil) {
NSLog(@" ");
}
return image;
}
@end
3. 동적 추가 방법
개발 사용 장면: 만약에 하나의 클래스 방법이 매우 많으면 클래스를 메모리에 불러올 때도 자원을 소모하기 때문에 모든 방법에 맵을 생성해야 한다. 동태적으로 특정한 클래스에 주고 방법을 추가하여 해결할 수 있다.
이 메커니즘에서 다루는 방법은 주로 두 가지가 있다.+ (BOOL)resolveInstanceMethod:(SEL)sel
+ (BOOL)resolveClassMethod:(SEL)sel
CallMeBoy 분류 코드는 다음과 같습니다classaddMethod 네 번째 매개 변수 의미 홈페이지 링크#import "CallMeBoy+CallWhat.h"
#import
// void(*)() //
void callMeBaby(id self,SEL _cmd) {
NSLog(@"%@ %@",self,NSStringFromSelector(_cmd));
}
//
void callYouThen(id self, SEL _cmd, NSString *name) {
NSLog(@"call you %@ ", name);
}
void callYouThenClass(id self, SEL _cmd, NSString *name) {
NSLog(@"call you %@ class", name);
}
@implementation CallMeBoy (CallWhat)
+(BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(callMeBaby)) {
// :
// :
// : ( )
// : ,( + ) v:void @: ->self : SEL->_cmd
class_addMethod(self, sel, (IMP)callMeBaby, "v@:");
return YES;
}
if (sel == @selector(callName)) {
class_addMethod([self class], sel, (IMP)callYouThen, "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
+(BOOL)resolveClassMethod:(SEL)sel{
if (sel == @selector(callNameClass)) {
class_addMethod(objc_getMetaClass("CallMeBoy"), sel,(IMP)callYouThenClass,"v#:@");
return YES;
}
return [super resolveClassMethod:sel];
}
@end
외부 호출 방법//
[callMe performSelector:@selector(callMeBaby)];
objc_msgSend(callMe,@selector(callMeBaby));
objc_msgSend(callMe,@selector(callName),@" ");
[callMe performSelector:@selector(callName) withObject:@" "];
//
objc_msgSend([CallMeBoy class], @selector(callNameClass), @" ");
인쇄 결과2017-08-17 16:13:38.611 SocketGG[18190:1936576] callMeBaby
2017-08-17 16:13:38.612 SocketGG[18190:1936576] callMeBaby
2017-08-17 16:13:38.612 SocketGG[18190:1936576] call you
2017-08-17 16:13:38.612 SocketGG[18190:1936576] call you
2017-08-17 16:13:42.037 SocketGG[18190:1936576] call you class
확장: performSelector Cocoa 내장에는 두 개의 매개 변수만 지원되고 여러 개의 매개 변수는 처리됩니다.
증가 방법-(id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 withObject:(id)object3 withObject:(id)object4 withObject:(id)object5{
NSMethodSignature *meSig = [self methodSignatureForSelector:aSelector];
if (meSig) {
NSInvocation* invo = [NSInvocation invocationWithMethodSignature:meSig];
[invo setTarget:self];
[invo setSelector:aSelector];
if (object1) {
[invo setArgument:&object1 atIndex:2];
}
if (object2) {
[invo setArgument:&object2 atIndex:3];
}
if (object3) {
[invo setArgument:&object3 atIndex:4];
}
if (object4) {
[invo setArgument:&object4 atIndex:5];
}
if (object5) {
[invo setArgument:&object5 atIndex:6];
}
[invo invoke];
if (meSig.methodReturnLength) {
id anObject;
[invo getReturnValue:&anObject];
return anObject;
} else {
return nil;
}
} else {
return nil;
}
}
사용void callYouThenMany(id self, SEL _cmd, NSString *one, NSString *two, NSString *three) {
NSLog(@"call you %@--%@--%@ ", one,two,three);
}
+(BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(callNameMany)) {
class_addMethod([self class], sel, (IMP)callYouThenMany, "v@:@@@");
}
return [super resolveInstanceMethod:sel];
}
[callMe performSelector:@selector(callNameMany) withObject:@"1" withObject:@"2" withObject:@"3" withObject:nil withObject:nil];
4. 분류에 속성 추가
원리: 하나의 클래스에 속성을 설명하는데 사실 본질은 이 클래스에 관련을 추가하는 것이다. 이 값의 메모리 공간을 클래스 메모리 공간에 직접 추가하는 것이 아니다.
분류에서 변수를 정의할 수 없고, Getter와setter 방법을 실현할 수 없으며,runtime 클래스로만 실현할 수 있습니다#import
@interface NSObject (Objc)
@property(nonatomic,copy)NSString *name;
@end
#import "NSObject+Objc.h"
#import
// key
static const char *key = "name";
@implementation NSObject (Objc)
- (NSString *)name {
// key, 。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name {
// :
// : key, key
// : value
// :
/*
OBJC_ASSOCIATION_ASSIGN; //assign
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy
OBJC_ASSOCIATION_RETAIN_NONATOMIC; //retain
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
외부 사용NSObject *objc = [[NSObject alloc] init];
objc.name = @" ";
NSLog(@"name--%@",objc.name);
2017-08-17 16:36:26.967 SocketGG[19114:2092692] name--
맺다
공부는 고통스럽고 즐거운 일이다. 배우지 않으면 재능을 넓힐 수 없고, 뜻이 없으면 학문을 이룰 수 없고, 순서에 따라 점진적으로 나아가면 천천히 하면 반드시 적게 축적하여 많이 될 수 있다.어려움을 알면 물러서고, 반은 알고 반은 알면서도, 그대와 함께 격려하지 마라.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
+ (BOOL)resolveInstanceMethod:(SEL)sel
+ (BOOL)resolveClassMethod:(SEL)sel
#import "CallMeBoy+CallWhat.h"
#import
// void(*)() //
void callMeBaby(id self,SEL _cmd) {
NSLog(@"%@ %@",self,NSStringFromSelector(_cmd));
}
//
void callYouThen(id self, SEL _cmd, NSString *name) {
NSLog(@"call you %@ ", name);
}
void callYouThenClass(id self, SEL _cmd, NSString *name) {
NSLog(@"call you %@ class", name);
}
@implementation CallMeBoy (CallWhat)
+(BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(callMeBaby)) {
// :
// :
// : ( )
// : ,( + ) v:void @: ->self : SEL->_cmd
class_addMethod(self, sel, (IMP)callMeBaby, "v@:");
return YES;
}
if (sel == @selector(callName)) {
class_addMethod([self class], sel, (IMP)callYouThen, "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
+(BOOL)resolveClassMethod:(SEL)sel{
if (sel == @selector(callNameClass)) {
class_addMethod(objc_getMetaClass("CallMeBoy"), sel,(IMP)callYouThenClass,"v#:@");
return YES;
}
return [super resolveClassMethod:sel];
}
@end
//
[callMe performSelector:@selector(callMeBaby)];
objc_msgSend(callMe,@selector(callMeBaby));
objc_msgSend(callMe,@selector(callName),@" ");
[callMe performSelector:@selector(callName) withObject:@" "];
//
objc_msgSend([CallMeBoy class], @selector(callNameClass), @" ");
2017-08-17 16:13:38.611 SocketGG[18190:1936576] callMeBaby
2017-08-17 16:13:38.612 SocketGG[18190:1936576] callMeBaby
2017-08-17 16:13:38.612 SocketGG[18190:1936576] call you
2017-08-17 16:13:38.612 SocketGG[18190:1936576] call you
2017-08-17 16:13:42.037 SocketGG[18190:1936576] call you class
-(id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 withObject:(id)object3 withObject:(id)object4 withObject:(id)object5{
NSMethodSignature *meSig = [self methodSignatureForSelector:aSelector];
if (meSig) {
NSInvocation* invo = [NSInvocation invocationWithMethodSignature:meSig];
[invo setTarget:self];
[invo setSelector:aSelector];
if (object1) {
[invo setArgument:&object1 atIndex:2];
}
if (object2) {
[invo setArgument:&object2 atIndex:3];
}
if (object3) {
[invo setArgument:&object3 atIndex:4];
}
if (object4) {
[invo setArgument:&object4 atIndex:5];
}
if (object5) {
[invo setArgument:&object5 atIndex:6];
}
[invo invoke];
if (meSig.methodReturnLength) {
id anObject;
[invo getReturnValue:&anObject];
return anObject;
} else {
return nil;
}
} else {
return nil;
}
}
void callYouThenMany(id self, SEL _cmd, NSString *one, NSString *two, NSString *three) {
NSLog(@"call you %@--%@--%@ ", one,two,three);
}
+(BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(callNameMany)) {
class_addMethod([self class], sel, (IMP)callYouThenMany, "v@:@@@");
}
return [super resolveInstanceMethod:sel];
}
[callMe performSelector:@selector(callNameMany) withObject:@"1" withObject:@"2" withObject:@"3" withObject:nil withObject:nil];
원리: 하나의 클래스에 속성을 설명하는데 사실 본질은 이 클래스에 관련을 추가하는 것이다. 이 값의 메모리 공간을 클래스 메모리 공간에 직접 추가하는 것이 아니다.
분류에서 변수를 정의할 수 없고, Getter와setter 방법을 실현할 수 없으며,runtime 클래스로만 실현할 수 있습니다
#import
@interface NSObject (Objc)
@property(nonatomic,copy)NSString *name;
@end
#import "NSObject+Objc.h"
#import
// key
static const char *key = "name";
@implementation NSObject (Objc)
- (NSString *)name {
// key, 。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name {
// :
// : key, key
// : value
// :
/*
OBJC_ASSOCIATION_ASSIGN; //assign
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy
OBJC_ASSOCIATION_RETAIN_NONATOMIC; //retain
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
외부 사용
NSObject *objc = [[NSObject alloc] init];
objc.name = @" ";
NSLog(@"name--%@",objc.name);
2017-08-17 16:36:26.967 SocketGG[19114:2092692] name--
맺다
공부는 고통스럽고 즐거운 일이다. 배우지 않으면 재능을 넓힐 수 없고, 뜻이 없으면 학문을 이룰 수 없고, 순서에 따라 점진적으로 나아가면 천천히 하면 반드시 적게 축적하여 많이 될 수 있다.어려움을 알면 물러서고, 반은 알고 반은 알면서도, 그대와 함께 격려하지 마라.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.