iOS-приложение на Go… и Катя. Финал

в 10:15, , рубрики: dcoin, Go, Катя

iOS-приложение на Go… и Катя. Финал - 1

Заключительная часть серии статей про мой опыт перехода с PHP на Go.

Первая часть, вторая, третья, четвертая.

4,5 года назад я имел неосторожность начать писать свою криптовалюту на совсем неподходящем для этого дела языке — на PHP. В итоге, конечно, написал (я упрямый), но получился костыль на костыле и то, что оно вообще работало было просто какой-то магией.

Сразу хочу предупредить, программер я самоучка-недоучка и пишу код, мягко сказать, неидеально.

Началось всё с того, что я расстался с девушкой, по имени Катя и в этот же день (4 апреля 2015-го) решил изучить Go и переписать свою криптовалюту. Писать про Катю не под спойлерами не могу, т.к. хабр всё же для IT-шных статей, а не для любовных рассказов и суровые айтишники, которым интересна тема Go, могут просто не обращать внимание на спойлеры «про Катю» и «про Машу».

Итог 8 месяцев: приложение работает на Win, OSX, Linux, FreeBSD, Android, IOS

Общего кода ~73к строк, кода под разные ОС где-то несколько сотен строчек.

40к — обработка/генерация блоков/тр-ий, 17.5к — контроллеры для интерфейса, 15.5к — шаблоны.

Поддерживаются PostgreSQL, SQLite, MySQL.

Тех, кто будет тестировать мое творение, предупреждаю — могут быть баги, и если у Вас есть время, черкните о них, пожалуйста, на darwin@dcoin.club или в личку на хабре. Пожелания и советы тоже приветствуются.

В первых четырех частях я рассказал про то, как в dcoin функционирует веб-сервер, про html/template, базы данных, плавное завершение приложения, шифрование и парсинг блоков, Android-приложение.

В этой части я расскажу про компиляцию под IOS.

Начало

Первой сложностью было то, что у меня не было сертификата разработчика. А без него скомпилировать приложение не получалось. Айфона у меня тоже не было, также как и Мака. Дня 3 возился с установкой osx на virualbox, в итоге смог поставить только на vmware и наладить сеть с virtualbox, чтобы в консоле работать.

Выяснил, что в моему счастью, в xcode 7 появилась возможность компилить приложения с фришным сертификатом, который может создать любой желающий. И айфон 4s мне очень вовремя одолжили. Можно было с головой погрузиться в разработку.

Про Катю
(В предыдущих частях):
Написал ей в ВК, сказала, что тел дома забыла, а сейчас у подруги. Я написал, что подожду её. После чего получил «Не звони и не пиши мне больше!!!!». Вопросов задавать не стал, позвонил в соседнюю квартиру, попросил передать цветы Кате, когда она будет дома. Приехал домой, через несколько часов принял решение переписать Dcoin на Go.

Через пару дней написал ей, что на несколько месяцев ухожу с головой в свой проект и попросил не беспокоить меня по пустякам.

Через неделю от Кати пришла смс-ка «привет. ну как ты там?». Я не ответил. Через неделю еще одна «привет. как дела?». Я снова не ответил.

Еще примерно через неделю она написала, что ей срочно нужно 7 т.р. в долг, т.к. ей не хватает на оплату за квартиру. Я ответил «OK». На следующий день она приехала ко мне домой.

Я не знаю, что у неё было в голове, наверное думала, что я буду к ней приставать. Весь вечер она была какой-то странной. Я был холоден и старался избегать любых прикосновений к ней. Мы поели, попили чаю. Катя сказала, что ей надо домой. Я вызвал такси.
Когда провожал её до такси спросил:

— Мы ведь не вместе да? Т.е. я могу делать что захочу?
Она: — В смысле «что захочу»? нет, мы вместе (пододвигается ко мне)
Я: — Ну у нас же не было первого свидания, мы еще не начали всё с начала.
Она: — Так вот было же только что.
Я: — Какое же это свидание, ты просто за деньгами приехала.

Мы уже стояли у дверей такси, я её усадил, расплатился с водителем, она уехала.

Утром зазвонил телефон, это была Катя. Я не поднял трубку.

На следующий день она прислала смс-ку «привет. я вчера звонила, ты не взял трубку». Я не стал отвечать.

Через неделю она написала, что получила з.п. и хочет скинуть мне на карту деньги. Я ни чего не ответил. Через несколько дней она написала «привет. как дела?». Я снова игнорировал.

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

Она очень позитивно отреагировала на то, что я вышел с ней на связь, согласилась встретиться. Потом сказала, что у неё всё плохо, подружка с которой она снимала квартиру съехала и что она из-за стрессов каждый день плачет, еще и уволиться решила. Я решил, что, когда мы встретимся, предложу ей переехать жить ко мне и ни о чем не париться.

Скомпилировалось и запустилось всё без особых проблем. Открыл в браузере и… ничего. Но зато если зайти по сети на 127.0.0.1:8089 то выдавало кошелек. Стало очевидным, что при нажатии кнопки home приложение переходит в какой-то спящий режим.

По аналогии с андроидом решил сделать сервис. Но, оказывается сервисы на ios невозможны. Максимум что можно сделать — это повисеть в бэкграунде 600 секунд. Так то оно, конечно, логично — борьба за сохранность заряда аккумулятора. В общем, пришлось изучать, как там вообще работают приложения в ios.

Про Катю

В итоге Катя так и не приехала. Опять были какие-то отмазки. Закончилось тем, что она меня снова послала. На этот раз я не думал сразу уходить, т.к. чувствовал, что нужен ей. Но Катя слишком сильно хотела, чтобы я ушел и мне пришлось оставить её в покое. И пообещать больше никогда не звонить и не писать ей.

Создал простенькое приложение в xcode, кинул на тел, работает. Начал копать структуру файлов и параллельно искать что-то похожее в gomobile, нашел вот этот файлик. Узнал про NSLog, определил место, куда он выдает инфу

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

Про Машу

Снова стал искать девушку на сайтах знакомств и в ВК. Я забыл упомянуть, что держу себя в отличной физ. форме, т.к. дома есть куча блинов, 2 штанги, гантельные грифы, скамья и турник. И выгляжу на 20 с чем-то, хотя мне уже за 30. Довольно быстро нашел девушку, которая мне нравилась и которая хотела со мной встретиться.

Objectve-C я не знал, да и сейчас толком не знаю. Но было очевидно, что без понимания, как минимум, синтаксиса ничего не получится. Немного почитал уроки про Objectve-C, стало проще понимать код.

Погуглил про фоновый режим, выяснил, что надо в didFinishLaunchingWithOptions добавить вот такой код

  // UIApplicationBackgroundFetchIntervalMinimum - чтобы наше приложение запустилось в бэкграунде при любом возможном случае
  [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

И добавить в info.plist

  <key>UIBackgroundModes</key>
  <array>
    <string>fetch</string>
  </array>

Gomobile генерит свой info.plist. Внести в него правки можно тут.

Про Машу

На первое свидание я опоздал минут на 10. Когда увидел Машу, то сразу подумал «Ухты, а мне везет», она была очень в моем вкусе. Мы гуляли по парку, катались на лодке, потом я сказал, что мне надо поесть белковой пищи, иначе мышцы расти не будут и повел к себе домой. Поев куриного мяса, пошли в спальню смотреть фильм. Но минут через 30 она сказала, что ей надо домой, т.к. она плохо себя чувствует из-за того, что еще не до конца вылечилась от простуды. Вызвал такси. Маша уехала.

webView

То, что в браузере всё работало было конечно круто, но этого хватало лишь на 3 минуты, ведь когда открывается браузер приложение идет в фоновый режим и через 3 минуты падает. Без webView тут никак. Довольно долго разбирался, куда и как вставить webView, чтобы оно отображалось. GUI-то нет, всё в текстовом файле надо писать, а учитывая, что с разработкой под IOS я был вообще не знаком, мне было очень тяжко

В итоге, конечно, всё получилось и оказалось крайне просто.

Про Машу

Затем в течение недели она говорила, что работает и нет времени встретиться, и увидеться мы сможем только в воскресенье и не раньше, чем через 2 недели. Я сказал, чтобы тогда просто приезжала ко мне после работы, живем то рядом, а видеться раз в неделю меня не устраивает. Она ответила, что подумает.
Через день написала, что боится ехать на ночь к малознакомому парню. Я сказал, что думал что она пропала с концами и уже чуть не начал назначать свидания другим девушкам на эти выходные. Она разозлилась, ругалась.
На следующий день отправил шутки ради смс-ку «Весь день на свиданках, катаюсь на лодке, в мозолях руки и не только». Шутку она не поняла, разозлилась пуще прежнего, пришлось объяснить, что мол шутка это, дома я весь день был, код писал.

- (void)viewDidLoad
{
  // в фоновом потоке спим 3 сек, чтобы веб-сервер мог успеть запуститься, к БД подключиться и пр.
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSThread sleepForTimeInterval:3.0f];
        // Переходим к выполнению кода в главном потоке
        dispatch_async(dispatch_get_main_queue(), ^{
	    // собвственно сам webView
	    self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
	    NSMutableURLRequest * request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1:8089"]];    
	    self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
	    self.webView.scrollView.bounces = NO;
	    self.webView.scalesPageToFit = NO;
	    self.view = self.webView;
	    self.webView.delegate = self;
	    [self.webView loadRequest:request];
        });
    });
    [super viewDidLoad];
}

В интерфейс ViewController надо добавить наш webView

@interface ViewController : UIViewController<UIWebViewDelegate,UIScrollViewDelegate,UITextFieldDelegate>
{
    IBOutlet UIWebView *webView;
    .....
}
@property(nonatomic,retain)UIWebView *webView;

Про Машу

Через день сказала, что готова приехать ко мне на ночь. Видимо ревность победила страх. Я, честно говоря, сильно удивился. На всякий случай сказал, что приставить к ней не буду если она первая не начнет, просто поужинаем, поболтаем и спать ляжем.

Уведомления

«Раз всё так просто, то надо сделать и уведомления» — подумал я.
Objectiv-C код пришлось внедрять в Go

// +build darwin
// +build arm arm64

package sendnotif

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation -framework GLKit -framework UIKit
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <GLKit/GLKit.h>

void
ShowMessM(char* title, char* text) {
    UILocalNotification* localNotification = [[UILocalNotification alloc] init];
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.alertTitle = [NSString stringWithUTF8String:title];
    localNotification.alertBody = [NSString stringWithUTF8String:text];
    localNotification.timeZone = [NSTimeZone systemTimeZone];
    localNotification.applicationIconBadgeNumber = 1;
    localNotification.repeatInterval = NSCalendarUnitMinute;
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    [localNotification release];
}


*/
import "C"

func SendMobileNotification(title, text string) {
	C.ShowMessM(C.CString(title), C.CString(text))
}

Про Машу

Прислал к ней такси, встретил, поднялись ко мне, поужинали, посмотрели какой-то фильм. Время было уже позднее, надо было ложиться спать. Она сказала, что будет спать на гостевом диване, т.к. со мной в одной кровати она еще не готова. «Ну нет, так нет», постелил ей на диване. Через 5 минут заходит и говорит, что у неё «этого» еще никогда не было, но она очень хочет. Для меня это стало приятной неожиданностью. В общем, той ночью мы не спали.

В Go коде использовать так: sendnotif.SendMobileNotification(«Заголовок», «Текст уведомления»)
И в didFinishLaunchingWithOptions надо добавить:

if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
    {
        // iOS 8 Notifications
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        
        [application registerForRemoteNotifications];
    }
    else
    {
        // iOS < 8 Notifications
        [application registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
    }

Это чтобы при запуске у пользователя вылезло сообщение с запросом прав на использование уведомлений.

Про Машу

На 4-м свидании я предложил ей переехать ко мне. Маша согласилась. Заехал к ней в общагу и перевез вещи.

Заключение

На этом я заканчиваю серию статей про свой опыт перехода с PHP на Go. Надеюсь мой материал был кому-то полезен. Если будут вопросы про кроссплатформенную разработку на Go, пишите в личку, помогу.

Про Машу и Катю

Прошло где-то пару недель. Поздний вечер, лежим с Машей на кровати, смотрим Интернов. Звонит Катя. Пьяная. Говорит, что просит у всех прощения, и что она наглоталась снотворного и через несколько часов умрет. Я растерялся, не знал что говорить. Попытался выяснить, где она находится, чтобы прислать к ней полицию и медиков. Потом написал её лучшей подружке, чтобы она сообщала её адрес и связалась срочно с Катей, она почему-то на захотела говорить адрес. Позвонил Кате, и услышал на заднем плане чей-то пьяный голос. Всё стало ясно, это блеф, она развлекается со своей подружкой. На следующий день убедился, что с Катей всё в порядке, т.к. она была онлайн.
Сейчас уже 6-й месяц живу с Машей. Недавно завели кота.

Автор: c-darwin

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js