Как правильно разделить переменную между некоторыми контроллерами представления в Swift? - PullRequest
0 голосов
/ 03 мая 2018

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

Я создаю User класс, в котором в качестве свойств указываются электронная почта, uid, имя и другие пользовательские данные, такие как их адрес и т. Д. Этот класс инициализируется в контроллере представления первой панели вкладок в контроллере панели вкладок (индекс: 0), скажем, мы называем его HomeVC. экземпляр класса User инициализируется с использованием данных, поступающих с сервера.

экземпляр этого User класса будет использоваться несколько раз в моем приложении. скажем, когда пользователь создает сообщение в PostVC, которое находится в нижнем / последнем VC в стеке навигации третьей панели вкладок (индекс: 2). а также когда пользователь видит свой профиль в profileVC.

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

В настоящее время я создаю суперглобальную переменную (переменную, расположенную вне класса), чтобы я мог получить к ней доступ в любом месте моего приложения. но я только что прочитал, что использование суперглобальной переменной - плохая практика программирования.

так что мне делать? я должен передать пользовательские данные с помощью prepareForSegue? Есть ли лучший вариант для решения этой проблемы?

Ответы [ 5 ]

0 голосов
/ 03 мая 2018

Я бы порекомендовал также избегать одиночных игр здесь. Основная мотивация - сделать вещи проверяемыми. Вот возможный подход.

У вас есть User что-то вроде этого:

struct User {
    let userid: String
    let email: String
}

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

protocol UserManagerProtocol {
    func getSignedInUser() -> User?
    func signIn(userid: String, password: String) -> User?
}

Объявите ваш фактический класс, который реализует протокол:

class UserManager: UserManagerProtocol {
    fileprivate var signedInUser: User?
    func getSignedInUser() -> User? {
        return signedInUser
    }
    func signIn(userid: String, password: String) -> User? {
        //call your server to sign in user
        // if sign in fails, return nil
        // if sign in works, create a User object
        signedInUser = User(userid: userid, email: "email retrieved from server")
        return signedInUser
    }
}

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

class HomeVC: UIViewController {
    var userManager: UserManagerProtocol?
}
class PostVC: UIViewController {
    var userManager: UserManagerProtocol?
}

Наконец, в вашем AppDelegate, когда вы запускаете приложение, создайте один экземпляр вашего UserManager, сохраните его в AppDelegate и передайте его всем вашим контроллерам представления. В этом примере я явно упустил много вещей, потому что я не знаю, как выглядит ваш AppDelegate.

class AppDelegate: NSObject, UIApplicationDelegate {
    var userManager: UserManagerProtocol?

    func applicationDidFinishLaunching(_ application: UIApplication) {
        userManager = UserManager()

        //when setting up your tab bar controllers, pass the userManager instance to each of them
    }
}
0 голосов
/ 03 мая 2018

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

0 голосов
/ 03 мая 2018

Поскольку вы уже используете Cloud Firestore, вы можете войти в систему с помощью различных методов на панели аутентификации Firebase (FirebaseAuth). Как только пользователь вошел в систему, вы можете получить текущего пользователя из любого места в вашем приложении, например:

    import Firebase        

    if let user = Auth.auth().currentUser {
        let userID = user.uid
        let email = user.email
        let displayName = user.displayName
    }

Когда приложение имеет действительный токен пользователя, он не перезванивает на сервер, если токен не нуждается в обновлении (например, во время изменения настроек учетной записи пользователя).

https://firebase.google.com/docs/auth/ios/start

0 голосов
/ 03 мая 2018

Я думаю, вам следует избегать одиночных игр. Одним из лучших решений, которые я узнал, является создание протоколов для ваших менеджеров данных (таких как сессии, корзина для покупок ...). После этого вы должны отодвинуть свои зависимости как можно дальше от вашего класса. Который в этом случае является AppDelegate. Таким образом, вы создаете свойства для этих классов, которые будут храниться там. Если у вас их много, соберите их в класс или что-то в этом роде.

Маленький пример:

@objc protocol SessionManagerProtocol {
  func persistUser()
}

Тогда в вашем AppDelegate: (сделайте его безопасным для потоков)

var sessionManager: SessionManagerProtocol!
func getSessionManager() -> SessionManagerProtocol {
    if let manager = sessionManager {
        return manager
    }
    sessionManager = SessionManager()
    return sessionManager
}

С помощью этого решения вы также можете вводить зависимости, если хотите сделать его тестируемым.

Если ваше приложение переходит в фоновый режим, вы сохраняете сеанс в userdefaults или в своей собственной базе данных.

Если вы просто хотите пройти между контроллерами представления, проверьте эту ссылку: Передача данных между контроллерами представления

0 голосов
/ 03 мая 2018

Люди ненавидят одиночек, несмотря на

URLSession.shared

UIApplication.shared

NotificationCenter.default

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...