• NSTimer内存泄漏的解决方案


        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    

    由于NSTimer会持有我们设置的target对象,而RunLoop也会对timer对象持有,主线程的RunLoop是一直存在的,即便设置为weak属性timer也不会被释放,所以在上面的方式添加定时器时会造成内存的泄露,解决上面的问题可以通过将timer设置为属性在对象即将消失的方法中对timer对象进行释放从而解决循环引用,代码如下:

    @property (nonatomic, strong) NSTimer * timer;
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
        
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        [self.timer invalidate];
        self.timer = nil;
    }
    

    在上面的方法中需要我们手动调用timer的释放工作从而解决存在的循环引用问题,对待此类问题的另一种解决方案是通过一个中间对象A持有timer,在A中判断target对象是否还存在并决定timer是否需要释放,从而解决每次都需要手动释放timer的问题,代码如下:

    // category的.h
    #import <Foundation/Foundation.h>
    
    @interface NSTimer (WeakTimer)
    + (NSTimer *)scheduledWeakTimerWithTimeInterval:(NSTimeInterval)interval
      target:(id)aTarget
    selector:(SEL)aSelector
    userInfo:(id)userInfo
     repeats:(BOOL)repeats;
    @end
    
    // category的.m
    #import "NSTimer+WeakTimer.h"
    
    @interface TimerWeakObject : NSObject
    @property (nonatomic, weak) id target;
    @property (nonatomic, assign) SEL selector;
    @property (nonatomic, weak) NSTimer *timer;
    
    - (void)fire:(NSTimer *)timer;
    @end
    
    @implementation TimerWeakObject
    
    - (void)fire:(NSTimer *)timer
    {
        if (self.target) {
            if ([self.target respondsToSelector:self.selector]) {
                [self.target performSelector:self.selector withObject:timer.userInfo];
            }
        }
        else{
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    
    @end
    
    @implementation NSTimer (WeakTimer)
    + (NSTimer *)scheduledWeakTimerWithTimeInterval:(NSTimeInterval)interval
                                             target:(id)aTarget
                                           selector:(SEL)aSelector
                                           userInfo:(id)userInfo
                                            repeats:(BOOL)repeats
    {
        TimerWeakObject *object = [[TimerWeakObject alloc] init];
        object.target = aTarget;
        object.selector = aSelector;
        object.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:object selector:@selector(fire:) userInfo:userInfo repeats:repeats];
        return object.timer;
    }
    @end
    
    //调用,无需手动释放所以不需要声明成员变量
    [[NSRunLoop currentRunLoop] addTimer:[NSTimer scheduledWeakTimerWithTimeInterval:1.0 target:self selector:@selector(test) userInfo:nil repeats:YES] forMode:NSDefaultRunLoopMode];
    
    
  • 相关阅读:
    数值的格式化
    最近开发的一个多功能选择器
    OCI22053: 溢出错误的原因和解决方法
    js的四舍五入问题
    Vista 下先安装 VS 再装 IIS 7 运行出现 500.19 Error 的解决方法
    最近开发的一个多功能选择器2
    Oracle REF Cursor 用法(转帖)
    Oracle 查询历史数据(转帖)
    HDU 1203 I NEED A OFFER! 动态规划(01背包)
    HDU 1160 FatMouse's Speed 动态规划
  • 原文地址:https://www.cnblogs.com/GoodmorningMr/p/11973362.html
Copyright © 2020-2023  润新知