如何:在 UITabBarController 中自定义选项卡时保存选项卡顺序

发布于 2024-08-17 04:20:26 字数 287 浏览 4 评论 0 原文

除了有关如何保存 UITabBarController 的 Tab 键顺序的文档之外,我无法找到任何其他信息,以便保存用户的自定义以供下次应用程序启动。我在网上搜索过,但无法找到任何通过正确代码执行此操作的博客文章或文章。

我意识到我必须使用 UITabBarController (didEndCustomizingViewControllers:) 的委托方法,但我不确定如何在保存用户想要选项卡的顺序状态方面最好地实现持久性。

有人可以发布一些代码,指出我吗方向正确,或者您有已保存内容的链接? :)

谢谢

I am having problems finding any other information than the docs for how to save the tab order for my UITabBarController, so that the user's customization is saved for next app launch. I have searched online, but have been unable to find any blog posts or articles that goes through the proper code for doing this.

I realize I have to use the delegate methods for the UITabBarController (didEndCustomizingViewControllers:) but I am not sure how I best approach persistance in terms of saving the state of the order the user wants the tabs in.

Can someone post some code, point me in the right direction or perhaps you have a link for something saved? :)

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

破晓 2024-08-24 04:20:26

至于您要求的一些示例代码,我将简单地在此处发布我如何在我的应用程序中处理相同的任务。

快速介绍:我使用 NIB 文件来存储初始 UITabBarController 状态,并且为了使我的选项卡彼此不同,我只需为分配给每个 UITabBarItem 对象定义标签变量UIViewController 填充在我的 UITabBarController 中。为了能够准确跟踪最后选定的选项卡(包括“更多”选项卡),我为 UITabBarControllerUINavigationControllerDelegateUITabBarControllerDelegate 实现了以下方法> 其 moreNavigationController。它们是:

#pragma mark UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [[NSUserDefaults standardUserDefaults] setInteger:mainTabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [[NSUserDefaults standardUserDefaults] setInteger:mainTabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

#pragma mark UITabBarControllerDelegate

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    [[NSUserDefaults standardUserDefaults] setInteger:tabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

下面是保存选项卡顺序的代码:

#pragma mark UITabBarControllerDelegate

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
    int count = mainTabBarController.viewControllers.count;
    NSMutableArray *savedTabsOrderArray = [[NSMutableArray alloc] initWithCapacity:count];
    for (int i = 0; i < count; i ++) {
        [savedTabsOrderArray addObject:[NSNumber numberWithInt:[[[mainTabBarController.viewControllers objectAtIndex:i] tabBarItem] tag]]];
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:savedTabsOrderArray] forKey:@"tabBarTabsOrder"];
    [savedTabsOrderArray release];
}

如您所见,我一直将选项卡索引的顺序存储在 NSUserDefaults 的数组中。

在应用程序在 applicationDidFinishLaunching: 方法中启动时,我使用以下代码重新排序了 UIViewControllers

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    mainTabBarController.delegate = self;

    int count = mainTabBarController.viewControllers.count;
    NSArray *savedTabsOrderArray = [[userDefaults arrayForKey:@"tabBarTabsOrder"] retain];
    if (savedTabsOrderArray.count == count) {
        BOOL needsReordering = NO;

        NSMutableDictionary *tabsOrderDictionary = [[NSMutableDictionary alloc] initWithCapacity:count];
        for (int i = 0; i < count; i ++) {
            NSNumber *tag = [[NSNumber alloc] initWithInt:[[[mainTabBarController.viewControllers objectAtIndex:i] tabBarItem] tag]];
            [tabsOrderDictionary setObject:[NSNumber numberWithInt:i] forKey:[tag stringValue]];

        if (!needsReordering && ![(NSNumber *)[savedTabsOrderArray objectAtIndex:i] isEqualToNumber:tag]) {
                needsReordering = YES;
            }
        }

        if (needsReordering) {
            NSMutableArray *tabsViewControllers = [[NSMutableArray alloc] initWithCapacity:count];
            for (int i = 0; i < count; i ++) {
                [tabsViewControllers addObject:[mainTabBarController.viewControllers objectAtIndex:
                                                [(NSNumber *)[tabsOrderDictionary objectForKey:
                                                              [(NSNumber *)[savedTabsOrderArray objectAtIndex:i] stringValue]] intValue]]];
            }
            [tabsOrderDictionary release];

            mainTabBarController.viewControllers = [NSArray arrayWithArray:tabsViewControllers];
            [tabsViewControllers release];
        }
    }
    [savedTabsOrderArray release];

    if ([userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"]) {
        if ([userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"] == 2147483647) {
            mainTabBarController.selectedViewController = mainTabBarController.moreNavigationController;
        }
        else {
            mainTabBarController.selectedIndex = [userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"];
        }
    }

    mainTabBarController.moreNavigationController.delegate = self;

    [window addSubview:mainTabBarController.view];
}

这非常棘手,可能看起来很奇怪,但不要忘记我的 UITabBarController 完全在 nib 文件中创建。如果您以编程方式构建它,您可以简单地执行相同的操作,但遵循保存的顺序。

PS:并且不要忘记在应用终止时同步 NSUserDefaults

- (void)applicationWillTerminate:(UIApplication *)application {
    [[NSUserDefaults standardUserDefaults] synchronize];
}

我希望这会有所帮助。如果有不清楚的地方请评论并询问。

As far as you've asked for some sample code I will simply post here how I dealt with the same task in my app.

Quick intro: I was using a NIB file for storing initial UITabBarController state and to differ my tabs one from another I simply defined tag variables for UITabBarItem objects assigned to each UIViewController stuffed in my UITabBarController. To be able to accurately track last selected tab (including the 'More' one) I've implemented following methods for UITabBarControllerDelegate of my UITabBarController and UINavigationControllerDelegate of its moreNavigationController. Here they are:

#pragma mark UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [[NSUserDefaults standardUserDefaults] setInteger:mainTabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [[NSUserDefaults standardUserDefaults] setInteger:mainTabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

#pragma mark UITabBarControllerDelegate

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    [[NSUserDefaults standardUserDefaults] setInteger:tabBarController.selectedIndex forKey:@"mainTabBarControllerSelectedIndex"];
}

And here's the code for saving the tabs order:

#pragma mark UITabBarControllerDelegate

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
    int count = mainTabBarController.viewControllers.count;
    NSMutableArray *savedTabsOrderArray = [[NSMutableArray alloc] initWithCapacity:count];
    for (int i = 0; i < count; i ++) {
        [savedTabsOrderArray addObject:[NSNumber numberWithInt:[[[mainTabBarController.viewControllers objectAtIndex:i] tabBarItem] tag]]];
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:savedTabsOrderArray] forKey:@"tabBarTabsOrder"];
    [savedTabsOrderArray release];
}

As you can see I've been storing the order of tabs' indexes in an array in NSUserDefaults.

On app's launch in applicationDidFinishLaunching: method I reordered the UIViewControllers using following code:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    mainTabBarController.delegate = self;

    int count = mainTabBarController.viewControllers.count;
    NSArray *savedTabsOrderArray = [[userDefaults arrayForKey:@"tabBarTabsOrder"] retain];
    if (savedTabsOrderArray.count == count) {
        BOOL needsReordering = NO;

        NSMutableDictionary *tabsOrderDictionary = [[NSMutableDictionary alloc] initWithCapacity:count];
        for (int i = 0; i < count; i ++) {
            NSNumber *tag = [[NSNumber alloc] initWithInt:[[[mainTabBarController.viewControllers objectAtIndex:i] tabBarItem] tag]];
            [tabsOrderDictionary setObject:[NSNumber numberWithInt:i] forKey:[tag stringValue]];

        if (!needsReordering && ![(NSNumber *)[savedTabsOrderArray objectAtIndex:i] isEqualToNumber:tag]) {
                needsReordering = YES;
            }
        }

        if (needsReordering) {
            NSMutableArray *tabsViewControllers = [[NSMutableArray alloc] initWithCapacity:count];
            for (int i = 0; i < count; i ++) {
                [tabsViewControllers addObject:[mainTabBarController.viewControllers objectAtIndex:
                                                [(NSNumber *)[tabsOrderDictionary objectForKey:
                                                              [(NSNumber *)[savedTabsOrderArray objectAtIndex:i] stringValue]] intValue]]];
            }
            [tabsOrderDictionary release];

            mainTabBarController.viewControllers = [NSArray arrayWithArray:tabsViewControllers];
            [tabsViewControllers release];
        }
    }
    [savedTabsOrderArray release];

    if ([userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"]) {
        if ([userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"] == 2147483647) {
            mainTabBarController.selectedViewController = mainTabBarController.moreNavigationController;
        }
        else {
            mainTabBarController.selectedIndex = [userDefaults integerForKey:@"mainTabBarControllerSelectedIndex"];
        }
    }

    mainTabBarController.moreNavigationController.delegate = self;

    [window addSubview:mainTabBarController.view];
}

It's quite tricky and may seem strange, but don't forget that my UITabBarController was fully created in a nib file. If you construct it programmatically you may simply do the same but following the saved order.

P.S.: and don't forget to synchronize NSUserDefaults when your app terminates.

- (void)applicationWillTerminate:(UIApplication *)application {
    [[NSUserDefaults standardUserDefaults] synchronize];
}

I hope this will help. If something is not clear please do comment and ask.

小伙你站住 2024-08-24 04:20:26

首先我投票赞成之前的答案,但后来我注意到它是多么复杂。它可以而且应该被简化。

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    NSArray *initialViewControllers = [NSArray arrayWithArray:self.tabBarController.viewControllers];
    NSArray *tabBarOrder = [[AppDelegate sharedSettingsService] tabBarOrder];
    if (tabBarOrder) {
        NSMutableArray *newViewControllers = [NSMutableArray arrayWithCapacity:initialViewControllers.count];
        for (NSNumber *tabBarNumber in tabBarOrder) {
            NSUInteger tabBarIndex = [tabBarNumber unsignedIntegerValue];
            [newViewControllers addObject:[initialViewControllers objectAtIndex:tabBarIndex]];
        }
        self.tabBarController.viewControllers = newViewControllers;
    }

    NSInteger tabBarSelectedIndex = [[AppDelegate sharedSettingsService] tabBarSelectedIndex];
    if (NSIntegerMax == tabBarSelectedIndex) {
        self.tabBarController.selectedViewController = self.tabBarController.moreNavigationController;
    } else {
        self.tabBarController.selectedIndex = tabBarSelectedIndex;
    }

    /* Add the tab bar controller's current view as a subview of the window. */
    [self.window addSubview:self.tabBarController.view];
}

- (void)applicationWillTerminate:(UIApplication *)application {

    NSInteger tabBarSelectedIndex = self.tabBarController.selectedIndex;
    [[AppDelegate sharedSettingsService] setTabBarSelectedIndex:tabBarSelectedIndex];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {

        NSUInteger count = tabBarController.viewControllers.count;
        NSMutableArray *tabOrderArray = [[NSMutableArray alloc] initWithCapacity:count];
        for (UIViewController *viewController in viewControllers) {

            NSInteger tag = viewController.tabBarItem.tag;
            [tabOrderArray addObject:[NSNumber numberWithInteger:tag]];
        }

        [[AppDelegate sharedSettingsService] setTabBarOrder:[NSArray arrayWithArray:tabOrderArray]];
        [tabOrderArray release];
    }

这一切都发生在 AppDelegate 中。您将 UITabBarController 的委托设置为 Interface Builder 中的 AppDelegate 实例。 SharedSettingsService 是为我保存数据的。基本上它可以是 NSUserDefaults 前端或任何你喜欢的东西(例如 CoreData)。所以一切都很简单,Interface Builder 在这里有所帮助,而不是让事情变得更复杂。

First I voted up the previous answer, but then I noticed how ridiculously complex it is. It can and should be simplified.

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    NSArray *initialViewControllers = [NSArray arrayWithArray:self.tabBarController.viewControllers];
    NSArray *tabBarOrder = [[AppDelegate sharedSettingsService] tabBarOrder];
    if (tabBarOrder) {
        NSMutableArray *newViewControllers = [NSMutableArray arrayWithCapacity:initialViewControllers.count];
        for (NSNumber *tabBarNumber in tabBarOrder) {
            NSUInteger tabBarIndex = [tabBarNumber unsignedIntegerValue];
            [newViewControllers addObject:[initialViewControllers objectAtIndex:tabBarIndex]];
        }
        self.tabBarController.viewControllers = newViewControllers;
    }

    NSInteger tabBarSelectedIndex = [[AppDelegate sharedSettingsService] tabBarSelectedIndex];
    if (NSIntegerMax == tabBarSelectedIndex) {
        self.tabBarController.selectedViewController = self.tabBarController.moreNavigationController;
    } else {
        self.tabBarController.selectedIndex = tabBarSelectedIndex;
    }

    /* Add the tab bar controller's current view as a subview of the window. */
    [self.window addSubview:self.tabBarController.view];
}

- (void)applicationWillTerminate:(UIApplication *)application {

    NSInteger tabBarSelectedIndex = self.tabBarController.selectedIndex;
    [[AppDelegate sharedSettingsService] setTabBarSelectedIndex:tabBarSelectedIndex];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {

        NSUInteger count = tabBarController.viewControllers.count;
        NSMutableArray *tabOrderArray = [[NSMutableArray alloc] initWithCapacity:count];
        for (UIViewController *viewController in viewControllers) {

            NSInteger tag = viewController.tabBarItem.tag;
            [tabOrderArray addObject:[NSNumber numberWithInteger:tag]];
        }

        [[AppDelegate sharedSettingsService] setTabBarOrder:[NSArray arrayWithArray:tabOrderArray]];
        [tabOrderArray release];
    }

All this happens in AppDelegate. You set UITabBarController's delegate to AppDelegate instance in Interface Builder. sharedSettingsService is what persists the data for me. Basically it can be a NSUserDefaults front-end or anything you like (CoreData for example). So everything is simple, Interface Builder helps here, not makes things more complex.

捶死心动 2024-08-24 04:20:26

也许是迟到了,但在学校学习 Swift 还不到两个月,而且我花了十五个小时以上的时间来学习 Swift,因为我在互联网上找不到合适的解释。

这是 Swift 中的一个解决方案

  1. 给所有 tabItem 一个标签,从 1 开始。您可以在每个单独的视图中执行此操作。如果您有六个视图,则在这种情况下,它们的 tabItem 将有一个唯一的编号,每个编号范围在 1 到 6 之间。

  2. UITabBarControllerDelegate 添加到所有 ViewController 的类中,以便您可以使用稍后介绍的函数第 5 点。

    class FirstViewController: UIViewController, UITabBarControllerDelegate {
    
  3. 添加以下全局变量 (作为示例,就在上面的代码之后),以便您可以从类中的任何函数将变量本地保存在手机上。

    let defaults = NSUserDefaults.standardUserDefaults()
    
  4. 将 tabBarController 委托给视图,以便视图可以更新对 tabBarController 的任何更改。将以下内容放入您的viewDidLoad()中。

    tabBarController!.delegate = self
    
  5. 实现以下代码。当用户编辑选项卡视图时,此选项将激活。该代码的作用是按照[ViewControllers]的标签顺序(用户更改标签后)并将其保存在手机本地。第一个 viewController 的标记以整数形式保存在变量“0”中,第二个标记保存在名为“1”的变量中,依此类推。

    func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], 更改: Bool) {
        如果(改变){
            print("新的 Tab 键顺序:")
            for (var i=0; i

打印结果会告诉您选项卡的新顺序。你不需要什么,但我认为很高兴看到后台发生的事情。所有这一切只是为了保存选项卡的顺序。现在,您必须在程序启动时检索它们。

  1. UIViewControl 文件切换到 AppDelegate.swift

  2. 最后,在 func application(application: UIApplication, didFinishLaunchingWithOptions... 中编写以下内容,您可以在 AppDelegate.swift 的顶部找到它。

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) ->布尔{
    // 让您读取和写入手机上的局部变量
    让默认值 = NSUserDefaults.standardUserDefaults()
    
    // 访问你的 tabBarController
    让 tabBar: UITabBarController = self.window?.rootViewController 为! UITabBar控制器
    
    var junkViewControllers = [UIViewController]()
    
    // 如果未设置则返回 0,因此 tabItem 的标签从 1 开始。
    var tagNumber : Int = defaults.integerForKey("0")
    
    if (标签编号!= 0) {
        for (var i=0; i

tabBarController 包含的所有视图都作为数组存储在 tabBarController.viewControllers 中。

此代码基本上创建了一个名为 junkViewControllers 的数组。然后,循环根据 UIViewController 的标签,按照先前存储的变量的顺序添加程序中现有的 UIViewController。当所有这些完成后,缩短为 tabBar 的 tabBarController 将被数组 覆盖。 >垃圾ViewController

Perhaps late to the game, but been learning Swift for less than two months at school and sat perhaps more than fifteen hours with this because I couldn't find a decent explanation on the interwebz.

Here is a solution in Swift

  1. Give all your tabItem's a tag, starting at 1. You do this in each separate view. If you got six views, their tabItems will in that case have a unique number each ranging between 1 and 6.

  2. Add UITabBarControllerDelegate to all the ViewControllers' classes so you can use the function explained later in point 5.

    class FirstViewController: UIViewController, UITabBarControllerDelegate {
    
  3. Add the following variable globally (right after the code above, as an example) so you can save variables locally on the phone from any function within the class.

    let defaults = NSUserDefaults.standardUserDefaults()
    
  4. Delegate the tabBarController to the view so the view can update any changes to the tabBarController. Put the following into your viewDidLoad().

    tabBarController!.delegate = self
    
  5. Implement the following code. This one will activate when the user is editing the tab view. What the code does is taking the [ViewControllers]'s tags in the order they are in (after the user changed it) and saves it locally on the phone. The first viewController's tag is saved as an integer in the variable "0", the second tag in a variable called "1", and so on.

    func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool) {
        if (changed) {
            print("New tab order:")
            for (var i=0; i<viewControllers.count; i++) {
                defaults.setInteger(viewControllers[i].tabBarItem.tag, forKey: String(i))
                print("\(i): \(viewControllers[i].tabBarItem.title!) (\(viewControllers[i].tabBarItem.tag))")
            }
        }
    }
    

The prints tell you the new order of the tabs. Nothing you will need, but I think it's nice to see what's happening in the background. All this was only to save the order of the tabs. You will now have to retrieve them when the program is starting.

  1. Switch from your UIViewControl file to AppDelegate.swift.

  2. Finally, write the following in func application(application: UIApplication, didFinishLaunchingWithOptions... that you can find at the top of AppDelegate.swift.

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Let you read and write to local variables on your phone
    let defaults = NSUserDefaults.standardUserDefaults()
    
    // Getting access to your tabBarController
    let tabBar: UITabBarController = self.window?.rootViewController as! UITabBarController
    
    var junkViewControllers = [UIViewController]()
    
    // returns 0 if not set, hence having the tabItem's tags starting at 1.
    var tagNumber : Int = defaults.integerForKey("0")
    
    if (tagNumber != 0) {
        for (var i=0; i<tabBar.viewControllers?.count; i++) {
            // the tags are between 1-6 but the order of the
            // viewControllers in the array are between 0-5
            // hence the "-1" below.
            tagNumber = defaults.integerForKey( String(i) ) - 1
            junkViewControllers.append(tabBar.viewControllers![tagNumber])
        }
    
        tabBar.viewControllers = junkViewControllers
    }
    }
    

What is good to know is that all views that a tabBarController contains is stored as an array in tabBarController.viewControllers.

This code basically creates an array called junkViewControllers. The for-loop then adds the existing UIViewControllers from the program in the order from the previous stored variables, based on the UIViewControllers' tags. When all this is done, the tabBarController shortened to tabBar is overwritten with the array junkViewController.

烙印 2024-08-24 04:20:26

这就是我的秘诀,建立在 Rickard & 的答案的基础上。杰斯珀。所有代码都进入主 TabBarController。

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {

let tabOrderKey = "customTabBarOrder"

override func viewDidLoad() {
    super.viewDidLoad()

    self.delegate = self
    loadCustomTabOrder()
}

func loadCustomTabOrder() {

    let defaults = NSUserDefaults.standardUserDefaults()
    let standardOrderChanged = defaults.boolForKey(tabOrderKey)

    if standardOrderChanged {
        print("Standard Order has changed")

        var VCArray = [UIViewController]()
        var tagNumber = 0

        let tabBar = self as UITabBarController

        if let countVC = tabBar.viewControllers?.count {
            print("\(countVC) VCs in total")
            for var x = 0; x < countVC; x++ {
                tagNumber = defaults.integerForKey("tabPosition\(x)")

                for VC in tabBar.viewControllers! {
                    if tagNumber == VC.tabBarItem.tag {
                        VCArray.append(VC)
                        print("Position \(x): \(VCArray[x].tabBarItem.title!) VC (tag \(tagNumber))")
                    }
                }
            }
        }
        tabBar.viewControllers = VCArray
    }

}

func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool) {

    print("Change func called")

    if changed {
        print("Order has changed")
        let defaults = NSUserDefaults.standardUserDefaults()

        for var x = 0; x < viewControllers.count; x++ {
            defaults.setInteger(viewControllers[x].tabBarItem.tag, forKey: "tabPosition\(x)")
            print("\(viewControllers[x].tabBarItem.title!) VC (with tag: \(viewControllers[x].tabBarItem.tag)) is now in position \(x)")
        }
        defaults.setBool(true, forKey: tabOrderKey)
    } else {
        print("Nothing has changed")
    }
}

}

This is what did the trick for me, building on the answers from Rickard & Jesper. All of the code goes into the main TabBarController.

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {

let tabOrderKey = "customTabBarOrder"

override func viewDidLoad() {
    super.viewDidLoad()

    self.delegate = self
    loadCustomTabOrder()
}

func loadCustomTabOrder() {

    let defaults = NSUserDefaults.standardUserDefaults()
    let standardOrderChanged = defaults.boolForKey(tabOrderKey)

    if standardOrderChanged {
        print("Standard Order has changed")

        var VCArray = [UIViewController]()
        var tagNumber = 0

        let tabBar = self as UITabBarController

        if let countVC = tabBar.viewControllers?.count {
            print("\(countVC) VCs in total")
            for var x = 0; x < countVC; x++ {
                tagNumber = defaults.integerForKey("tabPosition\(x)")

                for VC in tabBar.viewControllers! {
                    if tagNumber == VC.tabBarItem.tag {
                        VCArray.append(VC)
                        print("Position \(x): \(VCArray[x].tabBarItem.title!) VC (tag \(tagNumber))")
                    }
                }
            }
        }
        tabBar.viewControllers = VCArray
    }

}

func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool) {

    print("Change func called")

    if changed {
        print("Order has changed")
        let defaults = NSUserDefaults.standardUserDefaults()

        for var x = 0; x < viewControllers.count; x++ {
            defaults.setInteger(viewControllers[x].tabBarItem.tag, forKey: "tabPosition\(x)")
            print("\(viewControllers[x].tabBarItem.title!) VC (with tag: \(viewControllers[x].tabBarItem.tag)) is now in position \(x)")
        }
        defaults.setBool(true, forKey: tabOrderKey)
    } else {
        print("Nothing has changed")
    }
}

}
韵柒 2024-08-24 04:20:26

我将解释如何以编程方式执行此操作。注意:这是使用 ARC,因此您可能必须根据需要插入保留/释放调用。

您可以使用 UITabBarItemtag 属性进行排序。对于要添加到 UITabBarController 的每个 UIViewController,请确保每个都有唯一的标签

- (id)init
{
    self = [super init];
    if (self) {
        self.tabBarItem.tag = 0;
        self.tabBarItem.image = <image>;
        self.tabBarItem.title = <title>;
    }
    return self;
}

大概您只会使用它们的标签的默认排序顺序,因此您原始的第一个视图控制器将是 0,然后是 1、2、3 等。

在 AppDelegate 的 didFinishLaunchingWithOptions

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{    
    self.tabBarController = [[UITabBarController alloc] init];
    self.tabBarController.delegate = self;

    NSMutableArray *unsortedControllers = [NSMutableArray array];

    UIViewController *viewOne = [[UIViewController alloc] init];
    [unsortedControllers addObject:viewOne];

    UIViewController *viewTwo = [[UIViewController alloc] init];
    [unsortedControllers addObject:viewTwo];
    ...

当它们全部实例化并添加到数组中后,您将通过查询 NSUserDefaults 来检查用户是否自定义了其订单。默认情况下,您将存储用户自定义的选项卡栏顺序的数组。这将是一个 NSNumbers 数组(最后一个代码片段中解释了如何创建它)。使用它们创建一个新的“排序”视图控制器数组并将其传递给选项卡栏控制器。如果他们没有自定义顺序,默认将返回 nil,您可以简单地使用未排序的数组。

    ...
    NSArray *tabBarOrder = [[NSUserDefaults standardUserDefaults] arrayForKey:@"tabBarOrder"];
    if (tabBarOrder)
    {
      NSMutableArray *sortedControllers = [NSMutableArray array];
      for (NSNumber *sortNumber in tabBarOrder)
      {
         [sortedControllers addObject:[unsortedControllers objectAtIndex:[sortNumber intValue]]];
      }
      self.tabBarController.viewControllers = sortedControllers;
    } else {
      self.tabBarController.viewControllers = unsortedControllers;
    }
    [self.window setRootViewController:self.tabBarController];
    [self.window makeKeyAndVisible];

    return YES;
}

要创建自定义排序顺序,请使用 UITabBarController 的委托方法:

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
    NSMutableArray *tabOrderArray = [[NSMutableArray alloc] init];
    for (UIViewController *vc in self.tabBarController.viewControllers)
    {
        [tabOrderArray addObject:[NSNumber numberWithInt:[[vc tabBarItem] tag]]];
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:tabOrderArray] forKey:@"tabBarOrder"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

I will explain how to do this programmatically. NOTE: This is using ARC, so you may have to insert retain/release calls as needed.

You use the tag property of the UITabBarItem for sorting. For every UIViewController that you are adding to the UITabBarController, make sure that each has a unique tag.

- (id)init
{
    self = [super init];
    if (self) {
        self.tabBarItem.tag = 0;
        self.tabBarItem.image = <image>;
        self.tabBarItem.title = <title>;
    }
    return self;
}

Presumably you would just use their default sorting order for their tags, so whatever you have as your original first view controller would be 0, followed by 1, 2, 3, etc.

Set up your UIViewControllers in the AppDelegate's didFinishLaunchingWithOptions as you normally would, making sure that you are instantiating them in their "default order". As you do so, add them to an instance of a NSMutableArray.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{    
    self.tabBarController = [[UITabBarController alloc] init];
    self.tabBarController.delegate = self;

    NSMutableArray *unsortedControllers = [NSMutableArray array];

    UIViewController *viewOne = [[UIViewController alloc] init];
    [unsortedControllers addObject:viewOne];

    UIViewController *viewTwo = [[UIViewController alloc] init];
    [unsortedControllers addObject:viewTwo];
    ...

After they are all instantiated and added to the array, you will check to see if the user has customized their order by querying NSUserDefaults. In the defaults, you will store an array of the user's customized tab bar order. This will be an array of NSNumbers (how this is created is explain in the last code snippet). Use these to create a new "sorted" array of view controllers and pass that to the tab bar controller. If they haven't customized the order, the default will return nil and you can simply used the unsorted array.

    ...
    NSArray *tabBarOrder = [[NSUserDefaults standardUserDefaults] arrayForKey:@"tabBarOrder"];
    if (tabBarOrder)
    {
      NSMutableArray *sortedControllers = [NSMutableArray array];
      for (NSNumber *sortNumber in tabBarOrder)
      {
         [sortedControllers addObject:[unsortedControllers objectAtIndex:[sortNumber intValue]]];
      }
      self.tabBarController.viewControllers = sortedControllers;
    } else {
      self.tabBarController.viewControllers = unsortedControllers;
    }
    [self.window setRootViewController:self.tabBarController];
    [self.window makeKeyAndVisible];

    return YES;
}

To create to customized sort order, use the UITabBarController's delegate method:

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
    NSMutableArray *tabOrderArray = [[NSMutableArray alloc] init];
    for (UIViewController *vc in self.tabBarController.viewControllers)
    {
        [tabOrderArray addObject:[NSNumber numberWithInt:[[vc tabBarItem] tag]]];
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:tabOrderArray] forKey:@"tabBarOrder"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
π浅易 2024-08-24 04:20:26

Rickard Elimää 进一步简化了答案。使用 tabBarController CustomizingViewControllers 的委托函数保存和加载自定义 ViewControllers 的“Swift”解决方案。

我就是这样做的。

class TabBarController: UITabBarController, UITabBarControllerDelegate {

    let kOrder = "customOrder"

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self

        loadCustomizedViews()
    }

    func loadCustomizedViews(){
        let defaults = NSUserDefaults.standardUserDefaults()

        // returns 0 if not set, hence having the tabItem's tags starting at 1.
        let changed : Bool = defaults.boolForKey(kOrder)

        if changed {
            var customViewControllers = [UIViewController]()
            var tagNumber: Int = 0
            for (var i=0; i<self.viewControllers?.count; i++) {
                // the tags are between 0-6 and the
                // viewControllers in the array are between 0-6
                // so we swap them to match the custom order
                tagNumber = defaults.integerForKey( String(i) )

                //print("TabBar re arrange i = \(i), tagNumber = \(tagNumber),  viewControllers.count = \(self.viewControllers?.count) ")
                customViewControllers.append(self.viewControllers![tagNumber])
            }

            self.viewControllers = customViewControllers
        }
    }

    func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool){

        if (changed) {
            let defaults = NSUserDefaults.standardUserDefaults()
            //print("New tab order:")
            for (var i=0; i<viewControllers.count; i++) {
                defaults.setInteger(viewControllers[i].tabBarItem.tag, forKey: String(i))
                //print("\(i): \(viewControllers[i].tabBarItem.title!) (\(viewControllers[i].tabBarItem.tag))")
            }

            defaults.setBool(changed, forKey: kOrder)
        }
    }
}

Simplified Rickard Elimää answer even further. "Swift" solution to saving and loading Customized ViewControllers using the delegate function of tabBarController CustomizingViewControllers.

This is how I did it.

class TabBarController: UITabBarController, UITabBarControllerDelegate {

    let kOrder = "customOrder"

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self

        loadCustomizedViews()
    }

    func loadCustomizedViews(){
        let defaults = NSUserDefaults.standardUserDefaults()

        // returns 0 if not set, hence having the tabItem's tags starting at 1.
        let changed : Bool = defaults.boolForKey(kOrder)

        if changed {
            var customViewControllers = [UIViewController]()
            var tagNumber: Int = 0
            for (var i=0; i<self.viewControllers?.count; i++) {
                // the tags are between 0-6 and the
                // viewControllers in the array are between 0-6
                // so we swap them to match the custom order
                tagNumber = defaults.integerForKey( String(i) )

                //print("TabBar re arrange i = \(i), tagNumber = \(tagNumber),  viewControllers.count = \(self.viewControllers?.count) ")
                customViewControllers.append(self.viewControllers![tagNumber])
            }

            self.viewControllers = customViewControllers
        }
    }

    func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool){

        if (changed) {
            let defaults = NSUserDefaults.standardUserDefaults()
            //print("New tab order:")
            for (var i=0; i<viewControllers.count; i++) {
                defaults.setInteger(viewControllers[i].tabBarItem.tag, forKey: String(i))
                //print("\(i): \(viewControllers[i].tabBarItem.title!) (\(viewControllers[i].tabBarItem.tag))")
            }

            defaults.setBool(changed, forKey: kOrder)
        }
    }
}
北城挽邺 2024-08-24 04:20:26

更新了 Swift 2.0 的答案

`
let tabBarOrderKey = "tabBarOrderKey"

extension TabBarButtonsController: UITabBarControllerDelegate {

 // Saves new tab bar custom order

  func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool) {
var orderedTagItems = [Int]()
if changed {
  for viewController in viewControllers {
    let tag = viewController.tabBarItem.tag
    orderedTagItems.append(tag)

  }
  NSUserDefaults.standardUserDefaults().setObject(orderedTagItems, forKey: tabBarOrderKey)
}
}

// set up tag to compare with when pulling from defaults and for saving initial tab bar change

func setUpTabBarItemTags() {
var tag = 0
if let viewControllers = viewControllers {
  for view in viewControllers {
    view.tabBarItem.tag = tag
    tag += 1
  }
 }
}

// Get Saved Tab Bar Order from defaults

func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
  if let tabBarOrder = NSUserDefaults.standardUserDefaults().objectForKey(tabBarOrderKey) as? [Int] {
    for tag in tabBarOrder {
      newViewControllerOrder.append(initialViewControllers[tag])
    }
    setViewControllers(newViewControllerOrder, animated: false)
  }
 }
}

}

`

请记住设置委托并在加载的视图中调用这些方法

Updated Answer for Swift 2.0

`
let tabBarOrderKey = "tabBarOrderKey"

extension TabBarButtonsController: UITabBarControllerDelegate {

 // Saves new tab bar custom order

  func tabBarController(tabBarController: UITabBarController, didEndCustomizingViewControllers viewControllers: [UIViewController], changed: Bool) {
var orderedTagItems = [Int]()
if changed {
  for viewController in viewControllers {
    let tag = viewController.tabBarItem.tag
    orderedTagItems.append(tag)

  }
  NSUserDefaults.standardUserDefaults().setObject(orderedTagItems, forKey: tabBarOrderKey)
}
}

// set up tag to compare with when pulling from defaults and for saving initial tab bar change

func setUpTabBarItemTags() {
var tag = 0
if let viewControllers = viewControllers {
  for view in viewControllers {
    view.tabBarItem.tag = tag
    tag += 1
  }
 }
}

// Get Saved Tab Bar Order from defaults

func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
  if let tabBarOrder = NSUserDefaults.standardUserDefaults().objectForKey(tabBarOrderKey) as? [Int] {
    for tag in tabBarOrder {
      newViewControllerOrder.append(initialViewControllers[tag])
    }
    setViewControllers(newViewControllerOrder, animated: false)
  }
 }
}

}

`

Remember to set the delegate and call these methods in the view did load

飘过的浮云 2024-08-24 04:20:26

我想分享我已经工作了近 3 天的代码,现在正在尝试各种组合,但有很多错误和失败 - 编码的一般寿命!哈哈。无论如何,下面的代码适用于 Swift 5。
这是如何:保存顺序的提取在 Sam 的代码 UITabBarController 中自定义选项卡时使用选项卡,但使用了 Swift 5 的 for 循环更新。
我的工作非常顺利,全部都在 TabBarViewController.swift 文件中。

因此,如果您只是将其粘贴到 Swift 文件中,请确保您的选项卡栏项目具有来自属性检查器的标签号,然后就可以开始了!

首先再次感谢 Sam 提供的代码。

import UIKit


class TabBarController: UITabBarController, UITabBarControllerDelegate {

let tabOrderKey = "customTabBarOrder"

override func viewDidLoad() {
super.viewDidLoad()

self.delegate = self
loadCustomTabOrder()
}

func loadCustomTabOrder() {

let defaults = UserDefaults.standard
let standardOrderChanged = defaults.bool(forKey: tabOrderKey)

if standardOrderChanged {
    print("Standard Order has changed")

    var VCArray = [UIViewController]()
    var tagNumber = 0

    let tabBar = self as UITabBarController

    if let countVC = tabBar.viewControllers?.count {
        print("\(countVC) VCs in total")
        for x in 0..<countVC {
            tagNumber = defaults.integer(forKey: "tabPosition\(x)")

            for VC in tabBar.viewControllers! {
                if tagNumber == VC.tabBarItem.tag {
                    VCArray.append(VC)
                    print("Position \(x): \(VCArray[x].tabBarItem.title!) VC (tag \(tagNumber))")
                }
            }
        }
    }
    tabBar.viewControllers = VCArray
 }

 }

func tabBarController(_ tabBarController: UITabBarController, didEndCustomizing viewControllers: [UIViewController], changed: Bool) {

print("Change func called")

if changed {
    print("Order has changed")
    let defaults = UserDefaults.standard

    for x in 0..<(viewControllers.count)  {
        defaults.set(viewControllers[x].tabBarItem.tag, forKey: "tabPosition\(x)")
        print("\(viewControllers[x].tabBarItem.title!) VC (with tag: \(viewControllers[x].tabBarItem.tag)) is now in position \(x)")
   }
    defaults.set(true, forKey: tabOrderKey)
    } else {
    print("Nothing has changed")
    }
  }

}

I'd like to share the code I have been working on for nearly 3 days now trying all sorts of combinations with many errors and failure - the general life of coding! ha ha. Anyway the code below works with Swift 5.
It's the extraction of How to: Save order of tabs when customizing tabs in UITabBarController , Sam's Code, but with the for loop update for Swift 5.
I have got this working great, all in the TabBarViewController.swift file.

So if you just paste this into your Swift file, make sure your Tab Bar Items have a tag number from the Attributes Inspector and your good to go!

Thanks again to Sam for the Code in the first place.

import UIKit


class TabBarController: UITabBarController, UITabBarControllerDelegate {

let tabOrderKey = "customTabBarOrder"

override func viewDidLoad() {
super.viewDidLoad()

self.delegate = self
loadCustomTabOrder()
}

func loadCustomTabOrder() {

let defaults = UserDefaults.standard
let standardOrderChanged = defaults.bool(forKey: tabOrderKey)

if standardOrderChanged {
    print("Standard Order has changed")

    var VCArray = [UIViewController]()
    var tagNumber = 0

    let tabBar = self as UITabBarController

    if let countVC = tabBar.viewControllers?.count {
        print("\(countVC) VCs in total")
        for x in 0..<countVC {
            tagNumber = defaults.integer(forKey: "tabPosition\(x)")

            for VC in tabBar.viewControllers! {
                if tagNumber == VC.tabBarItem.tag {
                    VCArray.append(VC)
                    print("Position \(x): \(VCArray[x].tabBarItem.title!) VC (tag \(tagNumber))")
                }
            }
        }
    }
    tabBar.viewControllers = VCArray
 }

 }

func tabBarController(_ tabBarController: UITabBarController, didEndCustomizing viewControllers: [UIViewController], changed: Bool) {

print("Change func called")

if changed {
    print("Order has changed")
    let defaults = UserDefaults.standard

    for x in 0..<(viewControllers.count)  {
        defaults.set(viewControllers[x].tabBarItem.tag, forKey: "tabPosition\(x)")
        print("\(viewControllers[x].tabBarItem.title!) VC (with tag: \(viewControllers[x].tabBarItem.tag)) is now in position \(x)")
   }
    defaults.set(true, forKey: tabOrderKey)
    } else {
    print("Nothing has changed")
    }
  }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文