I should note first that this isn't a good thing to do in any situation other than testing; even then, proceed with care -- AliSoftware provides some details and example code in comments below. See also the interesting answers at Can I declare a dispatch_once_t
predicate as a member variable instead of static?, including some important information from the horse's mouth.
dispatch_once_t
is a typedef
d long
. Its false value is 0. If you reset that flag to 0, dispatch_once()
will run again. Your problem is "just" how to change the value of a static variable from another compilation unit. For this, I think you need a debug/unit test hook, like so:
MakeWhoopie.h
#import <Foundation/Foundation.h>
void makeWhoopie(void);
#ifdef DEBUG
void resetDispatchOnce(void);
#endif
MakeWhoopie.m
#include "MakeWhoopie.h"
static dispatch_once_t * once_token_debug;
void makeWhoopie(void)
{
static dispatch_once_t once_token;
once_token_debug = &once_token; // Store address of once_token
// to access it in debug function.
dispatch_once(&once_token, ^{
NSLog(@"That's what you get, folks.");
});
NSLog(@"Making whoopie.");
}
#ifdef DEBUG
void resetDispatchOnce(void)
{
*once_token_debug = 0;
}
#endif
(You could also move once_token
up to file level and change it directly.)
Trying this out:
#import <Foundation/Foundation.h>
#import "MakeWhoopie.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
makeWhoopie();
makeWhoopie();
resetDispatchOnce();
makeWhoopie();
}
return 0;
}
Results in:
2012-06-07 18:45:28.134 ResetDispatchOnce[8628:403] That's what you get, folks.
2012-06-07 18:45:28.163 ResetDispatchOnce[8628:403] Making whoopie.
2012-06-07 18:45:28.164 ResetDispatchOnce[8628:403] Making whoopie.
2012-06-07 18:45:28.165 ResetDispatchOnce[8628:403] That's what you get, folks.
2012-06-07 18:45:28.165 ResetDispatchOnce[8628:403] Making whoopie.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…