iOS - 回到我的初始视图控制器
iOS - unwind to my initial view controller
我正在使用 unwind segue 来展开到故事板中的初始视图控制器。放松效果很好,我在我的初始视图控制器中实现了这个方法:
- (IBAction) unwindToInitialViewController:(UIStoryboardSegue *) unwindSegue {
}
但是,如果我在展开后尝试转至另一个视图控制器,我会收到以下错误:
Warning: Attempt to present on
whose view is not in the window
hierarchy!
这似乎只有在我展开到情节提要中检查为 'Initial View Controller' 的视图控制器时才会发生。这是一个错误吗?我应该能够放松到那个初始控制器吗?其他想法?
编辑:
这是我执行第二个 segue 的方式:
[self performSegueWithIdentifier:@"mySegue" sender:nil];
我应该注意到这是一个 login/logout 问题。当我第一次登录时,从我的登录控制器到我的下一个控制器的 segue 工作。当我注销时,我放松到初始视图控制器。然后我再次登录,从我的登录控制器到下一个控制器的 segue 不起作用。
编辑 2:
通过更多研究,我发现它是因为我正在使用委托进行登录。登录是异步的,我使用 AFNetworking 进行调用,完成后我调用我的登录委托(在本例中为登录 VC)。那时登录 VC 可以转到视图。
登录码:
- (void) login: (NSDictionary *) parameters {
[http.manager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, NSDictionary *response) {
[self.loginDelegate loginSuccess:response];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.loginDelegate loginFailure:error];
}];
}
我的登录名VC是代表:
- (void) loginSuccess:(NSDictionary *) response {
// setup user info based on response
...
// Segue
[self performSegueWithIdentifier:@"loginSuccessSegue" sender:nil];
}
我已经检查过我何时在主线程中,并且我继续,但仍然没有运气。我知道 AFNetworking 也总是在主线程上调用 success/failure 块。
棘手的部分。如果我将上面的代码更改为使用块而不是委托,storyboard/segue 不会搞砸,我可以毫无问题地多次登录和注销。
为什么 segue 第一次使用委托模式工作,但在注销(解除)时,我不能再次使用该 segue 吗?
编辑 3:
更多调查表明,在取消登录时 VC viewDidAppear 被调用了两次。在初始展开时,视图看起来仍然在堆栈中,快速显示它并调用 viewDidAppear。然而,这很快就被动画化了,viewWillAppear 被第二次调用了不同的 VC。我认为这可能是问题的根源。为什么当我放松到那个 VC 时它动画消失只是为了动画回来?
请检查您的 loginDelegate
是否在第二次尝试登录时为 nil
。 如果是 nil
,"delegate calls" 将无处可去。 另外请检查 loginDelegate
是否指向您期望的实例。如果它指向一个"old"实例,可能会尝试呈现错误的视图。
方法集 viewDidLoad
、viewDidAppear
、viewWillAppear
等可能会以意想不到的顺序调用,尤其是在返回导航或展示广告并从中返回时.如果您在这些方法中分配了不同的 initialization/setup 任务,您最终可能会得到一个部分初始化的视图控制器。
(考虑到这个问题我丢失了你对遇到的错误的陈述,所以可能委托不是零。)
编辑:
我 运行 我的一个小型放松测试项目,记录了 viewDidAppear
调用:
viewDidAppear: <ViewController: 0x7a687700>
viewDidAppear: <VC2: 0x7a70e970>
viewDidAppear: <VC3: 0x7a694d50>
unwind target
viewDidAppear: <VC2: 0x7a70e970>
viewDidAppear: <ViewController: 0x7a687700>
viewDidAppear: <VC2: 0x7a71b790>
viewDidAppear: <VC3: 0x7a694d20>
unwind target
viewDidAppear: <VC2: 0x7a71b790>
viewDidAppear: <ViewController: 0x7a687700>
在 VC3
中进行展开会短暂显示 VC2
并最终到达目标 ViewController
。现在第二个 "login" 导致视图控制器的不同实例。
您是否保留对 "old" 视图控制器的引用?
另一个原因可能是,您的 "logout" 检测触发了两次(一次是在展开时触发,另一次是在中间或初始视图控制器检测到需要登录时?)。
我正在使用 unwind segue 来展开到故事板中的初始视图控制器。放松效果很好,我在我的初始视图控制器中实现了这个方法:
- (IBAction) unwindToInitialViewController:(UIStoryboardSegue *) unwindSegue {
}
但是,如果我在展开后尝试转至另一个视图控制器,我会收到以下错误:
Warning: Attempt to present on whose view is not in the window hierarchy!
这似乎只有在我展开到情节提要中检查为 'Initial View Controller' 的视图控制器时才会发生。这是一个错误吗?我应该能够放松到那个初始控制器吗?其他想法?
编辑:
这是我执行第二个 segue 的方式:
[self performSegueWithIdentifier:@"mySegue" sender:nil];
我应该注意到这是一个 login/logout 问题。当我第一次登录时,从我的登录控制器到我的下一个控制器的 segue 工作。当我注销时,我放松到初始视图控制器。然后我再次登录,从我的登录控制器到下一个控制器的 segue 不起作用。
编辑 2:
通过更多研究,我发现它是因为我正在使用委托进行登录。登录是异步的,我使用 AFNetworking 进行调用,完成后我调用我的登录委托(在本例中为登录 VC)。那时登录 VC 可以转到视图。
登录码:
- (void) login: (NSDictionary *) parameters {
[http.manager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, NSDictionary *response) {
[self.loginDelegate loginSuccess:response];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.loginDelegate loginFailure:error];
}];
}
我的登录名VC是代表:
- (void) loginSuccess:(NSDictionary *) response {
// setup user info based on response
...
// Segue
[self performSegueWithIdentifier:@"loginSuccessSegue" sender:nil];
}
我已经检查过我何时在主线程中,并且我继续,但仍然没有运气。我知道 AFNetworking 也总是在主线程上调用 success/failure 块。
棘手的部分。如果我将上面的代码更改为使用块而不是委托,storyboard/segue 不会搞砸,我可以毫无问题地多次登录和注销。
为什么 segue 第一次使用委托模式工作,但在注销(解除)时,我不能再次使用该 segue 吗?
编辑 3:
更多调查表明,在取消登录时 VC viewDidAppear 被调用了两次。在初始展开时,视图看起来仍然在堆栈中,快速显示它并调用 viewDidAppear。然而,这很快就被动画化了,viewWillAppear 被第二次调用了不同的 VC。我认为这可能是问题的根源。为什么当我放松到那个 VC 时它动画消失只是为了动画回来?
请检查您的 loginDelegate
是否在第二次尝试登录时为 nil
。 如果是 另外请检查 nil
,"delegate calls" 将无处可去。loginDelegate
是否指向您期望的实例。如果它指向一个"old"实例,可能会尝试呈现错误的视图。
方法集 viewDidLoad
、viewDidAppear
、viewWillAppear
等可能会以意想不到的顺序调用,尤其是在返回导航或展示广告并从中返回时.如果您在这些方法中分配了不同的 initialization/setup 任务,您最终可能会得到一个部分初始化的视图控制器。
(考虑到这个问题我丢失了你对遇到的错误的陈述,所以可能委托不是零。)
编辑:
我 运行 我的一个小型放松测试项目,记录了 viewDidAppear
调用:
viewDidAppear: <ViewController: 0x7a687700>
viewDidAppear: <VC2: 0x7a70e970>
viewDidAppear: <VC3: 0x7a694d50>
unwind target
viewDidAppear: <VC2: 0x7a70e970>
viewDidAppear: <ViewController: 0x7a687700>
viewDidAppear: <VC2: 0x7a71b790>
viewDidAppear: <VC3: 0x7a694d20>
unwind target
viewDidAppear: <VC2: 0x7a71b790>
viewDidAppear: <ViewController: 0x7a687700>
在 VC3
中进行展开会短暂显示 VC2
并最终到达目标 ViewController
。现在第二个 "login" 导致视图控制器的不同实例。
您是否保留对 "old" 视图控制器的引用?
另一个原因可能是,您的 "logout" 检测触发了两次(一次是在展开时触发,另一次是在中间或初始视图控制器检测到需要登录时?)。