자체 NSZombie 구축

12056 단어
xcode zombie 옵션을 켜서 '방출된 대상' 으로 메시지를 보낼 때
    ObjZomies *oz = [[ObjZomies  alloc] init];
    oz.name = @"obz";
    
    NSLog(@"ObjZomies :----%@---%s---%p",[ObjZomies class],object_getClassName(oz),oz);
    [oz release];
    
    NSLog(@"ObjZomies :-------%@----%s----%p",[ObjZomies class],object_getClassName(oz),oz);
    
    oz.name = @"z----o";

인쇄 결과:
2015-10-27 17:32:43.303 Zombies[68811:1009530] ObjZomies :----ObjZomies---ObjZomies---0x7fcb71f047c0
2015-10-27 17:32:43.304 Zombies[68811:1009530] ObjZomies :-------ObjZomies----_NSZombie_ObjZomies----0x7fcb71f047c0
2015-10-27 17:32:43.304 Zombies[68811:1009530] *** -[ObjZomies setName:]: message sent to deallocated instance 0x7fcb71f047c0

신기한데...분석 로그에서 다음 정보를 얻을 수 있습니다.
1, 우리는'방출된 대상'ObjZomies에 setName: 방법을 보냈습니다.
2, oz가 release 앞뒤로 ObjectgetClassName(oz) 인쇄 결과가 다릅니다. 즉, oz의 isa가 가리키는 class가 0.0으로 바뀌었습니다.
ObjZomies와NSZombie_ObjZomies  
3, 그 세 개의%p가 모두 같은 0x7fcb71f047c0이라는 것을 알아차리지 못했는가? 이것은 oz 이 물건이release 이후에 따로 방출되지 않았다는 것을 설명한다.
그래서'이미 풀린 대상'은 풀리지 않고'좀비'로 변해 프로그램이 실행되는 동안 메모리에 머물렀다.물론 xcode zombie 옵션을 사용하면 모든 종류가'좀비'로 변하는 것을 피할 수 없습니다
 
 _NSZombie_ObjZomies는 당연히 실행할 때 추가된 클래스입니다. KVO처럼 목표 클래스가 A라면 실행할 때 특수한 기능을 가진 클래스 xxxA는 일부 기능을 행사한다.
_NSZombie_ 접두사 + ObjZomies는 실행할 때 만들어진 좀비 포착 기능 클래스를 구성합니다.
 
 
_NSZombie_MyClass는 좀비류를 잡는 것이고,
'이미 방출된 대상'에게 메시지를 보낼 때 이상을 촉발할 수 있는 메커니즘을 포착하고 개발자에게 구체적으로 방출된 클래스와 어떤 메시지를 보냈는지 알려주는 역할을 한다.
이것은 oc의 강력한 동태성과 메시지 전달 메커니즘에 의존한다.
원리를 간략하게 요약하다.
클래스 A의 실례 a의 인용 계수가 0일 때,delloc를 호출하여 메모리 정리 작업을 합니다. 물론 기본 클래스는 NSobject가 최종적으로 NSObject의 dealloc로 이동하는 것입니다.이때 만약 그것을 다 가게 한다면 a도 석방될 것이다.우리도 영원히 그것이 누군지 모른다.
그래서 a를 방출할 수 없다. a를'좀비'로 만들 수 있다. 즉, a의 메모리가 프로그램이 실행될 때 좀비를 잡는 클래스 B를 만들고 메시지가 a로 전송될 때 B에 이상을 던지며 관련 정보를 제시한다.즉, a-isa-->B는 a의 이사 바늘을 B에게 가리키고, (여기서 이해하지 못하는 것은 공부를 잘해야 한다) 그러면 a는 이사로 B에서 대응하는 것을 찾아낸다.
 
구현은 다음과 같습니다.
주의m 환경이 ARC가 아닌 경우 xcode zombie 관련 옵션 켜기
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import <objc/runtime.h>
#import "ObjZomies.h"

void EmpthIMP(id obj,SEL _cmd){}


NSMethodSignature * ZombieMethodSignatureForSelector(id obj,SEL _cmd,SEL selector){
    Class class = object_getClass(obj);
    NSString *className = NSStringFromClass(class);
    className = [className substringFromIndex:[@"CMZombie_" length]];
    
    NSLog(@"Selector %@ sent to deallocated instance %p of class %@", NSStringFromSelector(selector), obj, className);
    abort();
  
    return nil;
}


Class ZombifyClass(Class class){
    
    NSString * className = NSStringFromClass(class);
    NSString *zombieClassName = [@"CMZombie_" stringByAppendingString:className];
    
    Class zombieClass = NSClassFromString(zombieClassName);
    if (zombieClass) {
        return zombieClass;
    }
    // NSZombie
    zombieClass = objc_allocateClassPair(nil, [zombieClassName UTF8String], 0);
    class_addMethod(zombieClass, @selector(methodSignatureForSelector:), (IMP)ZombieMethodSignatureForSelector, "@@::");
// ,+initialize MetaClass , Class 。 class_addMethod(object_getClass(zombieClass), @selector(initialize), (IMP)EmpthIMP,
"v@:"); objc_registerClassPair(zombieClass); return zombieClass; } void ZombieDealloc(id obj,SEL _cmd){ Class c = ZombifyClass(object_getClass(obj));
// obj isa " " _NSZombie_MyClass object_setClass(obj, c); }
void EnableZombies(void){ Method m = class_getInstanceMethod([NSObject class],@selector(dealloc)); method_setImplementation(m , (IMP)ZombieDealloc); }

int main(int argc, char * argv[]) { // EnableZombies(); ObjZomies *oz = [[ObjZomies alloc] init]; oz.name = @"obz"; NSLog(@"ObjZomies :----%@---%s---%p",[ObjZomies class],object_getClassName(oz),oz); [oz release]; NSLog(@"ObjZomies :-------%@----%s----%p",[ObjZomies class],object_getClassName(oz),oz); oz.name = @"z----o"; @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
#import <Foundation/Foundation.h>

@interface ObjZomies : NSObject
@property (nonatomic,copy) NSString *name;

@end

#import "ObjZomies.h"

@implementation ObjZomies
@end

 
다시 실행:
2015-10-27 17:55:55.433 Zombies[68883:1030347] ObjZomies :----ObjZomies---ObjZomies---0x7f825ae00790
2015-10-27 17:55:55.435 Zombies[68883:1030347] ObjZomies :-------ObjZomies----CMZombie_ObjZomies----0x7f825ae00790
2015-10-27 17:55:55.435 Zombies[68883:1030347] Selector setName: sent to deallocated instance 0x7f825ae00790 of class ObjZomies

so cool .
 
     
참조:https://www.mikeash.com/pyblog/friday-qa-2014-11-07-lets-build-nszombie.htmlhttp://www.cocoachina.com/ios/20141204/10526.html

좋은 웹페이지 즐겨찾기