Разбор примера работы с Mysql через POST и JSON


#1

Всем привет.

Очень захотелось разобраться в работе IOS приложения с Mysql-базой, и php скриптами соответственно.
Причем безо всяких фреймворков (которые в разы уменьшают время разработки, но потом после обновления языка начинаешь рвать везде волосы, т.к. фреймворк при сбоях так просто не починишь).

В итоге (не без помощи многоуважаемого haymob) у меня родился этот пост.

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

Совсем уж новичкам это позволит на живом примере увидеть, как выглядит код приложения, работающего с сервером (но предупреждаю, там полно костылей).
А продвинутым - придется читать всё это в попытке разобраться :slight_smile:, а вдруг и даже помочь нам :clap:

Пока функционал будет ограничен регистрацией - авторизацией юзеров на сервере. Попробовал много примеров, и остановился на уроке Сергея Каргополова - вот ссылки на все три видео по этой теме, там же можно скачать 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 с удалением и редактированием личных данных - это всё не проблема.

Итак, в приложении работает, но криво:

  1. Иногда при регистрации юзера возникает “The network connection was lost” (за кучей логов его не видно, но поверьте, он вылезает в самый ответственный момент), и регистрации не происходит. Я в своем приложении это отлавливаю, и эмулирую еще одно “Нажатие на кнопку Register”, и в следующий раз всё проходит хорошо, но во-первых, мне пришлось использовать глобальную переменную запоротых попыток, а во вторых, эмулировать нажатие на кнопку - это уж совсем моветон, но я просто не знаю, как запустить неудачную сессию еще раз). Также хотелось бы поместить сетевую часть в отдельный файл, лучше в класс (класс уже реализован, по крайней мере регистрация теперь размещена в классе RestApi) (а то сессии в основном файле - это, говорят, совсем жесть). Чтобы при необходимости регистрации юзера просто вызвать метод типа - userRegister(данные), а функция сама считала неудачные попытки и в результате заканчивалась бы успешной регистрацией). То же самое - с получением данных (но там попроще, т.к. ничего отправлять не надо). Также глобальная переменная мне аукнется, когда будет не одна сессия, а вдруг сразу две или три - всё перемешается, кол-во неудачных попыток должно быть персональным для каждого действия в приложении (регистрация, авторизация, получение данных (это в будущем)).

  2. При попытке разобраться с сессиями я вывел лог и в консоль и на вьюконтроллер, и получил интересный результат при нажатии кнопки Зарегистрировать - в консоли сразу же весь лог выводится, а на вью он выводится сначала моментально, до лога “приготовили request”, а далее - с задержкой (иногда до полминуты), что как-то странно. (Кстати я там кажется накосячил со временем при выводе лога - вроде оно не меняется в процессе сессии) В варианте исходников от Ookey эта ошибка пропала, очень интересно

  3. Нет проверки на отсутствие интернета. (уж делать приложение так нормально сразу)
    У меня в принципе есть код, который также отлажен под свифт 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 (хотя это скорей костыль, т.к. еще один дурной тон - работать с алёртами (да и вообще с любыми вью - элементы) внутри сессии)


Swift + PHP + mysql
#2

Не вижу вопроса :slight_smile: (двадцатьсимволовдвадцатьсимволовдвадцатьсимволов)


#3

А вот они:
Если в двух словах - это “The network connection was lost” и тормозной лог при выводе прямо в textview.
Но обычно в этом случае пишут - что так кратко? Опиши проблему? Что я и сделал.


#4

Это у вас с сервером беда какая-то или интернет пропадает.

В текстфилд вы выводите не из главного потока, потому и “тормозной”.

P.S. Подправте код - очень грязно написано, ухудшает читаемость. Сами же, когда через месяц полезете туда, будете проклинать все на свете.


#6

Не из главного потока, поэтом тормозной. Принимается, бум знать.
То есть я на телефоне никак не смогу увидеть что сейчас происходит внутри сессии?

А что касается кода - подправлю с удовольствием - а что именно? Если сам код, то он такой же кривой, как и я )
А вот форматирование могу поправить, но вряд ли оно так прям критично.
Я вроде уже на автомате постоянно жму CMD A , CTRL I


#7

Это что вы имеете ввиду?

Оно прям очень критично. У меня пока что есть время я поправлю побыстрому.


#8

Я имею в виду - когда я тестирую регистрацию юзера на сервере прямо на телефоне, то я никак не смогу оперативно получать лог на textview? Оперативно - это так же, как в консоль.


#9

На скорую руку подправил, должно все работать.


#10

Спасибо Вам огромное!

Перезалил сверху исходник, упомянул про Ваши правки :clap:
Не понял одну вещь - теперь вывод лога и в консоль, и на экран телефона происходит моментально (максимум 1 секунда проходит, ну это нормально), причем это и в эмуляторе, и на реальном телефоне.

Теперь можно смело отлаживать процессы происходящие при регистрации.

То есть второй вопрос решен. Но как? Поделитесь, плз.

Ведь сами говорили "В текстфилд вы выводите не из главного потока, потому и вывод “тормозной”."
А сейчас мы также выводим не из главного потока. Однако теперь все логи отображаются моментом.


#11

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

 DispatchQueue.main.async { 
      // сюда
 }

С помощью DispatchQueue.main.async, мы асинхронно вызываем метод в главном потоке.


#12

Всё понял, спасибо еще раз! Теперь хотя бы можно тестировать на девайсе.