美文网首页iOS卖瓜大队
iOS 关于NSTimer随控制器释放问题

iOS 关于NSTimer随控制器释放问题

作者: BiBiMan | 来源:发表于2020-07-24 18:02 被阅读0次

凡事有因必有果,正如问题的发现必定伴随问题的解决。再来说标题中的问题,相信一路过来的同胞都可能遇到,勤快一点的肯定也积累了解决问题的一二三,本人班门弄斧来码篇文章。

首先本片文章暂不涉及Dispatch Source Timer 的使用以及注意事项,单单来谈谈NSTimer的释放问题,至于为什么会出现NSTimer释放不掉,本文章不再细究(无非就是多重强引用的问题),一般遇到NSTimer释放问题主要的解决方向:

一、主动添加invalidate事件(按钮事件、手势事件、代理回调等事件)

- (void)invalidateAction:(id)sender {

    [timer invalidate]; // timer 为定义的NSTimer变量

}

二、自定义类承载target

@interface CustomTimerTarget : NSObject

@property(nonatomic,weak)idtarget;

@property(nonatomic,assign) SEL selector;

@property(nonatomic,weak)NSTimer* timer;

@end

@implementation CustomTimerTarget

@end

三、使用block块来实现计时业务代码

+ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block userInfo:(id)userInfo repeats:(BOOL)repeats {

    return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(timeBlockAction:) userInfo:@[[block copy], userInfo] repeats:repeats];

}

+ (void)timeBlockAction:(NSArray*)userInfo {

void (^block)() = userInfo[0];

id info = userInfo[1];

if(block) {

        block(info);

    }

}

然后就可以在block中编写美丽的代码了:

-(void)customTimerAction:(id)sender{

NSTimer *timer = [NSTimer TimerscheduledTimerWithTimeInterval:3.0f block:^(id userInfo) {

    NSLog(@"%@", userInfo);

}userInfo:@"Fire"repeats:YES];

    [timer fire];

}

到此问题解决,ViewController完美调用dealloc ,多年的“便秘”药到病除。

以上解决方法基本被大家熟知,所以再来加点新鲜的,直接上菜:

▶︎1.ios 10之后苹果提供了新的API

+ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)intervalrepeats:(BOOL)repeatsblock:(void(^)(NSTimer*timer))blockAPI_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

/// - parameter:  block  The execution body of the timer; the timer itself is passed as the parameter to this block when executed to aid in avoiding cyclical references

说明文档中也提到了cyclical references,此API可以避免循环引用的问题;

Demo:

__weak typeof(self) weakSelf = self;

    NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {

        weakSelf.testLab.text =@"***";

        //demo

        if (/** condition **/) {

            [timer invalidate];

        }

    }];

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

▶︎2.换个思维考虑,VC(ViewController)在被pop和dissmiss后,视图层的肯定会有所变化,所以沿着这条线又发现新大陆:

VC在pop和dismiss前,view也存在一个superView,也就是view的载体Wrapper视图

view存在一个包装层

在VC被pop和dismiss后,view也从WrapperView中移除

view从包装层移除

根据以上思路又可以愉快地敲那美丽的代码:

- (IBAction)startTimerAction:(id)sender {

    NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(customTimerEvent:) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

}

- (void)customTimerEvent:(NSTimer*)timer {

    //demo

    if (!self.view.superview) {

        [timer invalidate];

        return;

    }

    if (/** condition **/) {

        [timer invalidate];

    }

}

最后VC又完美的dealloc,到此本文章也告一段落。

上述内容,如有错误,欢迎指教(⁎⁍̴̛ᴗ⁍̴̛⁎)

相关文章

网友评论

    本文标题:iOS 关于NSTimer随控制器释放问题

    本文链接:https://www.haomeiwen.com/subject/iiajlktx.html