zoukankan      html  css  js  c++  java
  • 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];
    
    
  • 相关阅读:
    压缩流GZipStream
    委托和事件
    .NET垃圾回收机制
    程序集相关知识
    生活
    poj 3767 I Wanna Go Home
    fw:Python GUI的设计工具
    How to configure an NTP client and server on CentOS/RedHat
    FW:Tripwire
    Bash if 判断 集合
  • 原文地址:https://www.cnblogs.com/GoodmorningMr/p/11973362.html
Copyright © 2011-2022 走看看