Является ли метод извращением, а Иза - одним и тем же?
Является ли метод извращением, а Иза - одним и тем же? Если нет, то что такое свист?
1 ответ
Метод Swizzling
Метод swizzling обменивается реализацией двух методов класса во время выполнения. Это повлияет на каждый экземпляр, который был или будет создан, измененного класса.
Пример: предположим, что вы написали категорию для NSString:
@interface NSString (Swizzling)
@end
@implementation NSString (Swizzling)
- (NSString *)swizzled_uppercaseString {
//when the method is swizzled, the original method will be called
//with swizzled_uppercaseString (so this will not create a stack overflow).
NSString *result = [self swizzled_uppercaseString];
// our custom code
result = [result stringByAppendingString:@" (swizzled)"];
return result;
}
@end
Затем вы можете обменять реализацию uppercaseString
метод с swizzled_uppercaseString
метод, поэтому реализация swizzled_uppercaseString
метод выполняется, когда uppercaseString
называется. (И оригинальная реализация uppercaseString
выполняется при вызове swizzled_uppercaseString
):
#import <objc/runtime.h>
NSString *sample = @"abc";
// original method is called:
NSLog([sample uppercaseString]);
//Obtaining original and swizzled method:
original = class_getInstanceMethod([NSString class], @selector(uppercaseString));
swizzled = class_getInstanceMethod([NSString class], @selector(swizzled_uppercaseString));
//Exchange implementations here:
method_exchangeImplementations(original, swizzled);
// swizzled method is called:
NSLog([sample uppercaseString]); //prints "ABC (swizzled)"
ISA Swizzling
ISA swizzling изменяет свойство отдельного объекта, свойство ISA ('is a'), которое описывает класс объекта, поэтому вы можете обмениваться типом данного отдельного объекта с другим типом во время выполнения.
Пример: предположим, у вас есть эта структура классов:
@interface Sample : NSObject
@property (nonatomic) NSString *sampleStringToLoad;
@end
@implementation Sample
@synthesize sampleStringToLoad;
@end
@interface SampleWithStringLoader :NSObject
@property (nonatomic) NSString *sampleStringToLoad;
-(void)loadString;
@end
@implementation SampleWithStringLoader
@synthesize sampleStringToLoad;
-(void)loadString {
self.sampleStringToLoad = @"abc";
}
@end
Затем вы можете установить класс SampleWithStringLoader
, Итак sampleStringToLoad
-метод становится доступным:
#import <objc/runtime.h>
Sample *sample = [Sample new];
// switch isa to new class:
object_setClass(sample, [SampleWithStringLoader class]);
// invoke method that is only in SampleWithStringLoader:
[sample performSelector:@selector(loadString)];
// switch isa back to original class:
object_setClass(sample,[Sample class]);
// Prints 'abc':
NSLog(sample.sampleStringToLoad);