arc方法中局部变量viewcontroller无法获得相应回调事件( exc_bad_access)
来源:互联网 发布:arp攻击软件使用方法 编辑:程序博客网 时间:2024/06/14 18:15
- (IBAction)baseTap:(id)sender { NLMailComposerViewController *mail = [[NLMailComposerViewController alloc] init]; mail.delegate = self; [self.view addSubview: mail.view]; NSArray *toRecipients = [NSArray arrayWithObject:@"88888888@qq.com"]; NSString *subject = @"this is subject"; NSString *emailBody = @"this is body!"; [mail showMailPickerToRecipients:toRecipients subject:subject emailBody:emailBody isHTML:NO];}- (void)emailDidFinished:(NLMailComposerViewController *)mailComposerViewController{ NSLog(@"邮件发送后代理回调"); // mailComposerViewController. [mailComposerViewController.view removeFromSuperview]; }
在baseTap方法中我要present出邮件view,由于以上代码用了arc,所以在离开baseTap方法后mail.view的controller释放了,导致emailDidFinished回调时crash。
当然我们可以在这个类中定义一个NLMailComposerViewController属性来解决这个办法。但总觉的这个不是理想解决方案。
于是在https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html中找到了答案:
Each view controller object is the sole owner of its view. You must not associate the same view object with multiple view controller objects. The only exception to this rule is that a container view controller implementation may add this view as a subview in its own view hierarchy. Before adding the subview, the container must first call its addChildViewController: method to create a parent-child relationship between the two view controller objects.
addChildViewController可以解决view controller无法获得相应回调事件的问题!
代码更正:
- (IBAction)baseTap:(id)sender { NLMailComposerViewController *mail = [[NLMailComposerViewController alloc] init]; mail.delegate = self; [self.view addSubview: mail.view]; [self addChildViewController:mail]; NSArray *toRecipients = [NSArray arrayWithObject:@"522941939@qq.com"]; NSString *subject = @"this is subject"; NSString *emailBody = @"this is body!"; [mail showMailPickerToRecipients:toRecipients subject:subject emailBody:emailBody isHTML:NO];}- (void)emailDidFinished:(NLMailComposerViewController *)mailComposerViewController{ NSLog(@"邮件发送后代理回调"); // mailComposerViewController. [mailComposerViewController removeFromParentViewController]; [mailComposerViewController.view removeFromSuperview]; }
PS:
[mailComposerViewController removeFromParentViewController]; 这个是删除 self addChildViewController加进去的view controller实例。 其view实例还是需要用 [mailComposerViewController.view removeFromSuperview]来删除。)
BTW:
在苹果的WWDC2011大会视频的 《Session 101 - What’s New in Cocoa》 和 《Session 102 - Implementing UIViewController Containment》 中介绍了苹果在iOS5中给UIViewController新增加的5方法以及一个属性:
// 方法
addChildViewController:
removeFromParentViewController: transitionFromViewController:toViewController:duration:options:animations:completion: willMoveToParentViewController:
didMoveToParentViewController:
// 属性
@property(nonatomic,readonly) NSArray *childViewControllers
原来的问题:
这些新增的方法和属性用于改进我们的编程方式。那么让我们先看看以前的对于UIViewController的使用有什么潜在的问题,认清问题,我们才能理解苹果改变的意义。
在以前,一个UIViewController的View可能有很多小的子view。这些子view很多时候被盖在最后,我们在最外层ViewController的viewDidLoad方法中,用addSubview增加了大量的子view。这些子view大多数不会一直处于界面上,只是在某些情况下才会出现,例如登陆失败的提示view,上传附件成功的提示view,网络失败的提示view等。但是虽然这些view很少出现,但是我们却常常一直把它们放在内存中。另外,当收到内存警告时,我们只能自己手工把这些view从super view中去掉。
改变:
苹果新的API增加了addChildViewController方法,并且希望我们在使用addSubview时,同时调用[self addChildViewController:child]方法将sub view对应的viewController也加到当前ViewController的管理中。对于那些当前暂时不需要显示的subview,只通过addChildViewController把subViewController加进去。需要显示时再调用transitionFromViewController:toViewController:duration:options:animations:completion方法。
另外,当收到系统的Memory Warning的时候,系统也会自动把当前没有显示的subview unload掉,以节省内存。
参考:https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html
https://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10
关于addChildViewController使用的例子:
ios5中UIViewController addChildViewController等新方法
联想:在category中使用iOS扩展机制 - associative
- arc方法中局部变量viewcontroller无法获得相应回调事件( exc_bad_access)
- 获得字典表中相应的数据(静态方法)
- iPhone开发中,使用僵尸变量解决EXC_BAD_ACCESS方法
- iOS - 非ARC中EXC_BAD_ACCESS异常分析
- IOS中使用ARC和定时器导致viewController无法正常释放
- java web工作中获得相应路径的方法
- IOS 在viewcontroller中响应了点击事件后子视图无法响应点击事件
- java中类变量和方法局部变量的初始化
- gdb 局部变量无法查看
- MOSS中Button事件输出二进制流后无法再次相应按钮事件的解决办法
- MSP430中,局部变量
- C语言中定义变量的技巧(全局变量、局部变量、静态全局变量、静态局部变量)
- C语言中函数返回局部变量的方法
- 关于在内部类中访问一个方法中的局部变量
- keil mdk调试过程中查看局部变量的方法
- onTouch无法相应拖拽事件
- struts中获得URL中变量值得方法
- 为什么局部内部类只能访问方法中final类型的局部变量?
- Cocoa多线程编程之 block 与 dispatch quene
- C# DataTable中Compute方法用法集锦(数值/字符串/运算符/表等操作)(转载)
- UITableViewCell的4种显示格式
- objective-c 中随机数的用法 (3种:arc4random() 、random()、CCRANDOM_0_1() )
- Leetcode Longest Consecutive Sequence
- arc方法中局部变量viewcontroller无法获得相应回调事件( exc_bad_access)
- ORA-28000: the account is locked解决方案
- 纯HTML项目部署在NGINX,不用TOMCAT
- ios5中UIViewController addChildViewController等新方法
- loadrunner
- mysql 1129 错误Host is blocked because of many connection errors; unblock with 'mysqladmin flush-host
- loadNibNamed
- .net + EF EasyUI 增删改查
- Block开发浅谈