如何:在重新排序后保存UITabBarItems的位置/顺序

时间:2011-09-26 14:14:16

标签: iphone ios xcode tabbar

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

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

3 个答案:

答案 0 :(得分:0)

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"]

然后,在应用重启时,加载数组并按正确的顺序设置标签项。

答案 1 :(得分:0)

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

我认为混淆来自于UITabBar.items返回的数组只有当前tabBar中可见的4个项目。当apple说你不应该搞乱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"];
    }
}

答案 2 :(得分:0)

我知道这是一个老问题,但我觉得发布这个就像我在查找如何做到这一点时所发现的那样。

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

我最终使用了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循环,但可能没有必要。