Шаблон проектирования для управления состоянием пользовательского интерфейса в iOS

Подобно этому question, но я ищу универсальное решение или шаблон дизайна или рамки.

Q. Как добавить управление состояниями во все элементы пользовательского интерфейса в моем приложении iOS автоматически без необходимости переписывать класс существующих элементов управления?

Пример:

например. Когда я нажму на UIButton, он создаст новую UIWebView, показывающую домашнюю страницу Google. Это легко, но проблема возникает, когда пользователь иногда.. нажмите кнопку просто слишком быстро, поэтому отобразятся два веб-представления.

Чтобы решить этот вопрос, мне нужно будет создать одноэлементный класс, содержащий webview, и иметь переменную состояния isOpended, и если она истинна, повторите использование существующего webview вместо создания нового.

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

Спасибо.

Ответ 1

Думаю, вы решаете не ту проблему. Почему бы вам не отключить кнопку до тех пор, пока UIWebView не будет обработан. Таким образом, пользователь не может дважды щелкнуть по нему.

- (IBAction)showMapHomepage:(UIButton*)sender
{
    sender.enabled = NO;
    [self taskThatTakesALongTimeWithCompletion:^{
        sender.enabled = YES;
        // Finish processing
    }];
}

Ответ 2

Вы неправильно истолковываете лучший способ решения своей проблемы. Прежде всего, вы никогда не должны находить себя в ситуации, когда вы создаете много многоголосов. Синглтоны - необходимое зло, но вы не должны злоупотреблять ими и злоупотреблять ими. Вот хороший пост о синглонах в objective-c.

Существует множество способов предотвратить отображение второго UIWebView, когда пользователь нажимает кнопку.

Как сказал кто-то другой, одним из решений было бы отключить кнопку, чтобы пользователь не мог "дважды щелкнуть" ее. Вы делаете это, используя:

button.enabled = NO;

Вы также можете скрыть свою кнопку, используя:

button.hidden = YES;

Или, в заголовке класса, который содержит ваш UIButton, вы можете создать логическое значение, которое будет обрабатывать логику того, была ли нажата кнопка;

// declare this in your header
BOOL buttonPressed;

// this is the IBAction that your button hooks up to
- (IBAction)createWebViewButtonPressed:(id)sender {
    if(!buttonPressed) {
        buttonPressed = YES;
        // insert code here to create your UIWebView
    }
}

Опять же, есть множество способов сделать то, что вы пытаетесь сделать. Вам просто нужно определить, какой из методов лучше для вас.

Ответ 3

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

- (IBAction)buttonAction:(UIButton*)sender
{
    NSString* webViewKey = @"AssociatedWebView";
    // See if there is web view already
    id webView = objc_getAssociatedObject(sender, webViewKey);
    if(webView == nil)
    {
        // There is no existing web view, create it
        webView = [self theWebView];
        // Associate it with the button
        objc_setAssociatedObject(sender, webViewKey, webView, OBJC_ASSOCIATION_RETAIN);
        // Add the web view
        [self.view addSubview:webView];
    }
}

Вышеприведенный общий способ связать объект с экземпляром UIButton, чтобы вы могли проверить, уже ли он связан и повторно использовать существующий. Я предоставляю этот ответ, если вы намереваетесь использовать его каким-либо другим способом, который не полностью описан в вашем вопросе, но на практике вы можете использовать свойство своего контроллера для webView, которое lazy загружает webView если он еще не загружен.

Если вы действительно хотите симулировать стиль singleton, который вы обсуждаете в своем вопросе (чтобы у вас могло быть много экземпляров UIButton, все они имеют один и тот же объект webView, если он уже существует) то вы можете связать webView с объектом [UIButton class] или даже с объектом [UIControl class] вместо вашего конкретного экземпляра. Вы сделали бы это, заменив sender на [UIControl class] в приведенном выше коде.

Ответ 4

Одним из возможных решений является сохранение указателя на веб-представление в свойстве viewController. В getter для веб-просмотра создайте веб-просмотр, если он еще не существует. Действие кнопки просто нужно отобразить webview, так как оно просто перерисовывает веб-просмотр, если оно уже существует, и оно создаст веб-просмотр, если это не так. Когда вы закончите с веб-просмотром, просто установите его на нуль.