iOS сделалSelectTabBarItem, зная, какой элемент был выбран ранее

У меня есть приложение IOS с UITabBar, и его делегат настроен на мой класс. didSelectTabBarItem правильно срабатывает, и с миром все в порядке. Однако у меня есть некоторый условный код, который должен возникать, когда выбранный UITabBarItem находится после одного конкретного UITabBarItem IE.. если пользователь нажимает на элемент панели вкладок 3, и в настоящее время он находится на элементе панели вкладок 2, мне нужно сделать небольшой дополнительный код , что мне не пришлось бы делать, если бы пользователь выбрал элемент панели вкладок 3 и ранее был на элементе панели вкладок 1.

Итак, в любом случае программно (кроме прямого отслеживания через мою программу через переменную состояния, чтобы узнать, какой ранее выбранный элемент находился на панели вкладок, когда выбран новый элемент панели вкладок?


person Speckpgh    schedule 16.09.2012    source источник


Ответы (5)


Да, это возможно, через наблюдение за ключом-значением (KVO).

примечание Этот ответ касается UITabBar, а не UITabBarController. У делегатов контроллера панели вкладок есть методы, которые вы ищете (как упоминалось rdelmar).

Для начала обратите внимание на панель вкладок следующим образом:

- (void)viewDidLoad{
    [super viewDidLoad];
    [self.tabBar addObserver:self forKeyPath:@"selectedItem" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}

Я думаю, вы уже видите, куда я иду, основываясь на том, что я использую как старые, так и новые варианты. Затем просто наблюдайте за изменением вместо использования метода делегата, например:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"selectedItem"] && [object isKindOfClass:[UITabBar class]]){
        UITabBar *bar = (UITabBar *)object; // The object will be the bar we're observing.
        // The change dictionary will contain the previous tabBarItem for the "old" key.
        UITabBarItem *wasItem = [change objectForKey:NSKeyValueChangeOldKey];
        NSUInteger was = [bar.items indexOfObject:wasItem];
        // The same is true for the new tabBarItem but it will be under the "new" key.
        UITabBarItem *isItem = [change objectForKey:NSKeyValueChangeNewKey];
        NSUInteger is = [bar.items indexOfObject:isItem];
        NSLog(@"was tab %i",was);
        NSLog(@"is tab  %i",is);
    } 
    // handle other observings.
}

Не забудьте удалить себя как наблюдателя как в viewDidUnload, так и в dealloc, так как viewDidUnload может никогда не вызываться.

person NJones    schedule 16.09.2012
comment
Спасибо, это то, что я ищу! Я знаю, что у контроллера есть для этого опции, но по многим причинам я использую не контроллер, а панель вкладок! Большое спасибо. - person Speckpgh; 17.09.2012

Я не знаю, можно ли это сделать иначе, чем вы предложили (переменная состояния), если вы не используете UITabBarController. Если вы используете контроллер панели вкладок, вы можете сделать это в делегате контроллера панели вкладок:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    if (viewController == [self.tabBarController.viewControllers objectAtIndex:2 && self.tabBarController.selectedIndex == 1]) {
        NSLog(@"Do special programming");
    }
    return YES;
}

Этот метод вызывается перед переключением (в отличие от метода didSelectTabBarItem UITabBar), поэтому выбранный индекс будет индексом вкладки, которая была активной до того, как вы коснулись новой вкладки.

person rdelmar    schedule 16.09.2012
comment
Если у OP есть UITabBarController, этот метод делегата - это путь. Но я думаю, вы имели в виду if (viewController == [self.tabBarController.viewControllers objectAtIndex:2] && self.tabBarController.selectedIndex == 1). - person NJones; 16.09.2012
comment
Спасибо, я ценю все варианты контроллера, которые дают люди, но я думаю, мне следовало быть более конкретным, я не использую tabbarcontroller, просто панель вкладок. - person Speckpgh; 17.09.2012

Могут быть лучшие идеи, но один из способов сделать это — создать объект NSString в вашем AppDelegate для хранения имени класса текущего контроллера представления, чтобы вы могли прочитать строку из вашего следующего контроллера представления и проверить ранее выбранный элемент. .

В AppDelegate.h вы объявляете строку и синтезируете ее.

@property (strong, nonatomic) NSString * preSelectedViewController;

И во всех ваших UIViewControllers, которые установлены как элементы для вашего UITabViewController, сделайте это

в файлах .h

#import "AppDelegate.h"

в файлах .m включите это в свой метод viewWillAppear:

AppDelegate * delegate1 =(AppDelegate *) [[UIApplication sharedApplication] delegate];
if (delegate1.preSelectedViewController ==nil) 
{
    delegate1.preSelectedViewController=NSStringFromClass( [self class]);

}

NSLog(@"previous %@",delegate1.preSelectedViewController);

//include 2nd_viewcontroller.h file and this if statement in your 3rd_viewcontroller(i.e. where you want to check and do your other programming) 
if ([delegate1.preSelectedViewController isEqualToString:NSStringFromClass([2nd_ViewController class]) ]) {
    //do your little extra code
}

delegate1.preSelectedViewController=NSStringFromClass( [self class]);
NSLog(@"present %@",delegate1.preSelectedViewController);

Думаю, это сработает для вас

person Neo    schedule 16.09.2012

Почему бы не сохранить lastSelectedIndex в iVar, а в - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController у вас есть оба значения. Вы даже можете (никогда не пробовали) использовать - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController, чтобы у вас был текущий выбранный индекс контроллера представления, выбранный индекс, а затем с помощью дополнительного метода вы можете найти индекс выбранного индекса viewController.

person Bernd Rabe    schedule 16.09.2012

Я обнаружил, что это работает с ReactiveCocoa:

#import <ReactiveCocoa/ReactiveCocoa.h>
// ...
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
@weakify(self);
[RACObserve(appDelegate, tabBarController.tabBar.selectedItem) subscribeNext:^(UITabBarItem *selectedTab) {
    @strongify(self);
    NSUInteger selectedIndex = [appDelegate.tabBarController.tabBar.items indexOfObject:selectedTab];
    NSLog(@"selected index: %lu", (unsigned long)selectedIndex);
}];
person Stunner    schedule 18.09.2017