Глобальные переменные при программировании в iOS

В одном из комментариев на сайте, читатель поинтересовался каким образом следует работать с глобальными переменными. Он даже привел пример приложения, над которым он работает. Если я правильно понял, то это приложение опросник, которое по очереди задает вопросы, принимает ответы, суммирует результаты ответов и в конце выводит какой-то результат. Читатель сказал, что для каждого вопроса он использует отдельный контроллер, и соответсвенно хочет отловить ответы с каждого контроллера. Я не согласен с подобной реализацией такой задачи, но в любом случае изложу в данной статье несколько вариантов решения, которые я вижу. А также свой вариант реализации подобного опросника, при котором глобальная переменная с результатом и вовсе не понадобится.

Для начала я собрал проект, в котором я сделал четыре контроллера:

Три контроллера содержат кнопки Да и Нет и четвертый будет использоваться для вывода результата.

Не буду подробно расписывать какие идентификаторы я задавал в Storyboard, и что именно я писал в коде. В этом нет ничего сложного. Просто приведу код, контроллеров из проекта.

 

Решение задачи

Итак, для подсчета результатов мы будем использовать схему при которой да = 10, а нет = 5. Это произвольные значения. Мы их определили, чтобы понимать ожидаемый результат.

Еще раз взглянем на проект: при отображении контроллеров и ответе пользователя на вопрос нам нужно запоминать результат ответов.

Вариант 1. Глобальная переменная.

Глобальную переменную можно объявить в любом файле за пределами объявления класса. Например, у нас есть файл AppDelegate, в котором задекларирован делегат приложения. Но это не значит что мы не можем ничего там писать. До объявления класса объявите переменную и константу:

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

Добавьте в ResultViewController в метод viewDidLoad() строку вывода результата на экран:

И не забыть сбросить результат, для следующего круга.

Все, все работает, считает, сравнивает…




Вариант 2. Класс Singleton

На страницах нашего сайта мы не раз разбирали Singleton. В статье Синглтон на Swift, или как правильно написать Singleton и вот в этой статье: Шаблоны программирования на Swift: И снова Singleton. Давайте применим знания на практике.

Для удобства давайте добавим еще один файл в проект и назовем его Manager.swift.  Внутри этого файла необходимо создать класс QuestionsManager, в котором указать нужные нам свойства: переменную результата и сумму правильных ответов. Также сделать все необходимы манипуляции, чтобы этот классицизмах являлся Singleton.

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

Также в ResultViewController нужно добавить свойство с менеджером и изменить код вывода результата на экран. А нужно изменить код сброса результатов для начала следующего круга.

Ссылка проекта на GitHub.

Вариант 3. Все в одном контроллере

И третий вариант, который я бы хотел вам показать, это создание подобного проекта, только с использованием одного контроллера. В этом случае глобальные переменны вовсе не нужны, — все подсчеты происходят внутри одного класса контроллера. Мне придется создать новый проект, чтобы предыдущий можно было выложить целиком на GitHub.

Вот что у меня получилось:

Созданные аутлеты и экшены, а также вспомогательные методы:

Итак, суть данного подхода в том, чтобы все вопросы записать в массив, и перебирая элементы массива выводить вопросы на экран. При этом заменять контроллер мы не будем. Мы будем менять надписи и прятать или наоборот выводить на экран нужные элементы.

Я предлагаю реализовать следующим образом:

Как видите, весь функционал реализован внутри только одного контроллера. Поэтому глобальные переменные вовсе не нужны. Мы используем переменные-свойства класса. Они доступны из любой точки класса контроллера.

Что еще нужно знать

Для решения поставленной вначале урока задачи можно обойтись без глобальных переменных вовсе. В других случаях, если требуется какой-либо глобальный объект, всегда используют Singleton. Использование глобальных переменных — крайне не рекомендуется по причине глобального пространства имен и впринципе неудобности такого подхода. Классы, любезно предоставленные нам Apple используют Singleton подход.  Например:

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




2 комментария на “Глобальные переменные при программировании в iOS
  1. Илья Федоров:

    Спасибо за урок!
    Я не знаю прочитаете вы или нет этот комментарий, но хочу кое-что отметить)

    В проекте наблюдается неограниченный рост памяти — все ViewController’ы остаются в памяти и эти ячейки памяти никогда не высвобождаются, даже если инициировать Memory Warning.

    P.s. я только начал писать на Swift и это жуткая проблема для меня.

    • Илья Федоров:

      Ох, не заметил сразу ссылку на GitHub.
      Обнаружил в вашем проекте такую вещь, как Unwind Segue, по которой у вас уже есть статья. Это решает мою проблему, отлично!

      Спасибо еще раз 😉

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*