Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do some stuff in viewDidAppear only once?

I want to check the pasteboard and show an alert if it contains specific values when the view appears. I can place the code into viewDidLoad to ensure it's only invoked once, but the problem is that the alert view shows too quickly. I know I can set a timer to defer the alert's appearance, but it's not a good work-around I think.

I checked the question iOS 7 - Difference between viewDidLoad and viewDidAppear and found that there is one step for checking whether the view exists. So I wonder if there's any api for doing this?

Update: The "only once" means the lifetime of the view controller instance.

like image 605
Allen Avatar asked Jan 29 '15 04:01

Allen


People also ask

Can viewDidAppear be called multiple times?

viewWillAppear(_:) is called every time the view appears. In this simple app, that means it is only called once. However, imagine your app has several views, and you can move between them. viewWillAppear(_:) is called every time your view is displayed.

What is called after viewDidAppear?

viewDidAppear is called once you see the loaded view on screen. It is called after view appeared. ViewDidAppear is called everytime when you see the view after it is loaded. if you push and then pop any other viewController on that view then again viewDidAppear gets called.

What is difference between viewWillAppear and viewDidAppear?

As the name suggests the viewWillAppear is called before the view is about to appear and viewDidAppear is called when view did appear.

What is the difference between viewDidLoad and viewDidAppear?

The difference between viewDidAppear and viewDidLoad is that viewDidAppear is called every time you land on the screen while viewDidLoad is only called once which is when the app loads.


2 Answers

There is a standard, built-in method you can use for this.

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     } } 

The call to isBeingPresented is true when a view controller is first being shown as a result of being shown modally. isMovingToParentViewController is true when a view controller is first being pushed onto the navigation stack. One of the two will be true the first time the view controller appears.

No need to deal with BOOL ivars or any other trick to track the first call.

like image 137
rmaddy Avatar answered Oct 11 '22 13:10

rmaddy


rmaddy's answers is really good but it does not solve the problem when the view controller is the root view controller of a navigation controller and all other containers that do not pass these flags to its child view controller.

So such situations i find best to use a flag and consume it later on.

@interface SomeViewController() {     BOOL isfirstAppeareanceExecutionDone; } @end  @implementation SomeViewController  -(void)viewDidAppear:(BOOL)animated {     [super viewDidAppear:animated];     if(isfirstAppeareanceExecutionDone == NO) {         // Do your stuff         isfirstAppeareanceExecutionDone = YES;     } }  @end 
like image 28
BangOperator Avatar answered Oct 11 '22 13:10

BangOperator