iOS上Delegate的悬垂指针问题
【摘要】
- (void)popUpActionSheet
{
UIActionSheet* sheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:NSLocalizedString(@"str_cancel", @"")
destructiveButtonTitle:NSLocalizedString(@"str_delete", @"")
otherButtonTitles:nil];
[sheet showInView:self.view];
}
@property(nonatomic,assign) id delegate; // weak reference
-(void)viewDidAppear:(BOOL)animated
{
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"abcde" delegate:self cancelButtonTitle:@"cancel" destructiveButtonTitle:nil otherButtonTitles:nil]; NSLog(@"application windows:%@", [UIApplication sharedApplication].windows); [sheet showInView:self.view]; NSLog(@"self.window:%@", self.view.window);
NSLog(@"sheet.window:%@", sheet.window); NSLog(@"application windows:%@", [UIApplication sharedApplication].windows);
}
application windows:(
UIWindow ...
) // actionsheet弹出前,只有1个UIWindow self.window: UIWindow ...
sheet.window: _UIAlertOverlayWindow ... application windows:(
UIWindow ...
UITextEffectsWindow ...
_UIAlertOverlayWindow ...
) // actionsheet弹出后,有3个UIWindow
改用一个实例变量V保存actionsheet。在X的dealloc方法里置V.delegate = nil。
不用实例变量,想办法在delegate dealloc的时候获得actionsheet的指针。
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"sheet" delegate:self cancelButtonTitle:@"cancel" destructiveButtonTitle:nil otherButtonTitles:nil];
[sheet showInView:self.view]; [sheet setTag:kSheetTag]; NSLog(@"root(self.view.window):%@", [self.view.window viewWithTag:kSheetTag]); // null
NSLog(@"root(internal window):%@", [[UIApplication sharedApplication].windows[2] viewWithTag:kSheetTag]); // actionsheet found!
[[UIApplication sharedApplication].windows enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (strcmp(class_getName([obj class]),"_UIAlertOverlayWindow") == 0)
{
UIActionSheet *theSheet = (UIActionSheet *)[obj viewWithTag:kSheetTag];
[theSheet setDelegate:nil];
}
}];
[[UIApplication sharedApplication].windows enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self traverseView:obj];
}];
// 遍历view树
- (void)traverseView:(UIView *)root
{
[[root subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UIActionSheet class]])
{
if (((UIActionSheet *)obj).delegate == self)
{
((UIActionSheet *)obj).delegate = nil;
NSLog(@"enemy spotted!");
}
}
else
{
[self traverseView:obj];
}
}];
}
@interface DelegateBaseParasite : NSObject
{
NSMutableSet *sanctuarySet_; // 集合S
} // 创建并将自己(parasite)绑定(对应)到hostObj X 上
+ (DelegateBaseParasite *)parasitizeIn:(id)hostObj; // 返回已经绑定(对应)到hostObj X上的parasite对象(或nil若未绑定)
+ (DelegateBaseParasite *)getParasiteFromHost:(id)hostObj; // 添加一个对象object到此parasite的集合S中,当object.delegate = hostObj X的时候
- (void)addToSanctuary:(id)object; // 从此parasite的集合S中移除object,当object.delegate不再=X的时候
- (void)removeFromSanctuary:(id)object; // 将所有sanctuary中对象的delegate(此时都指向hostObj)置为nil
- (void)redemptionAll;
@end
#define kDelegateAssociativeParasiteSanctuaryKey "kDelegateAssociativeParasiteSanctuaryKey" @implementation DelegateAssociativeParasite #pragma mark -
#pragma public interface
+ (DelegateAssociativeParasite *)parasitizeIn:(id)hostObj
{
DelegateAssociativeParasite *parasite = [[DelegateAssociativeParasite alloc] init]; objc_setAssociatedObject(hostObj, &kDelegateAssociativeParasiteSanctuaryKey, parasite, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return parasite;
} + (DelegateAssociativeParasite *)getParasiteFromHost:(id)hostObj
{
return objc_getAssociatedObject(hostObj, &kDelegateAssociativeParasiteSanctuaryKey);
} - (void)Dealloc
{
[self redemptionAll];
} @end
[DelegateAutoUnregisterHelper registerDelegateAutoUnregisterTo:[UIActionSheet class]];
既然问题出在associate object上,那我们就不用它,想想有没有其它实现X与P一对一绑定(对应)的方法。这时我们又想起了weak指针。系统是怎么做到将object与指向其的weak指针集合绑定(对应)在一起的呢?
@implementation DelegateDictParasite + (DelegateDictParasite *)parasitizeIn:(id)hostObj
{
if (!class_getInstanceMethod([hostObj class], @selector(myHostObjDealloc)))
{
[DelegateDictParasite addNewMethodToHost:[hostObj class]];
[DelegateAutoUnregisterHelper mergeOldSEL:[DelegateAutoUnregisterHelper deallocSelector] NewSEL:@selector(myHostObjDealloc) ForClass:[hostObj class]];
[DelegateAutoUnregisterHelper mergeOldSEL:[DelegateAutoUnregisterHelper releaseSelector] NewSEL:@selector(myHostObjRelease) ForClass:[hostObj class]];
} DelegateDictParasite *parasite; @synchronized(kDelegateAssociativeParasiteLock)
{
if (!delegateHostParasiteHashTable)
{
delegateHostParasiteHashTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
} parasite = [[DelegateDictParasite alloc] init]; CFDictionarySetValue(delegateHostParasiteHashTable, (__bridge const void *)(hostObj), (__bridge const void *)(parasite));
} return parasite;
} + (DelegateDictParasite *)getParasiteFromHost:(id)hostObj
{
DelegateDictParasite *parasite; @synchronized(kDelegateAssociativeParasiteLock)
{
if (!delegateHostParasiteHashTable)
{
return nil;
} parasite = CFDictionaryGetValue(delegateHostParasiteHashTable, (__bridge const void *)(hostObj));
} return parasite;
} @end
iOS上Delegate的悬垂指针问题的更多相关文章
- 转iOS中delegate、protocol的关系
iOS中delegate.protocol的关系 分类: iOS Development2014-02-12 10:47 277人阅读 评论(0) 收藏 举报 delegateiosprocotolc ...
- IOS上传文件开发
IOS上传文件开发 在移动应用开发 文件形式上传是不可缺少的,近期把IOS这块文件上传文件代码简单的整理一下.假设大家有须要安卓这边的代码,本人也能够分享给大家! QQ群:74432915 ...
- 【转】iOS 上常用的两个功能:点击屏幕和return退出隐藏键盘和解决虚拟键盘挡住UITextField的方法
iOS上面对键盘的处理很不人性化,所以这些功能都需要自己来实现, 首先是点击return和屏幕隐藏键盘 这个首先引用双子座的博客 http://my.oschina.net/plumsoft/blog ...
- 细数iOS上的那些安全防护
细数iOS上的那些安全防护 龙磊,黑雪,蒸米 @阿里巴巴移动安全 0x00 序 随着苹果对iOS系统多年的研发,iOS上的安全防护机制也是越来越多,越来越复杂.这对于刚接触iOS安全的研究人员来说非 ...
- 微信双开是定时炸弹?关于非越狱iOS上微信分身高危插件ImgNaix的分析
作者:蒸米@阿里移动安全 序言 微信作为手机上的第一大应用,有着上亿的用户.并且很多人都不只拥有一个微信帐号,有的微信账号是用于商业的,有的是用于私人的.可惜的是官方版的微信并不支持多开的功能,并且频 ...
- ios上position:fixed失效问题
手机端上的猫腻真是多啊~~~ 此起彼伏! 最近又遇到了 固定定位的底部导航在ios上被弹出去 此时内心1w+个草泥马奔过~~~~~~~~ 直接上解决方案: <div class="ma ...
- :active 为什么在ios上失效
:active是针对鼠标,而手机上是没有鼠标,而是touchstart,所以早成了ios上不兼容 解决方法是: window.onload = function(){ document.body.ad ...
- 解决protobuf不能直接在IOS上使用,利用protobuf-net在IOS上通讯
---------------------------------------------------------------------------------------------------- ...
- iOS上简单推送通知(Push Notification)的实现
iOS上简单推送通知(Push Notification)的实现 根据这篇很好的教程(http://www.raywenderlich.com/3443/apple-push-notification ...
随机推荐
- Grid++Report——打印功能
一.安装下载 http://www.rubylong.cn/Download.htm 二.添加引用 三.添加类 四.制作打印模板 1.新增报表节 新增明细网格 新增列→设置为自由格→调整大小 报表→设 ...
- easyUI combobox下拉框很长,easyUI combobox下拉框如何显示滚动条的解决方法
如下图,combobox下拉框里内容很多时,会导致下拉框很长,很不美观. 如何使得combobox下拉框显示滚动条 方法:把属性panelHeight:"auto"注释掉即可. $ ...
- 微信小程序开发笔记2,底部导航栏tablebar
底部导航(要在app.js里面配置,也就是把导航的代码写到app.js) 官方文档说最少2个导航最多5个 , "tabBar": { "color": &quo ...
- 自己搞了20万张图片100个分类,tensorflow训练23万次后。。。。。。
自己搞了20万张图片100个分类,tensorflow训练23万次后...... 我自己把训练用的一张图片,弄乱之后做了一个预测 100个汉字,20多万张图片,tensorflow CNN训练23万次 ...
- 2018春招-今日头条笔试题5题(后附大佬答案-c++版)
1题目描述 在n个元素的数组中,找到差值为k的除重后的数字对 输入描述 第一行:n和k,n表示数字的个数,k表示差值 第二行:n个整数 输入样例 输入: 5 2 1 5 3 4 2 输出: 3 说明: ...
- pycharm 使用jupyter notebook 报错:'_xsrf' argument missing from POST
出问题的关键点就在: 我用cmd启动的jupyter notebook,然后用pycham新建了一个jupyter notebook 结果 一直报错'_xsrf' argument missing f ...
- javascript中的浅拷贝和深拷贝 分类: JavaScript 2015-05-07 15:29 831人阅读 评论(1) 收藏
1.js对象浅拷贝 简单的赋值就是浅拷贝.因为对象和数组在赋值的时候都是引用传递.赋值的时候只是传递一个指针. 看下面的实例代码: var a = [1,2,3]; var b =a ; var te ...
- android Butter Knife 使用详解
Butter Knife github连接:https://github.com/JakeWharton/butterknife 本文使用的butterknife版本7.0.1 butterknife ...
- Java_try,catch,finally return之间的执行顺序
以往认为函数只要执行到return语句便会返回结果并终止,然而这时错误的,因为这存在特例. 掌握下面几条原则就可以完全解决“当try.catch.finally遭遇return”的问题. 原则:1.f ...
- 使用fastjson进行转换
package junit.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; imp ...