Add block handling functions to NSTimer

This commit is contained in:
Gregory John Casamento 2019-10-26 17:03:38 -04:00
parent 3d6cd160b2
commit 873e4edc47
4 changed files with 128 additions and 50 deletions

View file

@ -51,7 +51,7 @@ enum {
};
typedef NSInteger NSQualityOfService;
@class NSString;
@class NSString, NSTimer;
DEFINE_BLOCK_TYPE(NSBackgroundActivityCompletionHandler, void, NSBackgroundActivityResult);
DEFINE_BLOCK_TYPE(GSScheduledBlock, void, NSBackgroundActivityCompletionHandler);
@ -64,6 +64,7 @@ DEFINE_BLOCK_TYPE(GSScheduledBlock, void, NSBackgroundActivityCompletionHandler)
NSTimeInterval _tolerance;
BOOL _repeats;
BOOL _shouldDefer;
NSTimer *_timer;
}
- (instancetype) initWithIdentifier: (NSString *)identifier;
@ -81,7 +82,7 @@ DEFINE_BLOCK_TYPE(GSScheduledBlock, void, NSBackgroundActivityCompletionHandler)
- (void) setInterval: (NSTimeInterval)interval;
- (NSTimeInterval) tolerance;
- (void) setTolerance: (NSTimeInterval)interval;
- (void) setTolerance: (NSTimeInterval)tolerance;
- (BOOL) shouldDefer;
- (void) setShouldDefer: (BOOL)flag;

View file

@ -28,6 +28,9 @@
#import <Foundation/NSDate.h>
@class NSTimer;
DEFINE_BLOCK_TYPE(GSTimerBlock, void, NSTimer*);
#if defined(__cplusplus)
extern "C" {
#endif
@ -43,13 +46,14 @@ extern "C" {
{
#if GS_EXPOSE(NSTimer)
@public
NSDate *_date; /* Must be first - for NSRunLoop optimisation */
BOOL _invalidated; /* Must be 2nd - for NSRunLoop optimisation */
BOOL _repeats;
NSDate *_date; /* Must be 1st - for NSRunLoop optimisation */
BOOL _invalidated; /* Must be 2nd - for NSRunLoop optimisation */
BOOL _repeats;
NSTimeInterval _interval;
id _target;
SEL _selector;
id _info;
id _target;
SEL _selector;
id _info;
GSTimerBlock _block;
#endif
#if GS_NONFRAGILE
#else
@ -67,15 +71,21 @@ extern "C" {
+ (NSTimer*) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
invocation: (NSInvocation*)invocation
repeats: (BOOL)f;
+ (NSTimer*) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
target: (id)object
selector: (SEL)selector
userInfo: (id)info
repeats: (BOOL)f;
+ (NSTimer *) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
repeats: (BOOL)f
block: (GSTimerBlock)block;
+ (NSTimer*) timerWithTimeInterval: (NSTimeInterval)ti
invocation: (NSInvocation*)invocation
repeats: (BOOL)f;
+ (NSTimer*) timerWithTimeInterval: (NSTimeInterval)ti
target: (id)object
selector: (SEL)selector
@ -102,6 +112,13 @@ extern "C" {
- (void) setFireDate: (NSDate*)fireDate;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_12, GS_API_LATEST)
- (instancetype)initWithFireDate:(NSDate *)date
interval:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(GSTimerBlock)block;
#endif
@end
#if defined(__cplusplus)

View file

@ -37,6 +37,7 @@
_interval = 0;
_tolerance = 0;
_shouldDefer = NO;
_timer = nil;
}
return self;
}
@ -103,6 +104,30 @@
- (void) scheduleWithBlock: (GSScheduledBlock)block
{
NSProcessInfo *pinfo = [NSProcessInfo processInfo];
id token = nil;
NSActivityOptions opts = 0;
switch(qualityOfService)
{
case NSQualityOfServiceUserInteractive:
opts = NSActivityUserInitiated | NSActivityIdleDisplaySleepDisabled;
break;
case NSQualityOfServiceUserInitiated:
opts = NSActivityUserInitiated;
break;
case NSQualityOfServiceUtility:
opts = NSActivityUserInitiated | NSActivityIdleDisplaySleepDisabled;
break;
case NSQualityOfServiceBackground:
opts = NSActivityBackground;
break;
case NSQualityOfServiceDefault:
opts = NSActivityLatencyCritical;
break;
}
token = [pinfo beginActivityWithOptions:
}
- (void) invalidate

View file

@ -145,6 +145,20 @@ static Class NSDate_class;
return self;
}
- (instancetype)initWithFireDate:(NSDate *)date
interval:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(GSTimerBlock)block
{
return [self initWithFireDate: date
interval: interval
target: nil
selector: NULL
userInfo: nil
repeats: repeats];
ASSIGN(_block, block);
}
/**
* Create a timer which will fire after ti seconds and, if f is YES,
* every ti seconds thereafter. On firing, invocation will be performed.<br />
@ -229,6 +243,19 @@ static Class NSDate_class;
return t;
}
+ (NSTimer *) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
repeats: (BOOL)f
block: (GSTimerBlock)block
{
id t = [[self alloc] initWithFireDate: nil
interval: ti
repeats: f
block: block];
[[NSRunLoop currentRunLoop] addTimer: t forMode: NSDefaultRunLoopMode];
RELEASE(t);
return t;
}
- (void) dealloc
{
if (_invalidated == NO)
@ -251,48 +278,56 @@ static Class NSDate_class;
*/
if (NO == _invalidated)
{
id target;
/* We retain the target so it won't be deallocated while we are using it
* (if this timer gets invalidated while we are firing).
*/
target = RETAIN(_target);
if (_selector == 0)
{
NS_DURING
{
[(NSInvocation*)target invoke];
}
NS_HANDLER
{
NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') "
@"raised during posting of timer with target %s(%s) "
@"and selector '%@'",
[localException name], [localException reason],
GSClassNameFromObject(target),
GSObjCIsInstance(target) ? "instance" : "class",
NSStringFromSelector([target selector]));
}
NS_ENDHANDLER
}
if(_block != nil)
{
CALL_BLOCK(_block, self);
}
else
{
NS_DURING
{
[target performSelector: _selector withObject: self];
}
NS_HANDLER
{
NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') "
@"raised during posting of timer with target %p and "
@"selector '%@'",
[localException name], [localException reason], target,
NSStringFromSelector(_selector));
}
NS_ENDHANDLER
}
RELEASE(target);
{
id target;
/* We retain the target so it won't be deallocated while we are using it
* (if this timer gets invalidated while we are firing).
*/
target = RETAIN(_target);
if (_selector == 0)
{
NS_DURING
{
[(NSInvocation*)target invoke];
}
NS_HANDLER
{
NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') "
@"raised during posting of timer with target %s(%s) "
@"and selector '%@'",
[localException name], [localException reason],
GSClassNameFromObject(target),
GSObjCIsInstance(target) ? "instance" : "class",
NSStringFromSelector([target selector]));
}
NS_ENDHANDLER
}
else
{
NS_DURING
{
[target performSelector: _selector withObject: self];
}
NS_HANDLER
{
NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') "
@"raised during posting of timer with target %p and "
@"selector '%@'",
[localException name], [localException reason], target,
NSStringFromSelector(_selector));
}
NS_ENDHANDLER
}
RELEASE(target);
}
if (_repeats == NO)
{
[self invalidate];