UIAlertController基本使用与内存泄露分析!!!
最近开发过程中,发现内存会无故增加,在做内存优化的过程中,无意间发现了内存泄露的情况,那就是从iOS8.0 苹果开始推荐我们使用的UIAlertController!!!
看到这你是不是会嘲笑我第一次使用UIAlertController,居然还会出现内存泄露?我想说你 too young, too simple, sometimes naive,不闹了,言归正传:这篇文章介绍
的知识点保证你从来没有注意到过,喜欢的点个👍,下方留言。。。
#pragma mark -- 基本使用
//1.ActionSheet UIAlertController * actionSheet = [UIAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleActionSheet]; [actionSheet addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [actionSheet addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { //进行后续删除的操作... }]]; [self presentViewController:actionSheet animated:YES completion:nil]; //2.alert UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { //进行后续删除的操作... }]]; [self presentViewController:alert animated:YES completion:nil];
#pragma mark -- 复杂操作(内存泄露)
因为UIAlertControllerStyleActionSheet 样式的弹框不支持添加textField不在继续探究内存泄露的问题了!
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { //设置占位符,键盘样式什么的。。。 }]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { }]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { [self doSomethingWithAccount:alert.textFields.firstObject.text withPassword:alert.textFields.lastObject.text]; }]]; [self presentViewController:alert animated:YES completion:nil]; - (void)doSomethingWithAccount:(NSString *)account withPassword:(NSString *)password { //进行删除操作。。。 }
在控制器中实现dealloc方法 发现返回到上一级界面后,该控制器也成功的被销毁了。说好的内存泄露呢?
内存泄露证明
1、使用工具(查看内存使用大小)
因为我的XCode内存调试工具不能使用,只能使用其他的方法证明内存泄露了:最明显的就是内存增加,不断的弹框,然后点击确定,发现XCode的Memory不断的增加,测试发现内存占用从40M--->140M。
2、代码测试内存泄露 (查看是否销毁)
控制器销毁了,那么唯一可能内存泄露的就是alert弹框了! 没错!!! 相信你也一定想到,写一个类继承自UIAlertController 看看有没有走dealloc方法......
----------------------------------------------------------------------------------------------------------------------
EYAlertController.h
#import <UIKit/UIKit.h> @interface EYAlertController : UIAlertController @end
EYAlertController.m
#import "EYAlertController.h" @interface EYAlertController () @end @implementation EYAlertController - (void)dealloc { NSLog(@"-----自定义弹框类EYAlertController销毁了----"); } @end
在控制器中导入
#import "EYAlertController.h"
EYAlertController * alert = [EYAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { //设置占位符,键盘样式什么的。。。 }]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { }]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:alert animated:YES completion:nil];
弹框后点击取消或者确定,pop到上一个控制器。控制台输出:
弹框销毁了 测试控制器也销毁了 没有任何问题!!
-----------------------------------------------------------------------------------------------------------------
但是当我们添加下面这句话时:
[self doSomethingWithAccount:alert.textFields.firstObject.text withPassword:alert.textFields.lastObject.text];
控制没有输出任何语句,alert和控制器都没有销毁!!
就是这句话引起的内存泄露!!!
---------------------------------------------------------------------------------------------------
将弹框修改为如下代码
__weak typeof(self) weakSelf = self; EYAlertController * alert = [EYAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { //设置占位符,键盘样式什么的。。。 }]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { }]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf doSomethingWithAccount:alert.textFields.firstObject.text withPassword:alert.textFields.lastObject.text]; }]]; [self presentViewController:alert animated:YES completion:nil];
控制台输出:
证明: alert 自己没有及时回收导致了内存泄露!!!
原因分析: 因为测试环境是ARC环境,引起内存泄露的应该就是强引用循环了。而且是alert自己强引用循环了,alert没有销毁,又强引用着刚才的self才导致刚才的的控制器也没有销毁!!!
最终完美的的代码:
EYAlertController * alert = [EYAlertController alertControllerWithTitle:@"提示" message:@"是否删除?" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { //设置占位符,键盘样式什么的。。。 }]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { }]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; __weak typeof(alert) weakAlert = alert; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { __strong typeof(weakAlert) strongAlert = weakAlert; [self doSomethingWithAccount:strongAlert.textFields.firstObject.text withPassword:strongAlert.textFields.lastObject.text]; }]]; [self presentViewController:alert animated:YES completion:nil];
控制台输出测试结果:
图例解释原因:
以上就是UIAlertController中添加textField 后的使用注意点。
总结:
1、测试发现内存不断升高,也有可能是控件自身的强引用循环。
2、以后使用自己不熟悉的控件,一定要继承该控件,使用自己的控件,重写dealloc方法,观察控件有没有及时的销毁。
更多内容--> 博客导航 每周一篇哟!!!
有任何关于iOS开发的问题!欢迎下方留言!!!或者邮件lieryangios@126.com 虽然我不一定能够解答出来,但是我会请教iOS开发高手!!!解答您的问题!!!