ios - 具有自定义委托(delegate)或数据源的 View Controller 的状态保存

标签 ios objective-c delegates uikit-state-preservation

我正在尝试使用 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)的方法:

  1. Restoration 类:遗憾的是,作为类方法,viewControllerWithRestorationIdentifierPath:coder: 无法帮助我指向特定的呈现 View Controller 。
  2. 在 Storyboard 中将我的演示 VC 设置为我的模式 VC 的委托(delegate):Xcode 不允许我绘制该连接,即使我的演示 VC 的类在其 header 中公开采用了 TNTLogingViewControllerDelegate> 协议(protocol)。这可能是一个单独的问题,或者这可能是不允许的。
  3. 使用 application-delegate-level application:viewControllerWithRestorationIdentifierPath:coder: 返回一个模态视图 Controller ,其委托(delegate)设置为我的呈现 View Controller 。我必须能够从 App Delegate 派生出呈现 VC,但它可能会起作用。

我现在选择 #3,但如果有人可以推荐更好的解决方案,我会很高兴。

会产生类似问题的设置:

  1. 设置数据源,例如 TableView 。

最佳答案

你是对的,这可以通过 application:viewControllerWithRestorationIdentifierPath:coder: 从应用程序委托(delegate)级别完成,但你需要小心/切碎如何执行此操作!

这里的目标是在状态恢复过程中返回一个 TNTLoginViewController,其委托(delegate)设置为它的父级。

首先您必须创建一个 TNTLoginViewController 对象。你提到了一个 Storyboard,所以我将从那里加载它。我假设您有一个相当标准的设置,其中包含一个 Main.storyboard 文件,并且在身份检查器中正确设置了身份。

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

接下来您需要将其委托(delegate)设置为父级。我将假设有一个 UINavigationController 连接这个模型。从 application-delegate 中找到它您需要深入了解其窗口属性的对象。

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

现在您可以使用导航堆栈顶部 Controller 的 topViewController 属性,这是您想要设置为您的委托(delegate)的!如果没有,那么您可以导航您的 UINavigationController 对象,您希望哪个对象作为您的委托(delegate)。

请记住,由于您是从应用程序委托(delegate)级别设置委托(delegate),因此您可能需要在此处指定您的协议(protocol)以避免含糊不清。

要在代码中实现这最后四个步骤,看起来像这样。

loginViewController.delegate = (id <TNTLoginViewControllerDelegate>)((UINavigationController *) self.window.rootViewController).topViewController;

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

确保不要忘记使用 application:viewControllerWithRestorationIdentifierPath:coder: 的含义。您只想在恢复 TNTLoginViewController 的情况下执行此操作。幸运的是,您可以使用传入的 identifierComponents 参数进行检查。将其与身份检查器中的身份名称进行比较,如果不匹配则返回 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/

相关文章:

iphone - 在 iPhone 中从运营商检索当前时间

ios - 将 NSString 解析为 NSDate

objective-c - 检测 iOS 8 自定义键盘中的键盘类型更改

ios - 删除委托(delegate)方法的 2 个实现中的重复代码

ios - 为所有 UINavigationBar 设置颜色

iOS 应用程序 - 应用内购买的实现逻辑

objective-c - 在 Mac OS X 应用程序中拥有 DAL 和 BLL 层是否可行?

ios - UITabBarController 内 UINavigationController 的 UINavigationBar 中缺少按钮的插图

c# - 非委托(delegate)类型的事件

iphone - 为什么在 Default.png 期间状态栏仍然显示?