我正在尝试使用iOS 6+(我的应用为7.0+)状态保存来保存从另一个View Controller模态显示的 View 。这样,具有典型的模态视图 Controller 解雇模式:

TNTLoginViewController.h包含

@protocol TNTLoginViewControllerDelegate <NSObject>

- (void)TNTLoginViewControllerDismiss:(TNTLoginViewController *)controller;

@end

@interface TNTLoginViewControllerDelegate : NSObject

@interface TNTLoginViewController : UIViewController

@property (weak, nonatomic) IBOutlet id <TNTLoginViewControllerDelegate> delegate;

- (IBAction)getStarted:(id)sender;

@end

getStarted:实现
- (IBAction)getStarted:(id)sender
{
    // Perform login
    ...

    // Dismiss me
    [self.delegate TNTLoginViewControllerDismiss:self];
}

TNTLoginViewControllerDismiss:委托(delegate)方法,介绍了模态
- (void)TNTLoginViewControllerDismiss:(TNTLoginViewController *)controller
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

这一切都像一个魅力!直到国家保护。简而言之,我不知道TNTLoginViewController将如何保留其委托(delegate)。我知道为什么不能:这只是一个指针!因此,我尝试了各种派生委托(delegate)的方法:
  • 恢复类:不幸的是,作为一种类方法,viewControllerWithRestorationIdentifierPath:coder:不能帮助我指向特定的演示View Controller。
  • 在演示图板中将我的演示VC设置为我的模式VC的委托(delegate):即使我的演示VC的类在其 header 中公开采用TNTLogingViewControllerDelegate>协议(protocol),Xcode也不允许我绘制该连接。那可能是一个单独的问题,或者可能不允许这样做。
  • 使用应用程序代表级别的application:viewControllerWithRestorationIdentifierPath:coder:返回模态视图 Controller ,并将其委托(delegate)设置为我正在显示的 View Controller 。我必须能够从App Delegate派生呈现V​​C,但它可能会起作用。

  • 我现在要使用#3,但是如果有人可以推荐更好的解决方案,我会很高兴。

    产生类似问题的设置:
  • 设置数据源,例如表 View 。
  • 最佳答案

    您是正确的,可以使用application:viewControllerWithRestorationIdentifierPath:coder:从应用程序代理级别执行此操作,但是您在执行此操作时要小心/谨慎!

    目的是在状态恢复过程中返回TNTLoginViewController,并将其委托(delegate)设置为其父对象。

    首先,您必须创建一个TNTLoginViewController对象。您提到了一个 Storyboard ,所以我将从那里加载它。我将假设您使用Main.storyboard文件进行了相当标准的设置,并且在Identity Inspector中正确设置了身份。

    TNTLoginViewController * loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"loginViewController"];
    

    接下来,您需要将其委托(delegate)设置为父代。我将假定有一个UINavigationController连接此模型。要从application-delegate对象中找到该对象,您需要挖掘其window属性。

    window属性是一个UIWindow对象,它具有另一个属性rootViewController。这是一个UIViewController对象。因为我假设有一个UINavigationController连接您的模型,所以您需要将此UIViewController类型转换为UINavigationViewController(我会将链接无法放置在当前的信誉级别)。

    现在,您可以使用topViewController属性,将其设置为导航堆栈顶部的 Controller ,将其设置为您的委托(delegate)!如果不是,则可以导航UINavigationController对象,以将其作为委托(delegate)对象。

    记住,由于您是在应用程序代理级别设置委托(delegate),因此可能需要在此处指定协议(protocol)以避免模糊性。

    要在代码中实现这最后四个步骤,将看起来像这样。
    loginViewController.delegate = (id <TNTLoginViewControllerDelegate>)((UINavigationController *) self.window.rootViewController).topViewController;
    

    然后,您可以返回TNTLoginViewController并正确设置其委托(delegate)!

    确保不要忘记使用application:viewControllerWithRestorationIdentifierPath:coder:的含义。您只想在还原TNTLoginViewController的情况下执行此操作。幸运的是,您可以使用传入的identifierComponents参数进行检查。将其与Identity Inspector中的身份名称进行比较,如果不匹配则返回nil。

    AppDelegate.m文件中的 final方法将如下所示。
    - (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
    {
    if ([[identifierComponents lastObject] isEqualToString:@"loginViewController"]) {
        TNTLoginViewController * loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"loginViewController"];
    
        loginViewController.delegate = (id <TNTLoginViewControllerDelegate>)((UINavigationController *) self.window.rootViewController).topViewController;
    
        return loginViewController;
    }
    
    return nil;
    }
    

    我希望这有帮助!

    关于ios - 具有自定义委托(delegate)或数据源的View Controller的状态保留,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21081896/

    10-14 22:04