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开发高手!!!解答您的问题!!!

 

posted on 2017-10-09 14:44  人生为代码而活  阅读(1093)  评论(0编辑  收藏  举报

导航