How to do some stuff in viewDidAppear only once?

前端 未结 8 1423
暖寄归人
暖寄归人 2020-11-29 03:25

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 onl

相关标签:
8条回答
  • 2020-11-29 03:56

    You shouldn't have issues in nested view controllers with this check

    extension UIViewController {
    
      var isPresentingForFirstTime: Bool {
          if let parent = parent {
            return parent.isPresentingForFirstTime
          }
          return isBeingPresented || isMovingFromParent
      }
    }
    
    0 讨论(0)
  • 2020-11-29 03:59

    If I understand your question correctly, you can simply set a BOOL variable to recognize that viewDidAppear has already been called, ex:

    - (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; 
        }
    }
    
    0 讨论(0)
  • 2020-11-29 04:05

    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.

    0 讨论(0)
  • 2020-11-29 04:07

    This solution will call viewDidAppear only once throughout the life cycle of the app even if you create the multiple object of the view controller this won't be called after one time. Please refer to the rmaddy's answer above

    You can either perform selector in viewDidLoad or you can use dispatch_once_t in you viewDidAppear. If you find a better solution then please do share with me. This is how I do the stuff.

    - (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];
      });
    }
    

    0 讨论(0)
  • 2020-11-29 04:07

    By reading other comments (and based on @rmaddy 's answer), I know this is not what OP asked for, but for those who come here because of title of the question:

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

    UPDATE

    You should use this method in viewDidAppear and viewWillAppear. (thanks to @rmaddy)

    UPDATE 2

    This method only works with modally presented view controllers and pushed view controllers. it's not working with a childViewController. using didMoveToParentViewController would be better with childViewControllers.

    0 讨论(0)
  • 2020-11-29 04:07

    Try to set a BOOL value, when the situation happens call it.

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

    in somewhere you init AViewController instance:

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

    Not sure why you do this in ViewDidAppear? But if you want doSomeStuff is private and soSomeStuff was called only once, here is another solution by notification:

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

    Then post when somewhere:

    [[NSNotificationCenter defaultCenter] postNotificationName:@"do_some_stuff" object:nil];
    
    0 讨论(0)
提交回复
热议问题