Как убедиться, что все ключи в словаре инициализированы

#ios #swift

Вопрос:

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

Проблема в том, что вызов завершен, и завершение выполняется до того, как все ключи будут инициализированы в моем словаре. Каким был бы метод, чтобы дождаться, пока все они будут инициализированы, чтобы он не возвращал ноль ?

Вот мой метод инициализации :

     func setLocales(locales: Layout, success: ([String: String]) -> Void) {
        self.layout["infoAllDebates"] = locales.infoAllDebates ?? "Débats"
        self.layout["actionReadMore"] = locales.actionReadMore ?? "Lire plus"
        self.layout["actionSeeMore"] = locales.actionSeeMore ?? "Voir plus"
        self.layout["actionAddArgument"] = locales.actionAddArgument ?? "Ajouter un argument"
        self.layout["actionLinkToDebate"] = locales.actionLinkToDebate ?? "Aller au débat"
        self.layout["actionUpdate"] = locales.actionUpdate ?? "Modifier"
        .... (150 more lines of strings)
        success(self.layout)
    }
 

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

Вызов API выглядит следующим образом :

 func getSettings(completion: (() -> Void)?) -> () {
        apiClient.getSettings { settings in
            self.setLocales(locales: settings.data.resource.layout, success: { layout in
                DispatchQueue.main.async {
                    if completion != nil {
                        return completion!()
                    }
                }
            })
        }
    }
    
 

Что я должен сделать, чтобы убедиться, что все ключи инициализированы ?

Комментарии:

1. Используйте кодируемую структуру, а не словарь. Словарь содержит неограниченное количество ключей, поэтому вы не можете гарантировать, что все они инициализированы. Структура имеет определенное количество ключей, поэтому вы можете.

2. Хорошо, это, кажется, хороший совет. Но смогу ли я в любом случае проверить ?

3. С помощью структуры компилятор проверит вас. Вы не сможете вернуться оттуда init , не установив все.

4. Вы уверены, что правильно используете функцию завершения? Это звучит как асинхронная проблема.

5. @вадиан, я не уверен

Ответ №1:

Прежде всего удалите обработчик завершения setLocales , потому что все происходит синхронно

 func setLocales(locales: Layout) {
    self.layout["infoAllDebates"] = locales.infoAllDebates ?? "Débats"
    self.layout["actionReadMore"] = locales.actionReadMore ?? "Lire plus"
    self.layout["actionSeeMore"] = locales.actionSeeMore ?? "Voir plus"
    self.layout["actionAddArgument"] = locales.actionAddArgument ?? "Ajouter un argument"
    self.layout["actionLinkToDebate"] = locales.actionLinkToDebate ?? "Aller au débat"
    self.layout["actionUpdate"] = locales.actionUpdate ?? "Modifier"
    .... (150 more lines of strings)
}
 

Во-вторых, не возвращайте (первый) обработчик завершения, вызовите его

 func getSettings(completion: (() -> Void)?) {
    apiClient.getSettings { settings in
        self.setLocales(locales: settings.data.resource.layout)
        DispatchQueue.main.async {
           completion?() // The completion != nil check is "unswifty"
        }
    }
}
 

Примечание: Избегайте префиксов get и set , если вы взаимодействуете с Objective-C. Это может привести к неожиданному поведению.

Комментарии:

1. Спасибо за ваше решение и ваши четкие объяснения. В любом случае, я все еще получаю нулевое значение, когда я вызываю определенный ключ.

2. Тогда проблема заключается в контексте, в котором вы используете getSettings