This commit is contained in:
2025-11-06 13:18:27 +08:00
parent abf32e8457
commit d7874829d9
48 changed files with 6952 additions and 2389 deletions

19
Pods/LSTTimer/LICENSE generated Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2020 490790096@qq.com <LoSenTrad@163.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

165
Pods/LSTTimer/LSTTimer/Classes/LSTTimer.h generated Normal file
View File

@@ -0,0 +1,165 @@
//
// LSTTimer.h
// LSTTimer
//
// Created by LoSenTrad on 2020/7/13.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^LSTTimerChangeBlock)(NSString *day, NSString *hour, NSString *minute, NSString *second, NSString *ms);
typedef void(^LSTTimerFinishBlock)(NSString *identifier);
typedef void(^LSTTimerPauseBlock)(NSString *identifier);
/** 倒计时变化通知类型 */
typedef NS_ENUM(NSInteger, LSTTimerSecondChangeNFType) {
LSTTimerSecondChangeNFTypeNone = 0,
LSTTimerSecondChangeNFTypeMS, //每100ms(毫秒) 发出一次
LSTTimerSecondChangeNFTypeSecond, //每1s(秒) 发出一次
};
@interface LSTTimer : NSObject
/** 单例 */
LSTTimer *LSTTimerM(void);
#pragma mark - ***** 配置计时任务通知回调 *****
/// 设置倒计时任务的通知回调
/// @param name 通知名
/// @param identifier 倒计时任务的标识
/// @param type 倒计时变化通知类型
+ (void)setNotificationForName:(NSString *)name identifier:(NSString *)identifier changeNFType:(LSTTimerSecondChangeNFType)type;
#pragma mark - ***** 添加计时任务(100ms回调一次) *****
/// 添加计时任务
/// @param time 时间长度
/// @param handle 每100ms回调一次
+ (void)addTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle;
/// 添加计时任务
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
+ (void)addTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle;
/// 添加计时任务
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
/// @param finishBlock 计时完成回调
/// @param pauseBlock 计时暂停回调
+ (void)addTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock;
/// 添加计时任务,持久化到硬盘
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
+ (void)addDiskTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle;
/// 添加计时任务,持久化到硬盘
/// @param time 添加计时任务,持久化到硬盘
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
/// @param finishBlock 计时完成回调
/// @param pauseBlock 计时暂停回调
+ (void)addDiskTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock;
#pragma mark - ***** 添加计时任务(1s回调一次) *****
/// 添加计时任务
/// @param time 时间长度
/// @param handle 计时任务标识
+ (void)addMinuteTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle;
/// 添加计时任务
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
+ (void)addMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle;
/// 添加计时任务
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
/// @param finishBlock 计时完成回调
/// @param pauseBlock 计时暂停回调
+ (void)addMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock;
/// 添加计时任务
/// @param time 时间长度
/// @param identifier 计时任务标识
/// @param handle 每100ms回调一次
/// @param finishBlock 计时完成回调
/// @param pauseBlock 计时暂停回调
+ (void)addDiskMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock;
#pragma mark - ***** 获取计时任务时间间隔 *****
/// 通过任务标识获取 计时任务 间隔(毫秒)
/// @param identifier 计时任务标识
+ (NSTimeInterval)getTimeIntervalForIdentifier:(NSString *)identifier;
#pragma mark - ***** 暂停计时任务 *****
/// 通过标识暂停计时任务
/// @param identifier 计时任务标识
+ (BOOL)pauseTimerForIdentifier:(NSString *)identifier;
/// 暂停所有计时任务
+ (void)pauseAllTimer;
#pragma mark - ***** 重启计时任务 *****
/// 通过标识重启 计时任务
/// @param identifier 计时任务标识
+ (BOOL)restartTimerForIdentifier:(NSString *)identifier;
/// 重启所有计时任务
+ (void)restartAllTimer;
#pragma mark - ***** 重置计时任务(恢复初始状态) *****
/// 通过标识重置 计时任务
/// @param identifier 计时任务标识
+ (BOOL)resetTimerForIdentifier:(NSString *)identifier;
/// 重置所有计时任务
+ (void)resetAllTimer;
#pragma mark - ***** 移除计时任务 *****
/// 通过标识移除计时任务
/// @param identifier 计时任务标识
+ (BOOL)removeTimerForIdentifier:(NSString *)identifier;
/// 移除所有计时任务
+ (void)removeAllTimer;
#pragma mark - ***** 格式化时间 *****
/// 将毫秒数 格式化成 时:分:秒:毫秒
/// @param time 时间长度(毫秒单位)
/// @param handle 格式化完成回调
+ (void)formatDateForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle;
@end
NS_ASSUME_NONNULL_END

790
Pods/LSTTimer/LSTTimer/Classes/LSTTimer.m generated Normal file
View File

@@ -0,0 +1,790 @@
//
// LSTTimer.m
// LSTTimer
//
// Created by LoSenTrad on 2020/7/13.
//
#import "LSTTimer.h"
#define LSTPopViewTimerPath(name) [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"LSTTimer_%@_Timer",name]]
@interface LSTPopViewTimerModel : NSObject
/** */
@property (nonatomic, assign) NSTimeInterval time;
/** */
@property (nonatomic, assign) NSTimeInterval oriTime;
/** */
@property (nonatomic, assign) NSTimeInterval unit;
/** block */
/** */
@property (nonatomic,assign) BOOL isDisk;
/** */
@property (nonatomic,assign) BOOL isPause;
/** */
@property (nonatomic, copy) NSString *identifier;
/** */
@property (nonatomic, copy) NSString *NFName;
/** 0. 1. 2. */
@property (nonatomic, assign) LSTTimerSecondChangeNFType NFType;
@property (nonatomic, copy) LSTTimerChangeBlock handleBlock;
/** block */
@property (nonatomic, copy) LSTTimerFinishBlock finishBlock;
/** block */
@property (nonatomic, copy) LSTTimerPauseBlock pauseBlock;
+ (instancetype)timeInterval:(NSInteger)timeInterval;
@end
@implementation LSTPopViewTimerModel
+ (instancetype)timeInterval:(NSInteger)timeInterval {
LSTPopViewTimerModel *object = [LSTPopViewTimerModel new];
object.time = timeInterval*1000;
object.oriTime = timeInterval*1000;
return object;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeDouble:self.time forKey:@"timeInterval"];
[aCoder encodeDouble:self.oriTime forKey:@"oriTime"];
[aCoder encodeDouble:self.unit forKey:@"unit"];
[aCoder encodeBool:self.isDisk forKey:@"isDisk"];
[aCoder encodeBool:self.isPause forKey:@"isPause"];
[aCoder encodeObject:self.identifier forKey:@"identifier"];
[aCoder encodeBool:self.NFType forKey:@"NFType"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.time = [aDecoder decodeDoubleForKey:@"timeInterval"];
self.oriTime = [aDecoder decodeDoubleForKey:@"oriTime"];
self.unit = [aDecoder decodeDoubleForKey:@"unit"];
self.isDisk = [aDecoder decodeBoolForKey:@"isDisk"];
self.isPause = [aDecoder decodeBoolForKey:@"isPause"];
self.identifier = [aDecoder decodeObjectForKey:@"identifier"];
self.NFType = [aDecoder decodeBoolForKey:@"NFType"];
}
return self;
}
@end
@interface LSTTimer ()
@property (nonatomic, strong) NSTimer * _Nullable showTimer;
/** */
@property (nonatomic, strong) NSMutableDictionary<NSString *, LSTPopViewTimerModel *> *timerMdic;
@end
@implementation LSTTimer
static LSTTimer *_instance;
LSTTimer *LSTTimerM() {
return [LSTTimer sharedInstance];
}
+ (instancetype)sharedInstance {
if (!_instance) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
}
return _instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
///
/// @param name
/// @param identifier
/// @param type
+ (void)setNotificationForName:(NSString *)name identifier:(NSString *)identifier changeNFType:(LSTTimerSecondChangeNFType)type {
if (identifier.length<=0) {
NSLog(@"计时器标识不能为空");
return;
}
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
if (model) {
model.NFType = type;
model.NFName = name;
return;
}else {
NSLog(@"找不到计时器任务");
return;
}
}
/** */
+ (void)addTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle {
[self initTimerForForTime:time identifier:nil ForIsDisk:NO unit:0 handle:handle finish:nil pause:nil];
}
/** */
+ (void)addTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:NO
unit:-1
handle:handle
finish:nil
pause:nil];
}
/** */
+ (void)addTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:NO
unit:-1
handle:handle
finish:finishBlock
pause:pauseBlock];
}
/** */
+ (void)addDiskTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:YES
unit:-1
handle:handle
finish:nil
pause:nil];
}
/** */
+ (void)addDiskTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:YES
unit:-1
handle:handle
finish:finishBlock
pause:pauseBlock];
}
/** */
+ (void)addMinuteTimerForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle {
[self initTimerForForTime:time identifier:nil ForIsDisk:NO unit:1000 handle:handle finish:nil pause:nil];
}
/** */
+ (void)addMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:NO
unit:1000
handle:handle
finish:nil
pause:nil];
}
/** */
+ (void)addMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:NO
unit:1000
handle:handle
finish:finishBlock
pause:pauseBlock];
}
/** */
+ (void)addDiskMinuteTimerForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock {
[self initTimerForForTime:time
identifier:identifier
ForIsDisk:YES
unit:1000
handle:handle
finish:finishBlock
pause:pauseBlock];
}
//
+ (void)initTimerForForTime:(NSTimeInterval)time
identifier:(NSString *)identifier
ForIsDisk:(BOOL)isDisk
unit:(NSTimeInterval)unit
handle:(LSTTimerChangeBlock)handle
finish:(LSTTimerFinishBlock)finishBlock
pause:(LSTTimerPauseBlock)pauseBlock {
if (identifier.length<=0) {
LSTPopViewTimerModel *model = [LSTPopViewTimerModel timeInterval:time];
model.isDisk = isDisk;
model.identifier = [NSString stringWithFormat:@"%p",model];
model.unit = unit;
model.handleBlock = handle;
model.finishBlock = finishBlock;
model.pauseBlock = pauseBlock;
[LSTTimerM().timerMdic setObject:model forKey:model.identifier];
if (model.handleBlock) {
NSInteger totalSeconds = model.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(model.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
model.handleBlock(days,hours,minute,second,ss);
}
//
if (model.NFType != LSTTimerSecondChangeNFTypeNone) {
[[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil];
}
if (model.isDisk) {
[self savaForTimerModel:model];
}
[self initTimer];
return;
}
BOOL isTempDisk = [LSTTimer timerIsExistInDiskForIdentifier:identifier];//
BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//
if (!isRAM && !isTempDisk) {//
LSTPopViewTimerModel *model = [LSTPopViewTimerModel timeInterval:time];
model.handleBlock = handle;
model.isDisk = isDisk;
model.identifier = identifier;
model.unit = unit;
model.finishBlock = finishBlock;
model.pauseBlock = pauseBlock;
[LSTTimerM().timerMdic setObject:model forKey:identifier];
if (model.handleBlock) {
NSInteger totalSeconds = model.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(model.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
if (model.isDisk) {
[self savaForTimerModel:model];
}
model.handleBlock(days,hours,minute,second,ss);
}
//
if (model.NFType != LSTTimerSecondChangeNFTypeNone) {
[[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil];
}
[self initTimer];
}
if (isRAM && !isTempDisk) {//
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
model.isPause = NO;
model.handleBlock = handle;
model.isDisk = isDisk;
model.finishBlock = finishBlock;
model.pauseBlock = pauseBlock;
if (model.isDisk) {
[self savaForTimerModel:model];
}
// [self initTimer];
}
if (!isRAM && isTempDisk) {//
LSTPopViewTimerModel *model = [LSTTimer getTimerModelForIdentifier:identifier];
if (isDisk == NO) {
[LSTTimer deleteForIdentifier:identifier];
}
model.isPause = NO;
model.isDisk = isDisk;
model.handleBlock = handle;
model.finishBlock = finishBlock;
model.pauseBlock = pauseBlock;
[LSTTimerM().timerMdic setObject:model forKey:identifier];
if (model.handleBlock) {
NSInteger totalSeconds = model.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(model.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
model.handleBlock(days,hours,minute,second,ss);
}
//
if (model.NFType != LSTTimerSecondChangeNFTypeNone) {
[[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil];
}
if (model.isDisk) {
[self savaForTimerModel:model];
}
[self initTimer];
}
if (isRAM && isTempDisk) {//
LSTPopViewTimerModel *model = [LSTTimer getTimerModelForIdentifier:identifier];
model.isPause = NO;
if (isDisk == NO) {
[LSTTimer deleteForIdentifier:identifier];
}
model.isDisk = isDisk;
model.handleBlock = handle;
model.finishBlock = finishBlock;
model.pauseBlock = pauseBlock;
[LSTTimerM().timerMdic setObject:model forKey:identifier];
if (model.handleBlock) {
NSInteger totalSeconds = model.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(model.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
model.handleBlock(days,hours,minute,second,ss);
}
//
if (model.NFType != LSTTimerSecondChangeNFTypeNone) {
[[NSNotificationCenter defaultCenter] postNotificationName:model.NFName object:nil userInfo:nil];
}
if (model.isDisk) {
[self savaForTimerModel:model];
}
// [self initTimer];
}
}
+ (NSTimeInterval)getTimeIntervalForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
return 0.0;
}
BOOL isTempDisk = [LSTTimer timerIsExistInDiskForIdentifier:identifier];//
BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//
if (isTempDisk) {
LSTPopViewTimerModel *model = [LSTTimer loadTimerForIdentifier:identifier];
return model.oriTime - model.time;
}else if (isRAM) {
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
return model.oriTime - model.time;
}else {
NSLog(@"找不到计时任务");
return 0.0;
}
}
+ (BOOL)pauseTimerForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
NSLog(@"计时器标识不能为空");
return NO;
}
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
if (model) {
model.isPause = YES;
if (model.pauseBlock) { model.pauseBlock(model.identifier); }
return YES;
}else {
NSLog(@"找不到计时器任务");
return NO;
}
}
+ (void)pauseAllTimer {
[LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) {
obj.isPause = YES;
if (obj.pauseBlock) { obj.pauseBlock(obj.identifier); }
}];
}
+ (BOOL)restartTimerForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
NSLog(@"计时器标识不能为空");
return NO;
}
//, addTimer
BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//
if (isRAM) {
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
model.isPause = NO;
return YES;
}else {
NSLog(@"找不到计时器任务");
return NO;
}
}
+ (void)restartAllTimer {
if (LSTTimerM().timerMdic.count<=0) {
return;
}
[LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) {
obj.isPause = NO;
}];
}
+ (BOOL)resetTimerForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
NSLog(@"计时器标识不能为空");
return NO;
}
//, addTimer
BOOL isRAM = LSTTimerM().timerMdic[identifier]?YES:NO;//
if (isRAM) {
LSTPopViewTimerModel *model = LSTTimerM().timerMdic[identifier];
model.isPause = NO;
model.time = model.oriTime;
if (model.handleBlock) {
NSInteger totalSeconds = model.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(model.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
model.handleBlock(days,hours,minute,second,ss);
}
return YES;
}else {
NSLog(@"找不到计时器任务");
return NO;
}
}
+ (void)resetAllTimer {
if (LSTTimerM().timerMdic.count<=0) {
return;
}
[LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) {
obj.isPause = NO;
obj.time = obj.oriTime;
if (obj.handleBlock) {
NSInteger totalSeconds = obj.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(obj.time))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
obj.handleBlock(days,hours,minute,second,ss);
}
}];
}
+ (BOOL)removeTimerForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
NSLog(@"计时器标识不能为空");
return NO;
}
[LSTTimerM().timerMdic removeObjectForKey:identifier];
if (LSTTimerM().timerMdic.count<=0) {//
[LSTTimerM().showTimer invalidate];
LSTTimerM().showTimer = nil;
}
return YES;
}
+ (void)removeAllTimer {
[LSTTimerM().timerMdic removeAllObjects];
[LSTTimerM().showTimer invalidate];
LSTTimerM().showTimer = nil;
}
/** increase YES: NO: */
+ (void)initTimer {
if (LSTTimerM().showTimer) {
return;
}
NSTimer *timer = [NSTimer timerWithTimeInterval:0.01f target:LSTTimerM() selector:@selector(timerChange) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
LSTTimerM().showTimer = timer;
}
- (void)timerChange {
// +
[LSTTimerM().timerMdic enumerateKeysAndObjectsUsingBlock:^(NSString *key, LSTPopViewTimerModel *obj, BOOL *stop) {
if (!obj.isPause) {
obj.time = obj.time-10.0;
if (obj.unit>-1) {
obj.unit = obj.unit-10.0;
}
if (obj.time<0) {//
obj.time = 0;
obj.isPause = YES;
}
NSInteger totalSeconds = obj.time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(obj.time))%1000/10;
NSString *ms = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ms.integerValue < 10) {
ms = [NSString stringWithFormat:@"0%@", ms];
}
if (obj.unit<=-1) {
if (obj.handleBlock) {obj.handleBlock(days,hours,minute,second,ms);}
if (obj.NFType == LSTTimerSecondChangeNFTypeMS) {
//
[[NSNotificationCenter defaultCenter] postNotificationName:obj.NFName object:nil userInfo:nil];
}
}else if (obj.unit == 0) {
if (obj.handleBlock) {obj.handleBlock(days,hours,minute,second,ms);}
obj.unit = 1000;
if (obj.NFType == LSTTimerSecondChangeNFTypeSecond) {
//
[[NSNotificationCenter defaultCenter] postNotificationName:obj.NFName object:nil userInfo:nil];
}
}
if (obj.isDisk) {
[LSTTimer savaForTimerModel:obj];
}
if (obj.time<=0) {//
if (obj.finishBlock) { obj.finishBlock(obj.identifier); }
[LSTTimerM().timerMdic removeObjectForKey:obj.identifier];
[LSTTimer deleteForIdentifier:obj.identifier];
}
}
}];
}
- (NSMutableDictionary<NSString *,LSTPopViewTimerModel *> *)timerMdic {
if(_timerMdic) return _timerMdic;
_timerMdic = [NSMutableDictionary dictionary];
return _timerMdic;
}
#pragma mark - ***** other *****
+ (BOOL)timerIsExistInDiskForIdentifier:(NSString *)identifier {
NSString *filePath = LSTPopViewTimerPath(identifier);
BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
return isExist;
}
/** */
+ (void)formatDateForTime:(NSTimeInterval)time handle:(LSTTimerChangeBlock)handle {
if (handle) {
NSInteger totalSeconds = time/1000.0;
NSString *days = [NSString stringWithFormat:@"%zd", totalSeconds/60/60/24];
NSString *hours = [NSString stringWithFormat:@"%zd", totalSeconds/60/60%24];
NSString *minute = [NSString stringWithFormat:@"%zd", (totalSeconds/60)%60];
NSString *second = [NSString stringWithFormat:@"%zd", totalSeconds%60];
CGFloat sss = ((NSInteger)(time))%1000/10;
NSString *ms = [NSString stringWithFormat:@"%.lf", sss];
if (hours.integerValue < 10) {
hours = [NSString stringWithFormat:@"0%@", hours];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ms.integerValue < 10) {
ms = [NSString stringWithFormat:@"0%@", ms];
}
handle(days,hours,minute,second,ms);
}
}
+ (BOOL)savaForTimerModel:(LSTPopViewTimerModel *)model {
NSString *filePath = LSTPopViewTimerPath(model.identifier);
return [NSKeyedArchiver archiveRootObject:model toFile:filePath];
}
+ (LSTPopViewTimerModel *)loadTimerForIdentifier:(NSString *)identifier{
NSString *filePath = LSTPopViewTimerPath(identifier);
return [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
}
+ (BOOL)deleteForIdentifier:(NSString *)identifier {
NSString *filePath = LSTPopViewTimerPath(identifier);
NSFileManager* fileManager = [NSFileManager defaultManager];
BOOL isExist = [fileManager fileExistsAtPath:filePath];
if (isExist) {
return [fileManager removeItemAtPath:filePath error:nil];
}
return NO;
}
+ (LSTPopViewTimerModel *)getTimerModelForIdentifier:(NSString *)identifier {
if (identifier.length<=0) {
return nil;
}
LSTPopViewTimerModel *model = [LSTTimer loadTimerForIdentifier:identifier];
return model;
}
@end

72
Pods/LSTTimer/README.md generated Normal file
View File

@@ -0,0 +1,72 @@
# LSTTimer 性能和精度兼得的iOS计时器组件
[![Platform](https://img.shields.io/badge/platform-iOS-red.svg)](https://developer.apple.com/iphone/index.action) [![Language](http://img.shields.io/badge/language-OC-yellow.svg?style=flat )](https://en.wikipedia.org/wiki/Objective-C) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://mit-license.org) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/LSTPopView.svg)](https://img.shields.io/cocoapods/v/LSTTimer.svg)
## 前言
- 在项目开发中,计时器任务的需求很多, LSTTimer的出现就是为了更好统一管理项目中的计时器任务.
- 欢迎coder们发现问题或者提供更好的idea,一起努力完善
## 博客地址
- github: [https://github.com/LoSenTrad/LSTTimer](https://github.com/LoSenTrad/LSTTimer)
- 简书: [https://www.jianshu.com/p/4f05c7e26bb1](https://www.jianshu.com/p/4f05c7e26bb1)
## 实现思路
LSTTimer单例设计, 内部持有一个NSTimer和计时任务池, 所有的计时任务都被添加到任务池里面; NSTimer每100ms(毫秒)执行一次遍历计时任务池, 每个计时任务会进行的时间差运算.
## 特性
- 提供丰富的api,简单入手使用
- 单例设计,安全且占用内存少,统一管理app所有计时任务
- 单计时器任务池设计,一个NSTimer完成多个计时任务
- 计时任务精确度:100ms(100毫秒)
- 支持计时格式--> 天:时:分:秒:毫秒
- 支持硬盘持久化计时任务
- 支持列表计时任务和各种花里胡哨的计时任务
## 版本更新历史[点我](https://github.com/LoSenTrad/LSTTimer/blob/master/UPDATE_HISTORY.md)
## 安装
- CocoaPods安装: 在podfile文件中添加以下描述,然后 `pod install` 或者 `pod update`
```ruby
pod 'LSTTimer'
```
- Carthage安装:(暂时未适配)
## 效果演示(gif图比较大,请耐心等待~)
- 应用市场常用的示例场景
- 支持 天:时:分:秒:毫秒
- 列表计时方案:只需一个计时任务
|常用示例场景<br><img src="https://raw.githubusercontent.com/5208171/LSTBlog/master/LSTTimer/%E5%B8%B8%E7%94%A8%E8%AE%A1%E6%97%B6%E4%BB%BB%E5%8A%A1%E7%A4%BA%E4%BE%8B.gif" width = "200" height = "424" alt="图片名称" align=center />|列表倒计时<br><img src="https://raw.githubusercontent.com/5208171/LSTBlog/master/LSTTimer/%E5%88%97%E8%A1%A8%E5%80%92%E8%AE%A1%E6%97%B6.gif" width = "200" height = "424" alt="图片名称" align=center />|
|---|---|
- 内存计时任务
(当前页面添加计时任务,退出当前页面,计时任务不会停止,而是存在于app的整个生命周期内.当然了,也可以手动移除)
|内存计时任务<br><img src="https://raw.githubusercontent.com/5208171/LSTBlog/master/LSTTimer/%E5%86%85%E5%AD%98%E8%AE%A1%E6%97%B6%E4%BB%BB%E5%8A%A1.gif" width = "200" height = "424" alt="图片名称" align=center />|
|---|
- 硬盘计时任务
(当前页面添加硬盘计时任务,退出app,计时任务保存在硬盘,再次打开进入app,如果计时任务没有结束,继续该计时任务)
|自动规避键盘遮挡<br><img src="https://raw.githubusercontent.com/5208171/LSTBlog/master/LSTTimer/%E7%A1%AC%E7%9B%98%E8%AE%A1%E6%97%B6%E4%BB%BB%E5%8A%A1.gif" width = "200" height = "424" alt="图片名称" align=center />|
|---|
## 作者
490790096@qq.com, LoSenTrad@163.com
## 版权
尊重劳动成果, 人人有责.