Ios 如何在ViewDid中执行一些只出现一次的操作?
我想检查粘贴板,并在视图出现时显示一个警报,如果它包含特定值。我可以将代码放入Ios 如何在ViewDid中执行一些只出现一次的操作?,ios,viewdidappear,Ios,Viewdidappear,我想检查粘贴板,并在视图出现时显示一个警报,如果它包含特定值。我可以将代码放入viewDidLoad以确保只调用一次,但问题是警报视图显示得太快。我知道我可以设置一个计时器来延迟警报的出现,但我认为这不是一个好办法 我检查了这个问题,发现有一个步骤可以检查视图是否存在。所以我想知道是否有任何api可以实现这一点 更新:“仅一次”表示视图控制器实例的生存期您可以在ViewDidLoad方法中使用此函数 performSelector:withObject:afterDelay: 它将在延迟后调用该
viewDidLoad
以确保只调用一次,但问题是警报视图显示得太快。我知道我可以设置一个计时器来延迟警报的出现,但我认为这不是一个好办法
我检查了这个问题,发现有一个步骤可以检查视图是否存在。所以我想知道是否有任何api可以实现这一点
更新:“仅一次”表示视图控制器实例的生存期您可以在ViewDidLoad方法中使用此函数 performSelector:withObject:afterDelay: 它将在延迟后调用该函数。因此,您不必使用任何自定义计时器对象。 这一次你可以用 dispatch_once DCD块。仅dispatch_once块中的performSelector在调用ViewDidLoad时将仅调用performSelector一次 希望有帮助此解决方案在应用程序的整个生命周期内只调用一次
viewdide
,即使您创建了视图控制器的多个对象,一次之后也不会调用。请参阅
您可以在viewdiload
中执行选择器,也可以在viewdilease
中使用dispatch\u once\t
。如果你找到更好的解决方案,请与我分享。我就是这样做的
- (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];
});
}
尝试设置布尔值,当情况发生时调用它
@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;
不确定为什么要在视图中执行此操作?但如果您希望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];
如果我正确理解了您的问题,您可以简单地设置一个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;
}
}
-(无效)视图显示{
如果(!self.viewHasBeenSet){/有一个标准的内置方法可以用于此操作
目标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
}
}
当视图控制器作为modally显示的结果首次显示时,isBeingPresented
的调用为真。isMovingToParentViewController
在视图控制器首次被推到导航堆栈上时为真。当视图控制器第一次出现时,这两个调用之一为真
无需处理BOOL
ivar或任何其他跟踪第一次呼叫的技巧。通过阅读其他评论(并根据@rmaddy的回答),我知道这不是OP要求的,而是针对那些因为问题标题而来的人:
extension UIViewController {
var isPresentingForFirstTime: Bool {
return isBeingPresented() || isMovingToParentViewController()
}
}
更新
您应该在viewdideappear
和viewWillAppear
中使用此方法(感谢@rmaddy)
更新2
此方法仅适用于模式显示的视图控制器和推式视图控制器。它不适用于childViewController。使用didMoveToParentViewController
会更好地适用于childViewController。rmaddy的答案非常好,但当视图控制器是根视图控制器时,它并不能解决问题导航控制器和所有其他容器的troller,这些容器不将这些标志传递给其子视图控制器
因此,在这种情况下,我发现最好使用一个标志,并在以后使用它
@interface SomeViewController()
{
BOOL isfirstAppeareanceExecutionDone;
}
@end
@implementation SomeViewController
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(isfirstAppeareanceExecutionDone == NO) {
// Do your stuff
isfirstAppeareanceExecutionDone = YES;
}
}
@end
通过此检查,嵌套视图控制器中不应出现问题
extension UIViewController {
var isPresentingForFirstTime: Bool {
if let parent = parent {
return parent.isPresentingForFirstTime
}
return isBeingPresented || isMovingFromParent
}
}
我认为您不需要在viewDidLoad
中将BOOL设置为NO。当创建对象时,BOOL将以NO
开始,并且viewDidLoad
,afaik,在视图控制器对象的生命周期中只调用一次。@MaxGabriel为了清晰起见,我这样写的,但是是的,这是真的。好的,好的。我已经删除了init我喜欢你的答案,但是如果static dispatch\u once\u t once;
是在本地声明的,应用程序怎么知道在变量解除分配后的下一次不执行它呢?似乎它需要作为类变量存储。。。dispatch_once
解决方案的真正问题是static
跨越视图控制器的实例。此解决方案确保在应用程序进程的整个生命周期中只调用一次myMethod
。@LyndseyScott不,这完全可以。它是一个静态变量,而不是局部变量。您可以阅读静态变量。这里有一个线程@rmaddy Correct,如果你拆下并重建视图控制器,dispatch_包装的代码将不会再次执行。在用户硬重设应用程序之前,它将不会再次执行!这在几乎所有情况下都是不希望出现的行为(包括本文中指定的情况)然后最好有一个您第一次设置的布尔标志。随后检查是否设置了该标志。从何处调用该标志?通过显示如何实际使用该标志来改进您的答案。问题围绕viewDidApearmethod@mohamadrezakoohkan即使视图已经加载,也可以多次调用viewdidApear他上面提出的问题是,他希望某件事情只执行一次。所以我要求他将逻辑从viewdidApear转换为viewdidLoad,因为viewdidLoad只调用了一次。如果他想做一些UI的事情,那么他可以在延迟后用perform selecter调用它,直到UI正确显示,这样他就可以避免在必须执行时出现额外的条件viewdidApear。希望它能解决您的问题。这段代码去哪里了?它还要求将doSomeStuff
初始化为YES
。这不是一个合适的解决方案。doSomeStuff
不应该是公共的。视图控制器本身应该是唯一知道doSomeStuff的类e> 应该设置