#ios #swift #uiviewcontroller #lifecycle
#iOS #swift #uiviewcontroller #жизненный цикл
Вопрос:
Сетевой вызов :-
static func getProfile(parameters:[String:AnyObject], onComplete:[String:AnyObject]->()) {
var requiredData:[String:AnyObject] = [:]
Alamofire.request(.GET,API.getProfile,parameters: parameters).validate().responseJSON { (response) in
if let responseData = response.result.value {
if let jsonData = responseData as? [String:AnyObject] {
requiredData["UserName"] = jsonData["UName"]
requiredData["UserEmail"] = jsonData["UEmail"]
requiredData["UserMobileNo"] = jsonData["UPhone"]
requiredData["UserAddress"] = jsonData["UAddress"]
requiredData["UserCity"] = jsonData["UCity"]
}// Inner If
} // Main if
onComplete(requiredData)
}// Alamofire Closed
}// Func closed
Сетевой вызов в требуемом VC :-
override func viewDidLoad() {
super.viewDidLoad()
let parameters:[String:AnyObject] = [
"WebKey": API.WebKey.value.rawValue,
"UId":NSUserDefaults.standardUserDefaults().integerForKey("UserId")
]
NetworkInterface.getProfile(parameters) { (responseDictionary) in
//print("Passed Data (responseDictionary["UserName"])")
self.userData = responseDictionary
self.updateUI()
}
}
Насколько я знаю, жизненный цикл VC выглядит примерно следующим образом :-
инициализация (кодировщик aDecoder: NSCoder) -> viewDidLoad -> viewWillAppear -> viewWillDisappear
Однако даже после появления view требуется несколько секунд, чтобы информация о пользователе отображалась в этих текстовых полях. Я подумал, что viewDidLoad — лучшее место для совершения сетевых вызовов.
Я понимаю, что сетевые вызовы являются асинхронными, поэтому потребуется время для извлечения необходимых данных из сети и ответа. Однако сетевой вызов был выполнен в viewDidLoad, поэтому к моменту появления view в нем уже должны быть требуемые данные? Не так ли?
Итак, кто-нибудь может объяснить мне, какое место является лучшим для совершения сетевых вызовов и почему? Я хочу, чтобы текстовые поля обновлялись информацией о пользователе, как только появится view.
Ответ №1:
Запросы необходимо запускать в viewWillAppear:
, только этот метод уведомляет вас о том, что экран вот-вот будет показан. Если вы не хотите отправлять запросы каждый раз при отображении экрана, рассмотрите возможность кэширования данных, как только они у вас появятся.
viewDidLoad
не лучший кандидат. Это не имеет никакого отношения к внешнему виду экрана. Он вызывается сразу после первого запроса представления контроллера просмотра, а не при отображении экрана.
Например, если экран был удален (при появлении на навигационном контроллере), вы получите сообщение viewDidLoad
при повторном показе (при наведении экрана на навигационный контроллер). Или, если приложение получает предупреждение о памяти, текущее представление выгружается и загружается снова, что в конечном итоге отправляет view controller viewDidLoad
.
viewDidLoad
это сложно.
Если вы думаете, что это viewDidLoad
избавит вас от многократной выборки данных с сервера: иногда это произойдет, иногда нет. В любом случае, это не тот инструмент для оптимизации работы сети, которым является кэширование!
Поскольку удаленные запросы являются дорогостоящими (они требуют времени и трафика), вы хотите понимать, когда они отправляются. viewWillAppear:
дает вам понимание. А в сочетании с кэшированием вы можете сделать его оптимальным.
Обновить
В большинстве случаев отправлять запросы напрямую с контроллера просмотра не очень хорошая идея. Я бы предложил создать отдельный сетевой уровень.
Комментарии:
1. Было бы интересно узнать, почему у меня есть -1.
2. Большой палец вверх, так как это действительно отличный ответ. Спасибо
3. Можете ли вы объяснить, почему «иногда это будет, иногда нет»? viewDidLoad вызывается один раз за весь жизненный цикл UIViewController. Не вижу никаких причин для его вызова более одного раза.
4. @TarasNikulin это очень хороший вопрос! Эта фраза действительно сбивает с толку. К сожалению, я не могу вспомнить, что именно я имел в виду четыре года назад 🙂 Сегодня я бы сказал, что можно создавать сети любым из этих методов в зависимости от конкретного случая. Кроме того, я все еще думаю, что кэширование может быть полезным. Я надеюсь, что это поможет.
Ответ №2:
Я думаю, что viewDidLoad — это правильное место для выполнения сетевого вызова, если это соответствует потребностям этого экрана. т. Е. вам не нужно повторно запрашивать данные в какой-то момент. Например, если данные профиля изменились с момента загрузки представления.
Что касается сетевых запросов, требующих времени, возможно, что ваше представление появится до выполнения сетевого запроса. Я предлагаю добавить некоторый индикатор загрузки, который вы скрываете после завершения запроса.
Кроме того, имейте в виду, что сетевые запросы могут завершаться сбоем, поэтому вам следует решить эту проблему, повторив запрос или отобразив сообщение об ошибке.