使某些代码只运行一次
Posted
技术标签:
【中文标题】使某些代码只运行一次【英文标题】:Making some code only run once 【发布时间】:2012-03-05 18:10:48 【问题描述】:我有一些代码只想在我的 MainViewController 中运行一次。它应该在用户每次启动应用程序时运行,但仅在 MainViewController 加载后运行。
我不想在-(void)applicationDidFinishLaunching:(UIApplication *)application
中运行它。
这是我的想法:
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;
有什么想法吗?
【问题讨论】:
运行-(void)applicationDidFinishLaunching:(UIApplication *)application
或您的代码有什么问题?或者,如果您不分配 MainViewCONtroller,它无论如何都会运行一次
每次激活一次(即启动时一次,从后台返回时一次),还是每次加载到内存中一次?
【参考方案1】:
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 在 Swift 中不再可用。在 Swift 中,您可以使用 延迟初始化的全局变量或静态属性并得到相同的 dispatch_once 提供的线程安全和调用一次保证 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.
【讨论】:
+1;对于这个任务,GCD 是比在你的类中保持 BOOL 状态更干净的选择 请注意,这是每个加载到内存中的应用程序一次。该代码将不会为正在创建的此类的另一个实例再次运行(这有点我最近),也不会在应用程序从挂起返回前台时再次运行。 很好的答案。这感觉比我最初的想法优雅得多。我学到了一些东西。谢谢! @JoshCaswell 好点,你知道无论如何要“重置” GCD 或类的实例,以便在某个时候再次调用它吗?我可以打电话给[[ClassName alloc] init];
来“重置”它吗?
可以重置once
令牌,@RazorSharp: ***.com/questions/10930044/…,尽管那时我会说你应该只使用另一个应该的机制重置,就像 Dylan 对 BOOL
属性的建议一样。【参考方案2】:
我认为该代码没有任何问题。我喜欢使用 BOOL(就像您所做的那样),然后分配 YES/NO 或 TRUE/FALSE,以便代码读取得更好。我会将 TRUE 分配给 didFinishLaunching 中的 firstRun,并在代码执行后将其设置为 FALSE。在我的代码中,这些类型的条件通常如下所示:
@synthesize firstRun;
-(void)viewDidLoad
[super viewDidLoad];
if (firstRun)
// code to run only once goes here
firstRun = FALSE;
【讨论】:
另一个推荐 Grand Central Dispatch 的答案可以说是一种更好的方法。另一方面,作为 BSD 级别的技术,考虑到这是一个“基本”问题,它的学习曲线相当陡峭。如果你想按照你的要求做,这段代码比你原来的代码稍微干净一些——如果你想尝试一种更高级的任务管理方法,GCD 非常强大。【参考方案3】:可能的变化(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
【讨论】:
【参考方案4】:由于没有dispatch_once_t insswift 3及以上,我们可以使用惰性初始化全局变量。
创建一个惰性全局变量
lazy var doOnlyOnce: () -> Void =
.. add code to run only once here ..
return
()
运行代码:
_ = doOnlyOnce
【讨论】:
【参考方案5】:使用 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()")
【讨论】:
【参考方案6】:对于 Swift2.2、Xcode 7.3:
static var token: dispatch_once_t = 0
dispatch_once(&YourClassName.token)
NSLog("Do it once")
注意“YourClassName.token
”
【讨论】:
以上是关于使某些代码只运行一次的主要内容,如果未能解决你的问题,请参考以下文章
如何使一行代码在循环中运行一次,并且只运行下一行代码,直到前一行运行一次?