如何在viewDidAppear中只做一次一些东西?

时间:2015-01-29 04:33:55

标签: ios viewdidappear

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

我检查了问题iOS 7 - Difference between viewDidLoad and viewDidAppear,发现有一个步骤可以检查视图是否存在。所以我想知道是否有这样做的api?

更新:"只有一次"表示视图控制器实例的生命周期

8 个答案:

答案 0 :(得分:56)

您可以使用标准的内置方法。

目标-C:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    if ([self isBeingPresented] || [self isMovingToParentViewController]) {
        // Perform an action that will only be done once
    }
}

斯威夫特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或任何其他技巧来跟踪第一个电话。

答案 1 :(得分:7)

rmaddy的答案非常好,但是当视图控制器是导航控制器的根视图控制器以及所有其他未将这些标志传递给其子视图控制器的容器时,它无法解决问题。

所以这种情况我最好使用一个标志并在以后使用它。

@interface SomeViewController()
{
    BOOL isfirstAppeareanceExecutionDone;
}
@end

@implementation SomeViewController

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

@end

答案 2 :(得分:4)

如果我理解你的问题,你可以简单地设置一个BOOL变量来识别已经调用了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; 
    }
}

答案 3 :(得分:1)

此解决方案将在应用程序的整个生命周期中仅调用viewDidAppear一次,即使您创建了视图控制器的多个对象,这在一次之后也不会被调用。请参阅rmaddy's answer above

您可以在viewDidLoad中执行选择,也可以在dispatch_once_t中使用viewDidAppear。如果您找到更好的解决方案,请与我分享。这就是我做这些事情的方式。

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

答案 4 :(得分:1)

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

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

<强>更新

您应该在viewDidAppearviewWillAppear中使用此方法。 (感谢@rmaddy)

更新2

此方法仅适用于模态呈现的视图控制器和推送的视图控制器。它不能与childViewController一起使用。使用didMoveToParentViewController使用childViewControllers会更好。

答案 5 :(得分:1)

通过此检查,嵌套视图控制器中应该不会出现问题

extension UIViewController {

  var isPresentingForFirstTime: Bool {
      if let parent = parent {
        return parent.isPresentingForFirstTime
      }
      return isBeingPresented || isMovingFromParent
  }
}

答案 6 :(得分:0)

尝试设置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中执行此操作?但是如果你想doSomeStuff是私有的,soSomeStuff只被调用一次,这是另一个通知的解决方案:

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

- (void) doSomeStuff
{}

然后在某个地方发帖:

[[NSNotificationCenter defaultCenter] postNotificationName:@"do_some_stuff" object:nil];

答案 7 :(得分:-1)

您可以在ViewDidLoad方法

中使用此功能
  

performSelector:withObject:afterDelay:

延迟后会调用该函数。所以你不必使用任何自定义计时器对象。 一旦你可以使用

  

dispatch_once DCD block.Just performSelector在dispatch_once块中,只有在调用ViewDidLoad时才调用performSelector

希望有所帮助