亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

iOS中實(shí)現(xiàn)檢測(cè)Zoombie對(duì)象的具體方法

 更新時(shí)間:2018年01月05日 10:49:24   作者:commer_cocoa  
這篇文章主要給大家介紹了關(guān)于iOS中實(shí)現(xiàn)檢測(cè)Zoombie對(duì)象的具體方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

前言

我們大家都知道,如果在XCode中開(kāi)啟了Zoombie Objects。如圖。

那么在一個(gè)對(duì)象釋放后,再次給該對(duì)象發(fā)送消息,在Xcode控制臺(tái)中,可看到如下打印信息。這些信息可以幫助我們定位問(wèn)題。

ZoombieDemo[12275:2841478] *** -[Test test]: message sent to deallocated instance 0x60800000b000

那么究竟XCode是如何實(shí)現(xiàn)僵尸對(duì)象的檢查的,我們將來(lái)一一揭曉。

實(shí)現(xiàn)原理

在《Effective Objective-C 》一書(shū)中有提到過(guò)僵尸指針的實(shí)現(xiàn)方式。

通過(guò)hook NSObject的dealloc的方法,在一個(gè)對(duì)象要釋放的時(shí)候,通過(guò)objcduplicateClass復(fù)制NSZombie類(lèi),生成NSZombieOriginaClass,并且將當(dāng)前對(duì)象的isa指向新生成的類(lèi)。這塊內(nèi)存不會(huì)釋放。

因?yàn)樵诮o該對(duì)象發(fā)消息時(shí),NSZombieOriginaClass并未實(shí)現(xiàn)原有類(lèi)的方法,所以會(huì)走完整的消息轉(zhuǎn)發(fā)。所以我們能取出具體的OriginaClass(去掉NS_Zombie),當(dāng)前sel,打印出來(lái)。

[class seletor]:message sent to deallocated instance 0x22909"

簡(jiǎn)單來(lái)說(shuō),就是將對(duì)象指向一個(gè)新的類(lèi),因?yàn)樾骂?lèi)里面并沒(méi)有原有類(lèi)方法的實(shí)現(xiàn),所以必定會(huì)走到消息轉(zhuǎn)發(fā)中。

以上說(shuō)的是動(dòng)態(tài)生成新的類(lèi),類(lèi)名是通過(guò)固定前綴拼接而成,將isa指向該類(lèi)。其實(shí)還有一種方式,就是指向固定的類(lèi),原有類(lèi)名通過(guò)關(guān)聯(lián)對(duì)象的方式來(lái)存儲(chǔ)。

既然知道了原理,可以動(dòng)手實(shí)現(xiàn)一下。

動(dòng)手實(shí)現(xiàn)

首先是hook dealloc方法。在NSObject+HookDealloc中實(shí)現(xiàn)。

+ (void)load {
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
  Class class = [self class];
  SEL originalSelector = NSSelectorFromString(@"dealloc");
  SEL swizzledSelector = @selector(swizzledDealloc);
  Method originalMethod = class_getInstanceMethod(class, originalSelector);
  Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);  
  BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
  if (success) {
   class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
  } else {
   method_exchangeImplementations(originalMethod, swizzledMethod);
  }
 });
}

動(dòng)態(tài)生成新的類(lèi)

在swizzledDealloc中,我們通過(guò)"Zoombie_"拼接原始類(lèi)名,得到一個(gè)新的類(lèi)名。然后生成該類(lèi),添加 forwardingTargetForSelector的實(shí)現(xiàn)。便于在消息轉(zhuǎn)發(fā)的時(shí)候得到調(diào)用信息。

NSString *Zoombie_Class_Prefix = @"Zoombie_";
// 指向動(dòng)態(tài)生成的類(lèi),用Zoombie拼接原有類(lèi)名
NSString *className = NSStringFromClass([self class]);
NSString *zombieClassName = [Zoombie_Class_Prefix stringByAppendingString: className]; 
Class zombieClass = NSClassFromString(zombieClassName);
if(zombieClass) return; 
zombieClass = objc_allocateClassPair([NSObject class], [zombieClassName UTF8String], 0); 
objc_registerClassPair(zombieClass);
class_addMethod([zombieClass class], @selector(forwardingTargetForSelector:), (IMP)forwardingTargetForSelector, "@@:@");
object_setClass(self, zombieClass);

forwardingTargetForSelector的方法實(shí)現(xiàn),原始類(lèi)名,去掉前綴即可得到。因?yàn)檫@里已經(jīng)是調(diào)用到已釋放對(duì)象的方法,我們直接abort掉,程序?qū)⒈罎ⅰ?/p>

id forwardingTargetForSelector(id self, SEL _cmd, SEL aSelector) {
 NSString *className = NSStringFromClass([self class]);
 NSString *realClass = [className stringByReplacingOccurrencesOfString:Zoombie_Class_Prefix withString:@""];
 NSLog(@"[%@ %@] message sent to deallocated instance %@", realClass, NSStringFromSelector(aSelector), self);
 abort();
}

指向固定類(lèi)

指向已有的ZoombieObject類(lèi),類(lèi)名存在關(guān)聯(lián)對(duì)象中。

 // 指向固定的類(lèi),原有類(lèi)名存儲(chǔ)在關(guān)聯(lián)對(duì)象中
NSString *originClassName = NSStringFromClass([self class]);
objc_setAssociatedObject(self, "OrigClassNameKey", originClassName, OBJC_ASSOCIATION_COPY_NONATOMIC);
object_setClass(self, [ZoombieObject class]);

同上,在ZoombieObject中實(shí)現(xiàn)forwardingTargetForSelector方法,可以得到調(diào)用信息。原始類(lèi)名通過(guò)關(guān)聯(lián)對(duì)象獲取。

- (id)forwardingTargetForSelector:(SEL)aSelector {
 NSLog(@"[%@ %@] message sent to deallocated instance %@", objc_getAssociatedObject(self, "OrigClassNameKey"), NSStringFromSelector(aSelector), self);
 abort();
}

forwardingTargetForSelector是消息轉(zhuǎn)發(fā)的第二步,我們也可以不在這里處理,等到最后一步forwardInvocation,不過(guò)要生成方法簽名,要略微復(fù)雜些。

要想走到forwardInvocation,methodSignatureForSelector返回不能是空。這里我們返回了StubProxy類(lèi)中stub的方法簽名(已經(jīng)定義好的類(lèi)和方法),最后就回走到forwardInvocation,通過(guò)invocation.selector可得到當(dāng)前調(diào)用方法名。通過(guò)關(guān)聯(lián)對(duì)象獲取到原始類(lèi)名。

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
 NSMethodSignature *sig = [super methodSignatureForSelector:aSelector];
 if (!sig) {
  sig = [StubProxy instanceMethodSignatureForSelector:@selector(stub)];
 } 
 return sig;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
 NSLog(@"[%@ %@] message sent to deallocated instance %@", objc_getAssociatedObject(self, "OrigClassNameKey"), NSStringFromSelector(anInvocation.selector), self);
}

這樣,一個(gè)簡(jiǎn)單的檢測(cè)僵尸指針的方案就實(shí)現(xiàn)了。

demo在此。

兩種方式都實(shí)現(xiàn)了,可通過(guò)調(diào)整NSObject+HookDealloc中,swizzledSelector的值來(lái)切換。my_dealloc是指向動(dòng)態(tài)類(lèi),swizzledDealloc是指向固定類(lèi)。

SEL swizzledSelector = @selector(my_dealloc);

在App運(yùn)行起來(lái)后,點(diǎn)擊button,即可觸發(fā)。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 使用UITextField限制只可輸入中,英文,數(shù)字的方法

    使用UITextField限制只可輸入中,英文,數(shù)字的方法

    在我們?nèi)粘i_(kāi)發(fā)中經(jīng)常遇到一些情況,要UITextField只能輸入某一種特定的字符.比如大寫(xiě)A-Z或者小寫(xiě)a-z,或者漢字.或者數(shù)字.那么該如何實(shí)現(xiàn)呢,下面通過(guò)這篇文章來(lái)看看吧。
    2016-09-09
  • iOS開(kāi)發(fā)之XLForm的使用方法

    iOS開(kāi)發(fā)之XLForm的使用方法

    這篇文章主要介紹了iOS開(kāi)發(fā)之XLForm的使用方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • IOS開(kāi)發(fā)OC代碼中創(chuàng)建Swift編寫(xiě)的視圖控制器

    IOS開(kāi)發(fā)OC代碼中創(chuàng)建Swift編寫(xiě)的視圖控制器

    這篇文章主要介紹了IOS開(kāi)發(fā)OC代碼中創(chuàng)建Swift編寫(xiě)的視圖控制器的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • IOS開(kāi)發(fā)基礎(chǔ)之二維數(shù)組詳解

    IOS開(kāi)發(fā)基礎(chǔ)之二維數(shù)組詳解

    這篇文章主要介紹了IOS開(kāi)發(fā)基礎(chǔ)之二維數(shù)組詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • iOS中謂詞(NSPredicate)的基本入門(mén)使用教程

    iOS中謂詞(NSPredicate)的基本入門(mén)使用教程

    這篇文章主要給大家介紹了關(guān)于iOS中謂詞(NSPredicate)的基本入門(mén)使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • iOS Crash常規(guī)跟蹤方法及Bugly集成運(yùn)用詳細(xì)介紹

    iOS Crash常規(guī)跟蹤方法及Bugly集成運(yùn)用詳細(xì)介紹

    這篇文章主要介紹了iOS Crash常規(guī)跟蹤方法及Bugly集成運(yùn)用詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • iOS常見(jiàn)宏理解及使用方法

    iOS常見(jiàn)宏理解及使用方法

    這篇文章主要給大家介紹了關(guān)于iOS常見(jiàn)宏理解及使用方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位iOS開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • iOS利用AFNetworking3.0——實(shí)現(xiàn)文件斷點(diǎn)下載

    iOS利用AFNetworking3.0——實(shí)現(xiàn)文件斷點(diǎn)下載

    這篇文章主要介紹了iOS利用AFNetworking3.0——實(shí)現(xiàn)文件斷點(diǎn)下載,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • iOS導(dǎo)航欄控制的一些總結(jié)

    iOS導(dǎo)航欄控制的一些總結(jié)

    這篇文章主要給大家介紹了關(guān)于iOS導(dǎo)航欄控制的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位iOS開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • iOS開(kāi)發(fā)之微信聊天工具欄的封裝

    iOS開(kāi)發(fā)之微信聊天工具欄的封裝

    這篇文章主要為大家詳細(xì)介紹了iOS開(kāi)發(fā)之微信聊天工具欄的封裝,針對(duì)聊天工具條進(jìn)行封裝,感興趣的小伙伴們可以參考一下
    2016-02-02

最新評(píng)論