2013-11-27 72 views
4

在我的应用程序中,有一个聊天服务。当用户想要发送新消息时,他按下“新聊天”并显示一个表视图控制器以从朋友列表中选择。我正在使用unwind segues以返回到前一个视图控制器并在两个视图控制器之间共享数据(主要是数据将成为与之聊天的朋友)。但是在我的应用程序中,当用户返回主VC时,为了直接转到另一个用户进行聊天的VC,我会发起一个新的切入;这不起作用。所有的赛段连接良好,我试过每个角落的NsLog,并且它正在进入,甚至是prepareForSegue:正在被访问。我试着把一个NsTimer,认为可能会有一些技术冲突,并没有奏效。我改变SEGUE到聊天VC的模式,现在它给我这个错误:unwind segue/performSegueWithIdentifier:问题

Warning: Attempt to present on whose view is not in the window hierarchy!

我可以通过其他方式访问该VC和它的层次结构中。我的问题是:什么可能是错的?展开segues是否会改变窗口层次结构?

PICTURE: enter image description here

更直观地说明问题,我说的是在主VC是左下角被连接至导航视图控制器。当用户按下新的聊天时,会显示右上角的两个VC(一个在朋友或组之间进行选择,另一个显示朋友/组)。所以当从右上角的VC中选择一个朋友时,我应该放弃继续到主VC。正如你可以从主要的VC看到的那样,还有其他的赛段。如果我确实放松继续工作,他们可以工作,如果我正常工作,他们工作。

+0

纯粹猜测这里考虑我们不能看到您的脚本或代码,但是很有可能你想表达的视图控制器从unwind segue解散的视角,你能向我们展示任何代码或任何东西吗? – JAManfredi

+0

@JAManfredi好吧,我添加了一张图片和一个解释。我猜代码是最小的,不会有任何区别。希望这很清楚。 – HusseinB

回答

14

它不工作的原因,并给你的错误是因为事情没有发生在你认为他们是的顺序。

当开卷发生时可见尚未驳回了视图,因此您要执行对视图这实际上是不是该层次结构类似的错误说一个SEGUE,借此例如,放置的NSLog声明在您的主视图控制器的最终视图,然后在放卷方法,你可以看到如下:

2013-11-27 14:51:10.848 testUnwindProj[2216:70b] Unwind 
2013-11-27 14:51:10.849 testUnwindProj[2216:70b] Will Appear 
2013-11-27 14:51:11.361 testUnwindProj[2216:70b] View Did Disappear 

因此在主视图开卷获取调用,认为会出现(您的主视图控制器),然后你可见的观点被驳回。这可能是一个简单的解决办法:

@interface ViewController() { 
    BOOL _unwindExecuted; 
} 

@end 

@implementation ViewController 

- (void)viewWillAppear:(BOOL)animated 
{ 
    NSLog(@"Will Appear"); 
    if (_unwindExecuted) { 
     _unwindExecuted = NO; 
     [self performSegueWithIdentifier:@"afterunwind" sender:self]; 
    } 
} 

- (IBAction)unwind:(UIStoryboardSegue *)segue 
{ 
    NSLog(@"Unwind"); 
    _unwindExecuted = YES; 
} 
+0

好评!感谢您的洞察力!对此,我真的非常感激!我没有想到它会被这些任务所困扰。 – HusseinB

+0

我不得不改变viewWillAppear以viewDidAppear,让我的代码工作,但感谢您的帮助。 – JimJty

+0

这就是它!肯定比拥有硬编码时间的dispatch_after要好得多 –

-2

还好解决了这个,问题是,有观点还没有实现,我不得不通过这种延迟的过程:

[self performSelector:@selector(fireNewConv) withObject:nil afterDelay:1]; 

然而,一些有趣的事情是,我试图通过拖延的NSTimer,但它没没有工作。

+1

这是实现这个最糟糕的可能方式。你只是猜测放松动画何时结束。正如@Ike正确地表明的那样,这是'viewDidAppear:'的目的;使用一个实例变量来检测这个视图的外观是否是一个表示是否应该开始下一个segue的信号。一个更好的解决方案可能是实现'segueForUnwindingToViewController:fromViewController:identifier:',它允许你完全控制整个代码中的展开过程。或者,只需手动放松(而不是放松休息)。 – matt

+0

不要这样做。使用完成块。 – Fattie

2

不要使用计时器或延迟来尝试和预测视图何时可能存在。

相反,使用要求,如: - (无效)dismissViewControllerAnimated:(BOOL)标志完成:(无效(^)(无效))完成

建成块将让你知道当你在返抵主要的VC。或者,查看与segues相关的各种调用,以便您确切知道何时可以在新窗口上执行操作。

如果一切都失败了,总是有UIViewController的viewDidAppear。

+0

这不是一个答案,但对OP的回答 – matt

2

这对于正在处理平仓,因为在放松身心的视图控制器一个共同的问题,即视图控制器可能无法在窗口层次。

为了解决,我添加了一个属性segueIdentifierToUnwindTo来协调展开。

这与JAManfredi的答案类似,但将其扩展为能够延续到任何视图控制器。

@interface FirstViewController() 
// Use this to coordinate unwind 
@property (nonatomic, strong) NSString *segueIdentifierToUnwindTo; 
@end 

@implementation FirstViewController 
- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    // Handle unwind 
    if (_segueIdentifierToUnwindTo) { 
     [self performSegueWithIdentifier:_segueIdentifierToUnwindTo sender:self]; 
     self.segueIdentifierToUnwindTo = nil; // reset 
     return; 
    } 
    // Any other code.. 
} 

// Example of an unwind segue "gotoLogin" 
- (IBAction)gotoLogin:(UIStoryboardSegue*)sender { 
    // Don't perform segue directly here, because in unwind, this view is not in window hierarchy yet! 
    // [self performSegueWithIdentifier:@"Login" sender:self]; 
    self.segueIdentifierToUnwindTo = @"Login"; 
} 
@end 

我也分享我如何使用与FirstViewController开卷塞格斯在我的博客:http://samwize.com/2015/04/23/guide-to-using-unwind-segues/