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

Iphone 如何:在UITabBarController中自定义选项卡时保存选项卡顺序,iphone,uitabbarcontroller,Iphone,Uitabbarcontroller,我在查找文档以外的任何其他信息时遇到问题,无法了解如何为我的UITabBarController保存选项卡顺序,以便为下一次应用程序启动保存用户自定义。我已经在网上搜索过了,但是找不到任何通过正确代码来实现这一点的博客帖子或文章 我意识到我必须使用UITabBarController(DIDENDCustomingViewControllers:)的委托方法,但我不确定在保存用户希望选项卡的顺序的状态方面如何最好地实现持久性 有人可以发布一些代码,给我指出正确的方向,或者你有一个保存的链接吗?:

我在查找文档以外的任何其他信息时遇到问题,无法了解如何为我的UITabBarController保存选项卡顺序,以便为下一次应用程序启动保存用户自定义。我已经在网上搜索过了,但是找不到任何通过正确代码来实现这一点的博客帖子或文章

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

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


谢谢

既然您要求提供一些示例代码,我将在这里简单地发布我是如何在我的应用程序中处理相同任务的

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

#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];
}
这很棘手,可能看起来很奇怪,但不要忘记我的
UITabBarController
完全是在nib文件中创建的。如果您以编程方式构造它,您可以简单地执行相同的操作,但遵循保存的顺序

注意:当你的应用程序终止时,别忘了同步
NSUserDefaults

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

我希望这会有所帮助。如果有什么不清楚的地方,请发表评论并提问。

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

- (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中。您可以在Interface Builder中将UITabBarController的委托设置为AppDelegate实例。sharedSettingsService为我保存数据。基本上,它可以是一个前端或任何你喜欢的东西(例如CoreData)。所以一切都很简单,Interface Builder在这里提供帮助,而不是使事情变得更复杂。

我将解释如何通过编程实现这一点。注意:这是使用ARC,因此您可能需要根据需要插入retain/release调用

使用
uitabaritem
标记
属性进行排序。对于要添加到
uitabarcontroller
的每个
UIViewController
,确保每个都有一个唯一的
标记

- (id)init
{
    self = [super init];
    if (self) {
        self.tabBarItem.tag = 0;
        self.tabBarItem.image = <image>;
        self.tabBarItem.title = <title>;
    }
    return self;
}
将它们全部实例化并添加到数组后,您将通过查询
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];
}

也许是比赛迟到了,但我在学校学了不到两个月的斯威夫特,大概坐了15个多小时,因为我在interwebz上找不到一个像样的解释

以下是Swift中的解决方案
  • 从1开始,为所有tabItem设置一个标记。您可以在每个单独的视图中执行此操作。如果您有六个视图,在这种情况下,它们的选项卡项将有一个唯一的编号,每个编号介于1和6之间

  • 将UITabBarControllerDelegate添加到所有ViewController类中,以便可以使用后面第5点中介绍的函数

    class FirstViewController: UIViewController, UITabBarControllerDelegate {
    
  • 在全局范围内添加以下变量(例如,在上面的代码后面),以便您可以通过类中的任何函数在手机上本地保存变量

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

  • 实现以下代码。此选项将在用户编辑选项卡视图时激活。代码的作用是按照[ViewController]的标签的顺序(用户更改后)获取标签,并将其保存在手机本地。第一个viewController的标记保存为变量“0”中的整数,第二个标记保存为变量“1”,依此类推

    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))")
            }
        }
    }
    
    func tabBarController(tabBarController:UITabBarController,didendcustomizationviewcontrollers:[UIViewController],已更改:Bool){
    如果(更改){
    打印(“新选项卡顺序:”)
    对于(变量i=0;i布尔){
    //允许您在手机上读取和写入本地变量
    让defaults=NSUserDefaults.standardUserDefaults()
    //获取对Tabbar控制器的访问权限
    让选项卡栏:UITabBarController=self.window?.rootViewController为!UITabBarController
    var junkViewControllers=[UIViewController]()
    //如果未设置,则返回0,因此tabItem的标记从1开始。
    变量标记号:Int=defaults.integerworkey(“0”)
    如果(标记号!=0){
    
    对于(var i=0;i简化的Rickard Elimä回答,更进一步。使用Tabbar Controller CustomizationViewController的委托功能保存和加载自定义ViewController的“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)
            }
        }
    }
    
    class TabBarController:UITabBarController,UITabBarController Delegate{
    让kOrder=“customOrder”
    重写func viewDidLoad(){
    super.viewDidLoad()
    self.delegate=self
    loadCustomizedViews()
    }
    func loadCustomizedViews(){
    让默认值=NSUserDefaults.standardUserDefaul
    
    tabBarController!.delegate = self
    
    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))")
            }
        }
    }
    
    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
    }
    }
    
    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)
            }
        }
    }
    
    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")
        }
    }
    
    }
    
    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)
      }
     }
    }
    
    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")
        }
      }
    
    }