【问题标题】:How to: Save position/order of UITabBarItems after the have been reordered如何:在重新排序后保存 UITabBarItems 的位置/顺序
【发布时间】:2011-11-25 06:23:21
【问题描述】:

好的,我已经四处寻找这个问题的答案,但到目前为止还没有找到答案。

这是我的问题:我使用的是 Apple 提供的默认 TabBarApplication。由于我创建了 10 个选项卡,因此它使用默认的重新排序过程。因此,在我重新排序选项卡并退出应用程序后,我想保存应用程序重新启动时要恢复的选项卡的位置。我该怎么做?感谢代码示例!

【问题讨论】:

标签: iphone ios xcode tabbar


【解决方案1】:

tabItems 存储在一个数组中。你可以做这样的事情(伪代码):

* myArray = [tabBar tabBarItems];
* itemNameArray = [[NSMutableArray new] autorelease];
* for (UITabBarItem *item in myArray)
*     NSString *itemName = [item title];
*     [itemNameArray addObject: itemName];
* [[NSUserDefaults standardUserDefaults] setObject: itemNameArray forKey: @"TabItemNames"]

然后,在应用重新启动时,加载数组并以正确的顺序设置选项卡项。

【讨论】:

  • 感谢@Olie!你能解释一下我将如何实现它以及我将它放在哪里吗?
  • 我不明白你所说的“你将如何实现它”是什么意思——你会写代码来做我上面说的!至于你把它放在哪里,我想说你可能想在你的 applicationWillTerminate 方法中保存选项卡项目——或者可能是你的 viewController 的拆卸代码——并将它们设置在你的视图控制器的 viewDidLoad 中。恐怕我无法提供更具体的建议,因为我并不真正了解您的应用程序。简而言之,只要想想你想要发生什么,然后将其转化为代码!
【解决方案2】:

我也觉得这有点令人困惑。希望我的研究能帮助其他人...

我认为混淆来自于这样一个事实,即 UITabBar.items 返回一个只有当前 tabBar 中可见的 4 个项目的数组。当苹果说你不应该弄乱 tabBar 对象时,这就是他们的意思。

您读取项目顺序(并更新项目顺序)的方式是通过 UITabBarController 的 viewControllers 参数。

所以代码看起来像(这是在一个覆盖 UITabBarController 的类中):

- (UIViewController *)vcWithTabBarTitle:(NSString *)name
{

    NSLog(@"looking for UIViewController with tabBarItem.title = %@", name);
    for (UIViewController *item in self.viewControllers)
    {
        if ([item.tabBarItem.title isEqualToString:name])
            return item;
    }

    return nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    NSArray *itemNames = [userDefaults objectForKey:@"viewControllersOrder"]

    if (itemNames != nil && itemNames.count > 0)
    {
        NSMutableArray *items = [NSMutableArray arrayWithCapacity:self.viewControllers.count];
        for (NSString *itemName in itemNames)
        {
            [items addObject:[self vcWithTabBarTitle:itemName]];
        }
        [self setViewControllers:items];
    }
}

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
    if (changed)
    {
        NSMutableArray *itemNames = [[NSMutableArray alloc] initWithCapacity:viewControllers.count];
        for (UIViewController *item in viewControllers)
        {
            if (item.tabBarItem.title != nil)
            {
                [itemNames addObject:item.tabBarItem.title];
            }
        }

        [userDefaults setObject:itemNames forKey:@"viewControllersOrder"];
    }
}

【讨论】:

    【解决方案3】:

    我知道这是一个老问题,但我想发布此问题,因为这是我在查找如何执行此操作时发现的。

    所以其他答案(在我写这篇文章时)并不正确。但是,当您引入本地化或具有动态更改其标题的导航项时,它们会立即中断,这两种情况都非常可能。

    我最终使用了 restoreIdentifier,您可以在代码或 IB 中将其设置到任何视图控制器(或其中的子类)。

    注意:这是在 UITabBarController 的子类中实现的。

    保存标签栏视图控制器顺序

    NSMutableArray *tabBarVCIDs = [NSMutableArray new];
    for (UIViewController *viewController in [self viewControllers])
        [tabBarVCIDs addObject:[viewController rootRestorationIdentifier]];
    
    [[NSUserDefaults standardUserDefaults] setObject:tabBarVCIDs forKey:@"tabBarVCIDs"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    

    加载标签栏项目顺序

    NSMutableArray *tabBarVCIDs = [[NSUserDefaults standardUserDefaults] objectForKey:@"tabBarVCIDs"];
    if (tabBarVCIDs)
    {
        NSMutableArray *viewControllers = [NSMutableArray new];
        for (NSString *vcID in tabBarVCIDs)
        {
            for (UIViewController *viewController in [self viewControllers])
            {
                if ([[viewController rootRestorationIdentifier] isEqualToString:vcID])
                {
                    [viewControllers addObject:viewController];
                    break;
                }
            }
        }
        [self setViewControllers:viewControllers];
    }
    

    rootRestorationIdentifier 是我放入一个类别中的一种方法,即使视图控制器位于导航控制器或拆分视图控制器中,也可以获得正确的恢复标识符(这对于可能具有略微不同布局的通用应用程序很有用)。

    - (NSString *)rootRestorationIdentifier
    {
        if ([self isKindOfClass:[UINavigationController class]] || [self isKindOfClass:[UISplitViewController class]])
        {
            __weak UIViewController *rootVC = [[(UINavigationController *)self viewControllers] firstObject];
        return [rootVC rootRestorationIdentifier];
        }
    
        return [self restorationIdentifier];
    }
    

    您也可以使用 NSPredicate 代替嵌套的 for 循环,但这可能不是必需的。

    【讨论】:

      猜你喜欢
      • 2017-07-03
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 2016-05-13
      • 2020-03-30
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      相关资源
      最近更新 更多