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 ...
随机推荐
- 剑指offer四十三之左旋转字符串
一.题目 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abc ...
- 关于MyBatis的工作流程和与JDBC的比较与Hibernate的比较
一.传统的JDBC的方式 1.从一个jdbc程序开始 public static void main(String[] args) { Connection connection = null; Pr ...
- 【kafka】kafka.admin.AdminOperationException: replication factor: 1 larger than available brokers: 0
https://blog.csdn.net/bigtree_3721/article/details/78442912 I am trying to create topics in Kafka by ...
- 【Java并发编程】:生产者—消费者模型
生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 这里实现如下情况的生产--消费模型: 生产者不断交替地生产两组数据“姓 ...
- ES6-Object‘s Extends
依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js <!DOCTYPE html> <html&g ...
- Spring MVC 实现web Socket向前端实时推送数据
最近项目中用到了webSocket服务,由后台实时向所有的前端推送消息,前端暂时是不可以发消息给后端的,数据的来源是由具体的设备数据收集器收集起来,然后通过socket推送给后端,后端收到数据后,再将 ...
- Global Embedding 理解
1.Attention-based seq2seq e(t,i):求上一时刻的输出和这一时刻编码器的输出的相似度 a(t,i):求这个词在整个文本中占多大的比重,每个时刻都存在着一个值,这个只是求一个 ...
- Android之网络丢包事件
原文链接 http://www.litrin.net/2013/03/01/android%E4%B9%8B%E7%BD%91%E7%BB%9C%E4%B8%A2%E5%8C%85%E4%BA%8B% ...
- webstorm皮肤外观样式快速设置,CMD的使用方法,webstorm11激活方法
一.皮肤外观设置 因为这里是上班时间写的,其客套话就不多bb.步入正题 1.首先设置webstorm整体面板颜色 file->settings->Appearance&Behavi ...
- 匿名函数、闭包、lambda表达式、Block
C#有lambda.匿名函数,js有匿名函数.闭包,OC中有block,看到这是不是心中有一万个草泥马在跑,不过它们这些都是换汤不换药,不同语言名字不一样. 从功能性上说lambda和closure( ...