Comments 4
Очередная помоечная статья, которая скорее имеет отрицательный эффект, чем хоть сколько-нибудь полезный.
Сначала я честно пытался понять, что же тут происходит на высоком уровне. Всё, что я понял – это есть какой-то URL, при обращении к которому открывается дверь.
Для меня это звучит просто, как:
// показать крутилку
let url = URL(string: "...")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// показать ошибку
// или
// fatalError() чтобы приложение "упало"
}
task.resume()
Это необходимо, чтобы мы со стороны Flutter могли поставить условие, что если приложение открыто с HW, то идет запрос на открытие двери. Если приложение просто открыто по тапу на него, ничего не должно происходить.
Честно говоря, тут я не понял. Если у приложения единственная задача – открывать дверь, то почему бы ему не открывать её всегда? И неважно, откуда открыто приложение – из виджета ли, или напрямую. Причём, во втором случае, даже виджет будет не нужен. Нажимаешь на иконку, открывается приложение, делает запрос, при успехе умирает.
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let channelName = "widgetChannel"
let methodChannel = FlutterMethodChannel(name: channelName,
binaryMessenger: controller.binaryMessenger)
Создаем контроллер...
Нет, тут мы ничего не создаём.
Вместо того, чтобы надеяться, что в этот момент окно будет существовать, что rootViewController
будет установлен, и что он будет определённого класса – почему бы не положить methodChannel
прямо в FlutterViewController
, и не создавать эти объекты у него в конструкторе?
if (result == true) {...}
– c true
обычно не сравнивают, но ладно.
isTappedOnWidget
– просто неграмотно.
Но дальше начинается просто шоу.
extension AppDelegate {
private func openedFromWidget(url: URL, isTapped: Bool) {
var tapped = isTappedOnWidget
if url.scheme == "widget", url.host == "widgetFamily", tapped == true {
let widgetFamily = url.lastPathComponent
tapped = isTapped
}
}
}
Что здесь произошло? Я вообще не понял. Есть локальная переменная tapped
, в неё производится только запись. Никто её не читает, никому она не интересна. В Xcode даже ворнинг такой есть.
Таким образом мы будем знать, что приложение раскрыто именно с HW, и даже узнаем с какого именно.
Не удержался, чтобы не спросить: какая двери разница, из какого виджета её открыли?
recieveResult()
– Опечатка, которая уже не кажется опечаткой.
override func application(...) -> Bool {
isTappedOnWidget = true
if isTappedOnWidget == true {
openedFromWidget(url: url, isTapped: isTappedOnWidget)
}
}
Что происходит? В isTappedOnWidget
сразу записывается true
. На следующей же строке мы проверяем: "а там true?". Возможно, космические лучи помешали его туда записать. Ну и если true
всё же записалось, вызываем openedFromWidget()
. Но кто знает, может это дверь на МКС, ведущая в открытый космос...
И снова, если включить все ворнинги, то Xcode должен был бы сказать, что condition is always true
.
Ну и самый сок.
private func closeApp () {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.isTappedOnWidget = false
UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
}
}
зачем что-то обнулять?
почему через две секунды? что если я за две секунды успею ещё пару раз нажать на виджет или что-нибудь другое?
но это всё ладно. Подходим к самой гениальной строке, честно говоря, я даже восхитился: создаём "временный" "мусорный" UIControl, который через мгновение умрёт, и отправляем им экшен
URLSessionTask.suspend
вUIApplication
. Это просто гениально. Я думал, что я знаю все способы так или иначе сделатьperformSelector
, но, как говорится, Today I Learned.
Пожалуйста, не позорьтесь, и забудьте о написании статей для широкой публики лет на 5-10. Не надо писать, лишь бы написать.
Flutter, создание Home Widget на платформе iOS