【问题标题】:Resetting Storyboard on Logout注销时重置情节提要
【发布时间】:2012-05-03 16:09:09
【问题描述】:

我正在构建一个使用情节提要的 IOS 5.1 Web 客户端应用程序。我的操作之一是“注销”,在此期间我想将我的根视图重置为由情节提要的根视图创建的初始视图。 (当您登录时,一些视图项会根据您的身份被删除或添加;当您注销时,我想将它们重置为我在情节提要中指定的默认值。)

我意识到我可以以编程方式重置/重新添加所有元素,但是故事板有什么用呢?我想一定有办法通过重新加载视图文件来回到原点,对吧?

【问题讨论】:

  • 你有没有想过这个问题?我也有同样的需求……

标签: ios uiviewcontroller xib nib


【解决方案1】:

我发现以下方法对我有用。请注意,我使用 ARC,但不确定这是否对解决方案有很大影响。首先,在应用程序委托类中,在application:didFinishLaunchingWithOptions: 中,我使用以下代码行捕获初始 Storyboard 实例:

_initalStoryboard = self.window.rootViewController.storyboard;

(显然有实例变量UIStoryboard* _initalStoryboard;

然后我在我的应用委托中定义了以下函数:

- (void)resetWindowToInitialView
{
    for (UIView* view in self.window.subviews)
    {
        [view removeFromSuperview];
    }

    UIViewController* initialScene = [_initalStoryboard instantiateInitialViewController];
    self.window.rootViewController = initialScene;
}

请注意 for in 循环从window 中删除所有子视图。 UIWindow rootViewController 文档状态:

如果窗口有一个现有的视图层次结构,旧的视图是 在安装新的之前删除。

但是我没有发现这种情况......所以我在分配新的 rootViewController 之前自己明确删除了现有视图。使用这种方法,我没有发现任何令人担忧的副作用或内存泄漏。我绝不是 UIKit 魔法方面的专家,所以如果你打算自己使用它,我建议你测试并重新测试这个解决方案。干杯

【讨论】:

  • 我想试试这个,但没有真正展示如何在按下按钮时从控制器调用函数。
  • 查看这个 SO 问题:stackoverflow.com/questions/1184146/… 它显示了如何获取对应用程序委托的引用 - 在您的情况下,您将在场景的视图控制器中使用它。因此,在按钮的触摸处理程序中,您将拥有类似以下内容: MyApplicationDelegate *appDelegate = (MyApplicationDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate resetWindowToInitialView];
  • 可以使用更优雅的解决方案来代替 for[self.window.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]
【解决方案2】:

如果您使用基于 NavController 的结构,以下内容对我很有用:

UIWindow *window = [[UIApplication sharedApplication].windows firstObject];
UINavigationController *navController = (UINavigationController *)window.rootViewController;
UIViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"Login"];
navController.viewControllers = @[vc];

您必须将 Storyboard ID“Login”分配给您的 Login VC 才能正常工作。

【讨论】:

    【解决方案3】:

    如果我使用基于 UISplitViewController 的结构(在 iOS 8+ 上测试),以下对我有用:

    从项目常规 -> 部署信息中删除情节提要,因此下拉列表如下所示,您必须在代码中配置情节提要。

    AppDelegate.m某处

    - (void)setupViewControllers
    {
        // check for thread, as this method might be called by other (e.g. logout) logic
        if ([NSThread currentThread] != [NSThread mainThread]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self setupViewControllers];
            });
            return;
        }
    
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
        UIViewController *vc =[storyboard instantiateInitialViewController];
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.rootViewController = vc;
    
        // configure split vc 
        // Note: I reference split vc for my own purpose, but it is your mater of choice
        self.splitViewController = (UISplitViewController *)self.window.rootViewController;
        self.splitViewController.delegate = self;
        self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
        self.splitViewController.preferredPrimaryColumnWidthFraction = 0.5;
    
        [self.window makeKeyAndVisible];
    }
    

    为避免代码重复,请在首次设置时从application:didFinishLaunchingWithOptions: 调用此函数

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // some code...
        [self setupViewControllers];
        // Optional: add splash view (e.g. [self addSplashView];)
        // some code...
    }
    

    在视图控制器中,您已准备好向用户展示 UI,移除启动视图。例如(在 Swift 中):

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
    
        if !AppSession.currentSession().isLoggedIn() {
            presentLoginViewController(false, completion: { ()->Void in
                self.removeSplash()
            })
        }
        else {
           removeSplash()
        }
    
        // some code...
    }
    
    private func removeSplash() {
        if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            appDelegate.removeSplashView()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-10-12
      • 2015-01-14
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 2012-07-22
      • 2019-06-09
      • 1970-01-01
      相关资源
      最近更新 更多