如何在viewDidAppear中只做一次?

我想检查粘贴板,并在出现视图时显示警报,如果它包含特定的值。 我可以将代码放入viewDidLoad以确保它只调用一次,但问题是警报视图显示得太快。 我知道我可以设置一个计时器来推迟警报的外观,但是我认为这不是一个好的解决办法。

我检查了iOS 7的问题- viewDidLoad和viewDidAppear之间的差异 ,发现有一个步骤来检查视图是否存在。 所以我想知道有没有这样做?

更新:“只有一次”意味着视图控制器实例的生命周期

有一个标准的,内置的方法,你可以使用这个。

Objective-C的:

 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if ([self isBeingPresented] || [self isMovingToParentViewController]) { // Perform an action that will only be done once } } 

Swift 3:

 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if self.isBeingPresented || self.isMovingToParentViewController { // Perform an action that will only be done once } } 

当视图控制器首先被显示为模态显示的结果时,对isBeingPresented的调用是真实的。 isMovingToParentViewController在视图控制器首次被推入导航堆栈时为true。 视图控制器第一次出现时,其中一个是真实的。

无需处理BOOL ivars或任何其他技巧来跟踪第一个电话。

rmaddy的答案是非常好的,但是它并不能解决问题,当视图控制器是导航控制器的根视图控制器和所有其他容器,不会将这些标志传递给它的子视图控制器。

所以这样的情况下我最好使用一个标志,并在以后使用。

 @interface SomeViewController() { BOOL isfirstAppeareanceExecutionDone; } @end @implementation SomeViewController -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if(isfirstAppeareanceExecutionDone == NO) { // Do your stuff isfirstAppeareanceExecutionDone = YES; } } @end 

如果我正确理解你的问题,你可以简单地设置一个BOOLvariables来识别viewDidAppear已经被调用,例如:

 - (void)viewDidAppear { if (!self.viewHasBeenSet) { // <-- BOOL default value equals NO // Perform whatever code you'd like to perform // the first time viewDidAppear is called self.viewHasBeenSet = YES; } } 

通过阅读其他评论(根据@rmaddy的回答),我知道这不是OP所要求的,而是因为这个问题的标题而来到这里的人:

 extension UIViewController { var isPresentingForFirstTime: Bool { return isBeingPresented() || isMovingToParentViewController() } } 

UPDATE

你应该在viewDidAppearviewWillAppear使用这个方法。 (感谢@rmaddy)

更新2

此方法只适用于模态呈现的视图控制器和推视图控制器。 它不与一个childViewController工作。 使用didMoveToParentViewController会更好的childViewControllers。

此解决scheme将在应用程序的整个生命周期内仅调用一次viewDidAppear ,即使您创build了视图控制器的多个对象,但一次后就不会调用该对象。 请参考上面的rmaddy的回答

您可以在viewDidLoad执行select器,也可以在viewDidAppear使用dispatch_once_t 如果你find更好的解决scheme,那么请与我分享。 这是我做的东西。

 - (void)viewDidLoad { [super viewDidLoad]; [self performSelector:@selector(myMethod) withObject:nil afterDelay:2.0]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; static dispatch_once_t once; dispatch_once(&once, ^{ //your stuff [self myMethod]; }); } 

您可以使用标志或设置标签来查看:

 override func viewDidAppear(_ animated: Bool) { if view.tag == 0 { //Your view have appeared for the first time //do anything here you want to do //when next time your view will appear these lines will be skipped } view.tag = 1 } 

你可以在ViewDidLoad方法中使用这个函数

performSelector:withObject:afterDelay:

它会在延迟后调用该函数。 所以你不必使用任何定制的计时器对象。 和一旦你可以使用

dispatch_once DCD block.Just performSelector在dispatch_once块中调用ViewDidLoad时只调用一次performSelector

希望能帮助到你

尝试设置一个BOOL值,当情况发生时调用它。

 @interface AViewController : UIViewController @property(nonatomic) BOOL doSomeStuff; @end @implementation AViewController - (void) viewWillAppear:(BOOL)animated { if(doSomeStuff) { [self doSomeStuff]; doSomeStuff = NO; } } 

在你启动AViewController实例的地方:

 AddEventViewController *ad = [AddEventViewController new]; ad.doSomeStuff = YES; 

不知道你为什么在ViewDidAppear做到这ViewDidAppear ? 但是,如果你想doSomeStuff是私人的, soSomeStuff只被调用一次,这里是通知的另一个解决scheme:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomeStuff) name:@"do_some_stuff" object:nil]; - (void) doSomeStuff {} 

然后在某个地方发帖:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"do_some_stuff" object:nil]; 
 if view.tag != 0 { // Not executed on First Instance // executed only when view did appear called after first time } view.tag = 1