Reputation: 13800
I have some code that I would like to run only once in my MainViewController. It should run every time the user starts the app, but only after the MainViewController has loaded.
I don't want to run it in -(void)applicationDidFinishLaunching:(UIApplication *)application
.
Here's the idea I had:
MainViewController.h
@interface IpadMainViewController : UIViewController <UISplitViewControllerDelegate> {
BOOL hasRun;
}
@property (nonatomic, assign) BOOL hasRun;
MainViewController.m
@synthesize hasRun;
-(void)viewDidLoad {
[super viewDidLoad];
if (hasRun == 0) {
// Do some stuff
hasRun = 1;
}
}
Any ideas?
Upvotes: 31
Views: 18283
Reputation: 967
Possible variation (Swift 5):
// Whether this is the first code run since app (re)started
var firstRun: Bool = true
public final class Foo {
public init() {
if firstRun {
// Code that has to be run only once goes
// HERE
firstRun = false
}
}
}
Upvotes: 1
Reputation: 3918
Since there is no dispatch_once_t ins swift 3 and above, we can use lazy initialized global variables.
Make a lazy global variable
lazy var doOnlyOnce: () -> Void = {
.. add code to run only once here ..
return {}
}()
To run the code:
_ = doOnlyOnce
Upvotes: 0
Reputation: 1206
Swift 1,2:
static var token: dispatch_once_t = 0
dispatch_once(&token) {
NSLog("Do it once")
}
Objective-C
static dispatch_once_t once;
dispatch_once(&once, ^ {
NSLog(@"Do it once");
});
Swift 3,4:
dispatch_once is no longer available in Swift. In Swift, you can use lazily initialized globals or static properties and get the same thread-safety and called-once guarantees as dispatch_once provided Apple doc
let myGlobal = { … global contains initialization in a call to a closure … }()
_ = myGlobal // using myGlobal will invoke
// the initialization code only the first time it is used.
Upvotes: 86
Reputation: 413
for Swift2.2,Xcode 7.3:
static var token: dispatch_once_t = 0
dispatch_once(&YourClassName.token) {
NSLog("Do it once")
}
Watch out "YourClassName.token
"
Upvotes: -2
Reputation: 9296
With Swift2.0, Xcode 7.0
var token: dispatch_once_t = 0
override func viewDidLoad() {
super. viewDidLoad()
dispatch_once(&token) {
println("This is printed only on the first call to test()")
}
println("This is printed for each call to test()")
}
Upvotes: -2
Reputation: 126
I don't see any problem with that code. I like using a BOOL (as you did) and then assigning either YES/NO or TRUE/FALSE just so that the code reads more nicely. I would assign TRUE to firstRun in didFinishLaunching, and set it FALSE after the code executes. In my code these type of conditionals usually look like this:
@synthesize firstRun;
-(void)viewDidLoad {
[super viewDidLoad];
if (firstRun) {
// code to run only once goes here
firstRun = FALSE;
}
}
Upvotes: 7