Вопрос по objective-c, ios – Запретить доступ к UIViewControllers с контроллером панели вкладок (раскадровка)

1

В настоящее время у меня возникла проблема с моим приложением для iOS.
Я пытаюсь включить шаблон постепенного входа в систему, т. Е. Использование может получить доступ к некоторым приложениям без необходимости входа в систему.

Требуемые функции следующие:

At all times the user can view all navigation items that require login When the user attempts to access an uiview(controller) that requires login, they will be prompted with a UIAlertView asking them to log in. (Preferably the UIAlertView will appear when the app recognised the initiated segue destination is restricted).

Сначала я использовал подкласс UIViewController, который в назначенном инициализаторе (initWithCoder) проверял NSUserDefaults, чтобы увидеть, вошел ли пользователь в систему. Затем я выделил его подклассы. Ограничения были следующие:

Couldn't use other subclasses of UIViewController, namely UITableViewController The UIAlertView came up after the view had appeared, which i am assuming would cause errors if the subclassed UIViewController assumed the user was logged in.

Question summary:
Я хотел бы знать, как условно запретить пользователям доступ к определенным UIView (Controller) и подклассам UIViewController, и когда это происходит, представить UIAlertView.

Update 1
Могут ли категории и / или протоколы быть жизнеспособным решением?

Update 2
CodaFi отметил, что синглтоны являются отличным решением для управления состоянием пользователя.

После этого мне нужно выяснить, как контролировать доступ пользователя.
Поскольку я использую раскадровки, я чувствую, что наиболее универсальной реализацией будет создание подкласса UIStoryboardSegue, и при проверке метода execute, если пользователь пытается получить доступ к ограниченному UIViewController (возможно, ограниченные контроллеры имеют свойство протокола, которое задает необходимый статус: залогинен / из). Однако ловушка здесь заключается в том, что вы не можете выбрать класс / подкласс UIStoryboardSegue в графическом редакторе раскадровки. Мне известно, что я мог бы сделать это программно, однако это кажется утомительным, поскольку мне пришлось бы добавлять IBActions и тому подобное к методам, выполняющим сегменты, кроме того, я не думаю, что это будет работать с тем, как ведут себя такие элементы, как navigationController и tabbarControllers.

Does anybody have a viable solution to restricting the user's navigation?

Update 3
Я добавил ответ на этот вопрос, однако я все еще считаю его без ответа, поскольку написанный мною ответ не учитывает переходы между контроллерами панели навигации. Однако это может помочь некоторым людям.

Я раньше не слышал термин «синглтон», после некоторого WikiResearch, я полагаю, вы имеете в виду какой-то объект сохранения состояния? Кроме того, я использую раскадровку, может ли расширение UIStoryboardSegue быть решением? MrJD
Синглтоны очень популярны в программировании на iOS anders
Ого, оглядываясь назад, на то время, когда я не знал, что такое синглтон. Синглтоны могут быть популярны. Но они плохая практика / анти-паттерн MrJD
Что @CodaFi сказал, плюс использование делегатов UITabViewController и UINavigationController. Till
Может ли синглтон работать? Этакий класс-привратник, который будет управлять вашими настройками по умолчанию в приложении. CodaFi

Ваш Ответ

2   ответа
2

Теперь я понимаю, что моей настоящей проблемой было психическое отключение с помощью протокола tabbarcontrollerdelegate.

В качестве решения для предотвращения доступа к вкладкам я создал класс для обработки указанного контроллера панели вкладок.

#import <Foundation/Foundation.h>

@interface TabBarDelegate : NSObject<UITabBarControllerDelegate,UIAlertViewDelegate>{
    UITabBarController *cachedTabBarController;
}

@end

#import "TabBarDelegate.h"

@implementation TabBarDelegate

-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
    NSLog(@"%s",__FUNCTION__);
    NSLog(@"Pretending the user isnt logged in");

    if(true){
        NSString *message = [NSString stringWithFormat:@"You require an account to access %@",viewController.tabBarItem.title];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Account Required" message:message delegate:self cancelButtonTitle:@"Okay" otherButtonTitles: @"Login",@"Create Account",nil];
        [alert show];
        //Hold tabbarcontroller property for alert callback
        cachedTabBarController = tabBarController;
        return false;
    }

    return true;
}

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
    if(cachedTabBarController){
        switch (buttonIndex) {
            case 1:
                //Login
                [cachedTabBarController performSegueWithIdentifier:@"tabBarToLogin" sender:cachedTabBarController];
                break;
            case 2:
                //Sign up
                [cachedTabBarController performSegueWithIdentifier:@"tabBarToSignup" sender:cachedTabBarController];
                break;
            default:
                break;
        }
        //Release tab bar controller from memory
        cachedTabBarController = nil;
    }
}

@end

Затем я подключил его к моему appDelegate в applicationDidFinishLaunching ...

//Hook up tab bar delegate
    mainTabController = (UITabBarController*)self.window.rootViewController;
    mainTabBarDelegate = [[TabBarDelegate alloc] init];
    mainTabController.delegate = mainTabBarDelegate;

И вуаля

0

Это работает только в ситуациях, когда вы можете выбрать собственный переход (и я только написал код для push, но не для модального режима).

Протокол "UIViewControllerAuthentication" для всех контроллеров, которым требуется аутентификация, этот протокол содержит метод для получения необходимого статуса аутентификации.

enum authenticationStatus {
notLoggedIn = 0,
noPassword = 1,
loggedIn = 2
};

@protocol UIViewControllerAuthentication <NSObject>

-(enum authenticationStatus)authStatusRequired;

@end

Контроллеры, которые требуют аутентификации, соответствуют этому протоколу:

-(enum authenticationStatus)authStatusRequired{
return loggedIn;
}

Тогда используйте это для аутентифицированного перехода

@interface SeguePushWithAuth : UIStoryboardSegue

@end
-(void)perform{
    NSLog(@"custom segue destination : %@",self.destinationViewController);
    NSLog(@"custom segue source : %@",self.sourceViewController);
    NSLog(@"custom segue dest conforms to protocol : %i",[self.destinationViewController conformsToProtocol:@protocol(UIViewControllerAuthentication)]);

    if([self.destinationViewController conformsToProtocol:@protocol(UIViewControllerAuthentication)]){
        UIViewController <UIViewControllerAuthentication> *destination = (UIViewController <UIViewControllerAuthentication> *)self.destinationViewController;
        if (!((int)[AccountModel userAuthStatus] >= (int)[destination authStatusRequired])) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Authentication" message:@"You need an account to access this area" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Login",@"Create Account", nil];
            //alert
            [alert show];
            return;
        }
    }

    [[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:true];
}

@end

Затем используйте пользовательские сегменты в Uistoryboard

Это хороший шаблон, позволяющий контроллеру назначения отменить переход.
Однако это далеко от того, что я хочу, так как я хочу иметь возможность аутентифицировать сегменты, которые связывают контроллеры панели вкладок с их дочерними элементами.

Похожие вопросы