2001-12-17 14:31:42 +00:00
|
|
|
/** Implementation of NSTimer for GNUstep
|
1999-06-03 12:36:10 +00:00
|
|
|
Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1996-03-12 15:39:13 +00:00
|
|
|
Created: March 1996
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-12-17 14:31:42 +00:00
|
|
|
Rewrite by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-03-12 15:39:13 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1996-03-12 15:39:13 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-03-12 15:39:13 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1996-03-12 15:39:13 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-10-13 19:10:56 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
<title>NSTimer class reference</title>
|
|
|
|
$Date$ $Revision$
|
1996-03-12 15:39:13 +00:00
|
|
|
*/
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
#import "common.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
#define EXPOSE_NSTimer_IVARS 1
|
|
|
|
#import "Foundation/NSTimer.h"
|
|
|
|
#import "Foundation/NSDate.h"
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
#import "Foundation/NSRunLoop.h"
|
|
|
|
#import "Foundation/NSInvocation.h"
|
1996-03-12 15:39:13 +00:00
|
|
|
|
1999-09-14 10:03:02 +00:00
|
|
|
@class NSGDate;
|
2005-07-08 11:48:37 +00:00
|
|
|
@interface NSGDate : NSObject // Help the compiler
|
|
|
|
@end
|
1999-09-14 10:03:02 +00:00
|
|
|
static Class NSDate_class;
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
/**
|
2009-05-27 11:03:42 +00:00
|
|
|
* <p>An <code>NSTimer</code> provides a way to send a message at some time in
|
2004-06-22 22:40:40 +00:00
|
|
|
* the future, possibly repeating every time a fixed interval has passed. To
|
|
|
|
* use a timer, you can either create one that will automatically be added to
|
|
|
|
* the run loop in the current thread (using the -addTimer:forMode: method),
|
|
|
|
* or you can create it without adding it then add it to an [NSRunLoop]
|
|
|
|
* explicitly later.
|
2009-05-27 11:03:42 +00:00
|
|
|
* </p>
|
|
|
|
* <p>NB. You may not use -init or +new to create a timer, as the timer must
|
|
|
|
* be properly initialised to send an action after some interval.
|
|
|
|
* </p>
|
2004-06-22 22:40:40 +00:00
|
|
|
*/
|
1996-03-12 15:39:13 +00:00
|
|
|
@implementation NSTimer
|
|
|
|
|
1999-09-14 10:03:02 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (self == [NSTimer class])
|
|
|
|
{
|
|
|
|
NSDate_class = [NSGDate class];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-27 10:53:45 +00:00
|
|
|
/* For MacOS-X compatibility, this returns nil.
|
|
|
|
*/
|
|
|
|
- (id) init
|
|
|
|
{
|
2010-02-25 18:49:31 +00:00
|
|
|
DESTROY(self);
|
2009-05-27 10:53:45 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2009-09-10 16:41:06 +00:00
|
|
|
/** <init />
|
2002-08-27 13:40:42 +00:00
|
|
|
* Initialise the receive, a newly allocated NSTimer object.<br />
|
|
|
|
* The ti argument specifies the time (in seconds) between the firing.
|
|
|
|
* If it is less than or equal to 0.0 then a small interval is chosen
|
|
|
|
* automatically.<br />
|
2009-09-10 16:41:06 +00:00
|
|
|
* The fd argument specifies an initial fire date copied by the timer...
|
|
|
|
* if it is not supplied (a nil object) then the ti argument is used to
|
|
|
|
* create a start date relative to the current time.<br />
|
2002-08-27 13:40:42 +00:00
|
|
|
* The f argument specifies whether the timer will fire repeatedly
|
|
|
|
* or just once.<br />
|
|
|
|
* If the selector argument is zero, then then object is an invocation
|
|
|
|
* to be used when the timer fires. otherwise, the object is sent the
|
|
|
|
* message specified by the selector and with the timer as an argument.<br />
|
2009-09-10 16:41:06 +00:00
|
|
|
* The object and info arguments will be retained until the timer is
|
|
|
|
* invalidated.
|
2002-01-16 14:00:59 +00:00
|
|
|
*/
|
2002-08-27 13:40:42 +00:00
|
|
|
- (id) initWithFireDate: (NSDate*)fd
|
|
|
|
interval: (NSTimeInterval)ti
|
|
|
|
target: (id)object
|
|
|
|
selector: (SEL)selector
|
|
|
|
userInfo: (id)info
|
|
|
|
repeats: (BOOL)f
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
2009-09-10 16:41:06 +00:00
|
|
|
if (ti <= 0.0)
|
2000-08-07 22:00:31 +00:00
|
|
|
{
|
2002-02-03 17:21:20 +00:00
|
|
|
ti = 0.0001;
|
2000-08-07 22:00:31 +00:00
|
|
|
}
|
2002-08-27 13:40:42 +00:00
|
|
|
if (fd == nil)
|
|
|
|
{
|
|
|
|
_date = [[NSDate_class allocWithZone: NSDefaultMallocZone()]
|
2009-09-10 16:41:06 +00:00
|
|
|
initWithTimeIntervalSinceNow: ti];
|
2002-08-27 13:40:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-10 16:41:06 +00:00
|
|
|
_date = [fd copyWithZone: NSDefaultMallocZone()];
|
2002-08-27 13:40:42 +00:00
|
|
|
}
|
2002-06-17 06:30:32 +00:00
|
|
|
_target = RETAIN(object);
|
2002-02-03 17:21:20 +00:00
|
|
|
_selector = selector;
|
2002-06-17 06:30:32 +00:00
|
|
|
_info = RETAIN(info);
|
2009-09-10 16:41:06 +00:00
|
|
|
if (f == YES)
|
|
|
|
{
|
|
|
|
_repeats = YES;
|
|
|
|
_interval = ti;
|
|
|
|
}
|
|
|
|
else
|
2007-12-07 06:32:04 +00:00
|
|
|
{
|
2009-09-10 16:41:06 +00:00
|
|
|
_repeats = NO;
|
2007-12-07 06:32:04 +00:00
|
|
|
_interval = 0.0;
|
|
|
|
}
|
1996-03-12 15:39:13 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2003-04-17 06:20:17 +00:00
|
|
|
* Create a timer which will fire after ti seconds and, if f is YES,
|
2002-06-17 06:47:28 +00:00
|
|
|
* every ti seconds thereafter. On firing, invocation will be performed.<br />
|
|
|
|
* NB. To make the timer operate, you must add it to a run loop.
|
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
+ (NSTimer*) timerWithTimeInterval: (NSTimeInterval)ti
|
2000-08-07 22:00:31 +00:00
|
|
|
invocation: (NSInvocation*)invocation
|
1999-06-03 12:36:10 +00:00
|
|
|
repeats: (BOOL)f
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
2002-08-27 13:40:42 +00:00
|
|
|
return AUTORELEASE([[self alloc] initWithFireDate: nil
|
|
|
|
interval: ti
|
|
|
|
target: invocation
|
|
|
|
selector: NULL
|
|
|
|
userInfo: nil
|
|
|
|
repeats: f]);
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2005-11-06 13:53:40 +00:00
|
|
|
* Create a timer which will fire after ti seconds and, if f is YES,
|
2002-06-17 06:47:28 +00:00
|
|
|
* every ti seconds thereafter. On firing, the target object will be
|
2006-10-13 19:10:56 +00:00
|
|
|
* sent a message specified by selector and with the timer as its
|
2002-06-17 06:47:28 +00:00
|
|
|
* argument.<br />
|
|
|
|
* NB. To make the timer operate, you must add it to a run loop.
|
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
+ (NSTimer*) timerWithTimeInterval: (NSTimeInterval)ti
|
2000-08-07 22:00:31 +00:00
|
|
|
target: (id)object
|
1999-06-03 12:36:10 +00:00
|
|
|
selector: (SEL)selector
|
2000-08-07 22:00:31 +00:00
|
|
|
userInfo: (id)info
|
1999-06-03 12:36:10 +00:00
|
|
|
repeats: (BOOL)f
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
2002-08-27 13:40:42 +00:00
|
|
|
return AUTORELEASE([[self alloc] initWithFireDate: nil
|
|
|
|
interval: ti
|
|
|
|
target: object
|
|
|
|
selector: selector
|
|
|
|
userInfo: info
|
|
|
|
repeats: f]);
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2002-08-27 13:40:42 +00:00
|
|
|
* Create a timer which will fire after ti seconds and, if f is YES,
|
2002-06-17 06:47:28 +00:00
|
|
|
* every ti seconds thereafter. On firing, invocation will be performed.<br />
|
|
|
|
* This timer will automatically be added to the current run loop and
|
2002-08-27 13:40:42 +00:00
|
|
|
* will fire in the default run loop mode.
|
2002-06-17 06:47:28 +00:00
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
+ (NSTimer*) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
|
2000-08-07 22:00:31 +00:00
|
|
|
invocation: (NSInvocation*)invocation
|
1999-06-03 12:36:10 +00:00
|
|
|
repeats: (BOOL)f
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
2007-03-25 10:28:29 +00:00
|
|
|
id t = [[self alloc] initWithFireDate: nil
|
|
|
|
interval: ti
|
|
|
|
target: invocation
|
|
|
|
selector: NULL
|
|
|
|
userInfo: nil
|
|
|
|
repeats: f];
|
1997-09-01 21:59:51 +00:00
|
|
|
[[NSRunLoop currentRunLoop] addTimer: t forMode: NSDefaultRunLoopMode];
|
2007-03-25 10:28:29 +00:00
|
|
|
RELEASE(t);
|
1996-03-12 15:39:13 +00:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2002-08-27 13:40:42 +00:00
|
|
|
* Create a timer which will fire after ti seconds and, if f is YES,
|
2002-06-17 06:47:28 +00:00
|
|
|
* every ti seconds thereafter. On firing, the target object will be
|
2006-10-13 19:10:56 +00:00
|
|
|
* sent a message specified by selector and with the timer as its
|
2002-06-17 06:47:28 +00:00
|
|
|
* argument.<br />
|
|
|
|
* This timer will automatically be added to the current run loop and
|
2002-08-27 13:40:42 +00:00
|
|
|
* will fire in the default run loop mode.
|
2002-06-17 06:47:28 +00:00
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
+ (NSTimer*) scheduledTimerWithTimeInterval: (NSTimeInterval)ti
|
2000-08-07 22:00:31 +00:00
|
|
|
target: (id)object
|
1999-06-03 12:36:10 +00:00
|
|
|
selector: (SEL)selector
|
2000-08-07 22:00:31 +00:00
|
|
|
userInfo: (id)info
|
1999-06-03 12:36:10 +00:00
|
|
|
repeats: (BOOL)f
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
2007-03-25 10:28:29 +00:00
|
|
|
id t = [[self alloc] initWithFireDate: nil
|
|
|
|
interval: ti
|
|
|
|
target: object
|
|
|
|
selector: selector
|
|
|
|
userInfo: info
|
|
|
|
repeats: f];
|
1997-09-01 21:59:51 +00:00
|
|
|
[[NSRunLoop currentRunLoop] addTimer: t forMode: NSDefaultRunLoopMode];
|
2007-03-25 10:28:29 +00:00
|
|
|
RELEASE(t);
|
1996-03-12 15:39:13 +00:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
1999-04-22 11:24:57 +00:00
|
|
|
- (void) dealloc
|
|
|
|
{
|
2002-06-17 06:30:32 +00:00
|
|
|
if (_invalidated == NO)
|
|
|
|
{
|
|
|
|
[self invalidate];
|
|
|
|
}
|
1999-04-22 11:24:57 +00:00
|
|
|
RELEASE(_date);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
1996-03-12 15:39:13 +00:00
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2005-11-06 13:53:40 +00:00
|
|
|
* Fires the timer ... either performs an invocation or sends a message
|
2002-06-17 06:47:28 +00:00
|
|
|
* to a target object, depending on how the timer was set up.<br />
|
2006-03-13 15:15:44 +00:00
|
|
|
* If the timer is not set to repeat, it is automatically invalidated.<br />
|
|
|
|
* Exceptions raised during firing of the timer are caught and logged.
|
2002-06-17 06:47:28 +00:00
|
|
|
*/
|
1996-03-12 15:39:13 +00:00
|
|
|
- (void) fire
|
|
|
|
{
|
2010-09-25 21:28:07 +00:00
|
|
|
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 = [_target retain];
|
|
|
|
|
|
|
|
/* We check that we have not been invalidated before we fire.
|
|
|
|
*/
|
|
|
|
if (NO == _invalidated)
|
2000-08-07 22:00:31 +00:00
|
|
|
{
|
2010-09-25 21:28:07 +00:00
|
|
|
if (_selector == 0)
|
2004-09-07 16:54:16 +00:00
|
|
|
{
|
2010-09-25 21:28:07 +00:00
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
[(NSInvocation*)target invoke];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') "
|
|
|
|
@"raised during posting of timer with target %p "
|
|
|
|
@"and selector '%@'",
|
|
|
|
[localException name], [localException reason], target,
|
|
|
|
NSStringFromSelector([target selector]));
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER
|
2004-09-07 16:54:16 +00:00
|
|
|
}
|
2010-09-25 21:28:07 +00:00
|
|
|
else
|
2005-02-22 11:22:44 +00:00
|
|
|
{
|
2010-09-25 21:28:07 +00:00
|
|
|
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
|
2004-09-07 16:54:16 +00:00
|
|
|
}
|
2000-08-07 22:00:31 +00:00
|
|
|
}
|
2010-09-25 21:28:07 +00:00
|
|
|
[target release];
|
1996-03-12 15:39:13 +00:00
|
|
|
|
2000-08-07 22:00:31 +00:00
|
|
|
if (_repeats == NO)
|
|
|
|
{
|
|
|
|
[self invalidate];
|
|
|
|
}
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
|
|
|
* Marks the timer as invalid, causing its target/invocation and user info
|
|
|
|
* objects to be released.<br />
|
|
|
|
* Invalidated timers are automatically removed from the run loop when it
|
|
|
|
* detects them.
|
|
|
|
*/
|
1996-03-12 15:39:13 +00:00
|
|
|
- (void) invalidate
|
|
|
|
{
|
2000-06-27 03:28:00 +00:00
|
|
|
/* OPENSTEP allows this method to be called multiple times. */
|
1999-04-20 16:28:04 +00:00
|
|
|
_invalidated = YES;
|
2009-01-09 09:23:40 +00:00
|
|
|
if (_target != nil)
|
|
|
|
{
|
|
|
|
DESTROY(_target);
|
|
|
|
}
|
|
|
|
if (_info != nil)
|
|
|
|
{
|
|
|
|
DESTROY(_info);
|
|
|
|
}
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
|
|
|
* Checks to see if the timer has been invalidated.
|
|
|
|
*/
|
1996-03-12 15:39:13 +00:00
|
|
|
- (BOOL) isValid
|
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
if (_invalidated == NO)
|
2002-06-17 06:30:32 +00:00
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
2000-08-07 22:00:31 +00:00
|
|
|
else
|
2002-06-17 06:30:32 +00:00
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
|
|
|
* Returns the date/time at which the timer is next due to fire.
|
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
- (NSDate*) fireDate
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
1999-04-22 11:24:57 +00:00
|
|
|
return _date;
|
1996-03-12 15:39:13 +00:00
|
|
|
}
|
|
|
|
|
2002-08-27 13:40:42 +00:00
|
|
|
/**
|
|
|
|
* Change the fire date for the receiver.<br />
|
|
|
|
* NB. You should <em>NOT</em> use this method for a timer which has
|
2002-08-27 14:32:27 +00:00
|
|
|
* been added to a run loop. The only time when it is safe to modify
|
2002-08-27 13:40:42 +00:00
|
|
|
* the fire date of a timer in a run loop is for a repeating timer
|
|
|
|
* when the timer is actually in the process of firing.
|
|
|
|
*/
|
|
|
|
- (void) setFireDate: (NSDate*)fireDate
|
|
|
|
{
|
|
|
|
ASSIGN(_date, fireDate);
|
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
2007-12-07 06:32:04 +00:00
|
|
|
* Returns the interval between firings, or zero if the timer
|
|
|
|
* does not repeat.
|
2002-06-17 06:47:28 +00:00
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
- (NSTimeInterval) timeInterval
|
|
|
|
{
|
|
|
|
return _interval;
|
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
|
|
|
* Returns the user info which was set for the timer when it was created,
|
|
|
|
* or nil if none was set or the timer is invalid.
|
|
|
|
*/
|
1999-06-03 12:36:10 +00:00
|
|
|
- (id) userInfo
|
1996-03-12 15:39:13 +00:00
|
|
|
{
|
|
|
|
return _info;
|
|
|
|
}
|
|
|
|
|
2002-06-17 06:47:28 +00:00
|
|
|
/**
|
|
|
|
* Compares timers based on the date at which they should next fire.
|
|
|
|
*/
|
2005-07-08 11:48:37 +00:00
|
|
|
- (NSComparisonResult) compare: (id)anotherTimer
|
1997-01-11 21:35:35 +00:00
|
|
|
{
|
2000-08-07 22:00:31 +00:00
|
|
|
if (anotherTimer == self)
|
|
|
|
{
|
|
|
|
return NSOrderedSame;
|
|
|
|
}
|
|
|
|
else if (anotherTimer == nil)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"nil argument for compare:"];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-07-08 11:48:37 +00:00
|
|
|
return [_date compare: ((NSTimer*)anotherTimer)->_date];
|
2000-08-07 22:00:31 +00:00
|
|
|
}
|
|
|
|
return 0;
|
1997-01-11 21:35:35 +00:00
|
|
|
}
|
1999-04-22 11:24:57 +00:00
|
|
|
|
1996-03-12 15:39:13 +00:00
|
|
|
@end
|