简体   繁体   English

unwind segue / performSegueWithIdentifier:问题

[英]unwind segue / performSegueWithIdentifier: problems

in my app, there is a chatting service. 在我的应用程序中,有一个聊天服务。 when the user wants to message someone new, he press on "new chat" and a Table View Controller is shown to select from the list of friends. 当用户想要给某人发新消息时,他按下“新聊天”并显示表视图控制器以从朋友列表中进行选择。 i'm using unwind segues in order to go back to the previous view controller and share the data between the two view controllers (mainly the data will be the friend to have a chat with). 我正在使用展开segue以返回到前一个视图控制器并在两个视图控制器之间共享数据(主要是数据将是与之聊天的朋友)。 the unwind segue works perfectly, however in my app, when the user goes back to the main VC, i fire a new segue in order to go to another VC directly where the user has the chat; unwind segue完美运行,但是在我的应用程序中,当用户返回主VC时,我会启动一个新的segue,以便直接转到用户聊天的另一个VC; and this isn't working. 这不起作用。 All segues are well connected and i tried NsLog in every corner and it's entering there and even the prepareForSegue: is being accessed. 所有segues连接良好,我在每个角落都尝试过NsLog,它正在进入那里甚至是prepareForSegue:正在被访问。 i tried putting an NsTimer, thought there might be some technical conflict, and it didn't work. 我试过放一个NsTimer,认为可能存在一些技术冲突,但它没有用。 i change the segue to the chat VC to a modal and now it's giving me this error: 我将segue更改为聊天VC到模态,现在它给了我这个错误:

Warning: Attempt to present on whose view is not in the window hierarchy! 警告:尝试显示其视图不在窗口层次结构中!

i can access this VC in other ways and it's in the hierarchy. 我可以通过其他方式访问此VC,它位于层次结构中。 my questions are: what could be wrong? 我的问题是:可能出现什么问题? does unwind segues alter the windows hierarchies ? 放松segues会改变Windows层次结构吗?

PICTURE: 图片: 在此输入图像描述

to present the problem more visually, the main VC i'm talking about is on the bottom left connected to a navigation view controller. 为了更直观地呈现问题,我正在谈论的主要VC是在左下方连接到导航视图控制器。 when a user presses new chat, the two VC on the top right are presented (one to choose between friends or group, the other to show the friends/ groups). 当用户按下新聊天时,会显示右上角的两个VC(一个用于选择朋友或组,另一个用于显示朋友/组)。 so when a friend is selected for say from the top right VC i should unwind segue to the main VC. 因此,当从右上角选择一个朋友说VC时,我应该将segue解开到主VC。 as you can see from the main VC there is other segues. 正如你从主VC看到的还有其他的segues。 non of them can work if i do unwind segue and they do work if i operate normally. 如果我放松segue它们可以工作,如果我正常运行它们会工作。

The reason it is not working and is giving you that error is because things arent happening in the order you think they are. 它不起作用并且给你错误的原因是因为事情没有按照你认为的顺序发生。

When the unwind happens the view which is visible is not dismissed yet, therefore you are trying to perform a segue on a view which is in fact not in that hierarchy like the error says, take this for example, placing NSLog statements in the final view and then in the unwind method in your main view controller you can see the following: 当展开发生时,可见的视图还没有被解散,因此你试图在视图上执行一个segue,这个视图实际上并不像错误所说的那样在层次结构中,例如,将NSLog语句放在最终视图中然后在主视图控制器的unwind方法中,您可以看到以下内容:

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

Thus the unwind in the main view is getting called, the view will appear (your main view controller), and then your visible view is dismissed. 因此,主视图中的展开被调用,视图将出现(您的主视图控制器),然后您的可见视图被取消。 This could be a simple fix: 这可能是一个简单的修复:

@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;
}

Don't use timers or delays to try and anticipate when a view may exist. 不要使用计时器或延迟来尝试预测何时可能存在视图。

Instead, use calls like: - (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion 相反,使用如下调用: - (void)dismissViewControllerAnimated:(BOOL)标志完成:(void(^)(void))完成

The completion block will let you know when you've arrived back at the main VC. 当您返回主VC时,完成块将通知您。 Alternatively, look at the various calls associated with segues so that you know precisely when you can perform operations on the new window. 或者,查看与segue相关的各种调用,以便准确了解何时可以在新窗口上执行操作。

If all else fails, there's always UIViewController viewDidAppear. 如果所有其他方法都失败了,那么总是有UIViewController viewDidAppear。

This is a common problem for the view controller that is handling the unwinding, because during unwind, that view controller is likely to not be in the window hierarchy. 这是处理展开的视图控制器的常见问题,因为在展开期间,该视图控制器可能不在窗口层次结构中。

To solve, I added a property segueIdentifierToUnwindTo to coordinate the unwinding. 为了解决这个问题,我添加了一个属性segueIdentifierToUnwindTo来协调展开。

This is similar to the answer by JAManfredi, but extending it to be able to segue to any view controllers. 这类似于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

I also shared how I use unwind segues with a FirstViewController on my blog: http://samwize.com/2015/04/23/guide-to-using-unwind-segues/ 我还分享了如何在我的博客上使用FirstViewController展开segues: httpFirstViewController

okay solved this, the problem is that the view wasn't there yet and i had to delay the process by this: 好吧解决了这个问题,问题是视图还没有,我不得不推迟这个过程:

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

However, something interesting is that i tried delaying by NSTimer but it didn't work. 然而,有趣的是我尝试延迟NSTimer,但它没有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM