Всем привет.
Очень захотелось разобраться в работе IOS приложения с Mysql-базой, и php скриптами соответственно.
Причем безо всяких фреймворков (которые в разы уменьшают время разработки, но потом после обновления языка начинаешь рвать везде волосы, т.к. фреймворк при сбоях так просто не починишь).
В итоге (не без помощи многоуважаемого haymob) у меня родился этот пост.
Суть его такова. Я попытался сделать приложение, нативно работающее с любым сервером (вообще правильно сказать - с php скриптом, а там уже любую базу можно использовать).
Совсем уж новичкам это позволит на живом примере увидеть, как выглядит код приложения, работающего с сервером (но предупреждаю, там полно костылей).
А продвинутым - придется читать всё это в попытке разобраться , а вдруг и даже помочь нам
Пока функционал будет ограничен регистрацией - авторизацией юзеров на сервере. Попробовал много примеров, и остановился на уроке Сергея Каргополова - вот ссылки на все три видео по этой теме, там же можно скачать PHP скрипты для работы серверной части
https://www.youtube.com/watch?v=a5pzlbBnfYg&t=6s - 1
https://www.youtube.com/watch?v=PKOswUE731c - 2
https://www.youtube.com/watch?v=xwyhCovrScQ&t=604s - 3
(Кстати, а может есть другой более надежный пример работы с POST (получение - сохранение данных), кидайте ссылки, буду изучать, пробовать, но без фреймворков и CocoaPods плз, туда мы еще успеем)
На базе этих примеров я сделал приложение (Перезалито после правки Ookey, за что ему большое спасибо качайте отсюда https://cloud.mail.ru/public/B1WN/RJLDQTM7j ), там реализована регистрация юзеров на моем личном сервере (регистрируйтесь там сколько хотите, но иногда я буду подчищать базу), если юзер есть или какая ошибка - выдается соотв. алёрт.
Если происходит какая-либо сетевая ошибка - она тоже отлавливается (в том числе отлавливается JSON, который возвращает нам php скрипт, то есть любые данные туда можно вернуть), и процесс регистрации повторяется до успешного завершения. Я там накидал кучу уведомлений и в консоль и во вью тоже, чтобы понимать, как всё это проходит по времени. (Алёрты пока отключил, чтобы лучше удобнее смотреть логи прямо на телефоне, если инет рвется (в метро, например))
Код оптимизирован под свифт 3, нет ни одного варнинга, терпеть их не могу.
Правда, часть авторизации юзеров я пока не трогал, работает только регистрация, начал с более сложного.
Констрейны также не делал, т.к. они в данном случае неважны, позже сделаю, также сделаю во вкладках список юзеров в tableview с удалением и редактированием личных данных - это всё не проблема.
Итак, в приложении работает, но криво:
-
Иногда при регистрации юзера возникает “The network connection was lost” (за кучей логов его не видно, но поверьте, он вылезает в самый ответственный момент), и регистрации не происходит. Я в своем приложении это отлавливаю, и эмулирую еще одно “Нажатие на кнопку Register”, и в следующий раз всё проходит хорошо, но во-первых, мне пришлось использовать глобальную переменную запоротых попыток, а во вторых, эмулировать нажатие на кнопку - это уж совсем моветон, но я просто не знаю, как запустить неудачную сессию еще раз). Также хотелось бы поместить сетевую часть в отдельный файл, лучше в класс (класс уже реализован, по крайней мере регистрация теперь размещена в классе RestApi) (а то сессии в основном файле - это, говорят, совсем жесть). Чтобы при необходимости регистрации юзера просто вызвать метод типа - userRegister(данные), а функция сама считала неудачные попытки и в результате заканчивалась бы успешной регистрацией). То же самое - с получением данных (но там попроще, т.к. ничего отправлять не надо). Также глобальная переменная мне аукнется, когда будет не одна сессия, а вдруг сразу две или три - всё перемешается, кол-во неудачных попыток должно быть персональным для каждого действия в приложении (регистрация, авторизация, получение данных (это в будущем)).
-
При попытке разобраться с сессиями я вывел лог и в консоль и на вьюконтроллер, и получил интересный результат при нажатии кнопки Зарегистрировать - в консоли сразу же весь лог выводится, а на вью он выводится сначала моментально, до лога “приготовили request”, а далее - с задержкой (иногда до полминуты), что как-то странно. (Кстати я там кажется накосячил со временем при выводе лога - вроде оно не меняется в процессе сессии) В варианте исходников от Ookey эта ошибка пропала, очень интересно
-
Нет проверки на отсутствие интернета. (уж делать приложение так нормально сразу)
У меня в принципе есть код, который также отлажен под свифт 3 и отлично работает (но вдруг он в принципе ужасен, тогда я готов изучить другой)
func isInternetAvailable() -> Bool // Перенести в другой файл или хотя бы сделать методом класса
{
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
А проверка на наличие инета выглядит так:
if isInternetAvailable() {
print("Интер есть")
} else {
print("Интер нет")
}
Но хотелось бы его также закинуть в класс и обращаться из любого места проекта
(Я сам не знаю, зачем в класс (как в фильме “Чародеи” - “Ну зачем зачем…Я и сам не знаю зачем. Положено”), но ведь это сейчас модно, но я мягко выражаясь, плаваю во всех этих наследованиях, инкапсуляциях, утечках памяти и т.п.)
В результате всех этих попыток по идее может получиться приложение, которое уже работает в 3 свифте, регистрирует и авторизует юзеров, делая запросы к базе на удаленном сервере. В случае неудачной попытки получения или сохранения данных сессия будет автоматически перезапускаться до получения ОК статуса (или до превышения кол-ва попыток). А далее это приложение можно будет развивать в любую сторону (я планирую докинуть туда авторизацию по пальцу, хранение фотки в профиле, персональные заметки и прочие удобства)
Всем спасибо, даже за прочтение!
P.S. Предвижу Ваши замечания по поводу - зачем изобретать велосипед? Ведь есть куча сервисов баз данных вместе с API (например, appbase.io ), но я Вас уверяю, наверняка найдется заказчик, который скажет - никаких публичных сервисов в моем приложении (у меня такой уже есть). Также прошу не отправлять изучать курсы с этого сайта, я их все просмотрел и законспектировал в тетрадочку. Нет там полного ответа на мой вопрос.
P.P.S. Я не проверял, но думаю, можно не заворачивать алёрты в DispatchQueue.main.async (хотя это скорей костыль, т.к. еще один дурной тон - работать с алёртами (да и вообще с любыми вью - элементы) внутри сессии)