- PVSM.RU - https://www.pvsm.ru -
Заключительная часть серии статей про мой опыт перехода с PHP на Go.
Первая часть [2], вторая [3], третья [4], четвертая [5].
4,5 года назад я имел неосторожность начать писать свою криптовалюту на совсем неподходящем для этого дела языке — на PHP. В итоге, конечно, написал (я упрямый), но получился костыль на костыле и то, что оно вообще работало было просто какой-то магией.
Сразу хочу предупредить, программер я самоучка-недоучка и пишу код, мягко сказать, неидеально.
Началось всё с того, что я расстался с девушкой, по имени Катя и в этот же день (4 апреля 2015-го) решил изучить Go и переписать свою криптовалюту. Писать про Катю не под спойлерами не могу, т.к. хабр всё же для IT-шных статей, а не для любовных рассказов и суровые айтишники, которым интересна тема Go, могут просто не обращать внимание на спойлеры «про Катю» и «про Машу».
Итог 8 месяцев: приложение работает на Win, OSX, Linux, FreeBSD [6], Android [7], IOS [8]
Общего кода ~73к строк, кода под разные ОС где-то несколько сотен строчек.
40к — обработка/генерация блоков/тр-ий, 17.5к — контроллеры для интерфейса, 15.5к — шаблоны.
Поддерживаются PostgreSQL, SQLite, MySQL.
Тех, кто будет тестировать мое творение, предупреждаю — могут быть баги, и если у Вас есть время, черкните о них, пожалуйста, на darwin@dcoin.club [9] или в личку на хабре. Пожелания и советы тоже приветствуются.
В первых четырех частях я рассказал про то, как в dcoin функционирует веб-сервер, про html/template [10], базы данных, плавное завершение приложения, шифрование и парсинг блоков, Android-приложение.
В этой части я расскажу про компиляцию под IOS.
Первой сложностью было то, что у меня не было сертификата разработчика. А без него скомпилировать приложение не получалось. Айфона у меня тоже не было, также как и Мака. Дня 3 возился с установкой osx на virualbox, в итоге смог поставить только на vmware и наладить сеть с virtualbox, чтобы в консоле работать.
Выяснил, что в моему счастью, в xcode 7 появилась возможность компилить приложения с фришным сертификатом, который может создать любой желающий. И айфон 4s мне очень вовремя одолжили. Можно было с головой погрузиться в разработку.
Через пару дней написал ей, что на несколько месяцев ухожу с головой в свой проект и попросил не беспокоить меня по пустякам.
Через неделю от Кати пришла смс-ка «привет. ну как ты там?». Я не ответил. Через неделю еще одна «привет. как дела?». Я снова не ответил.
Еще примерно через неделю она написала, что ей срочно нужно 7 т.р. в долг, т.к. ей не хватает на оплату за квартиру. Я ответил «OK». На следующий день она приехала ко мне домой.
Я не знаю, что у неё было в голове, наверное думала, что я буду к ней приставать. Весь вечер она была какой-то странной. Я был холоден и старался избегать любых прикосновений к ней. Мы поели, попили чаю. Катя сказала, что ей надо домой. Я вызвал такси.
Когда провожал её до такси спросил:
— Мы ведь не вместе да? Т.е. я могу делать что захочу?
Она: — В смысле «что захочу»? нет, мы вместе (пододвигается ко мне)
Я: — Ну у нас же не было первого свидания, мы еще не начали всё с начала.
Она: — Так вот было же только что.
Я: — Какое же это свидание, ты просто за деньгами приехала.
Мы уже стояли у дверей такси, я её усадил, расплатился с водителем, она уехала.
Утром зазвонил телефон, это была Катя. Я не поднял трубку.
На следующий день она прислала смс-ку «привет. я вчера звонила, ты не взял трубку». Я не стал отвечать.
Через неделю она написала, что получила з.п. и хочет скинуть мне на карту деньги. Я ни чего не ответил. Через несколько дней она написала «привет. как дела?». Я снова игнорировал.
Еще примерно через неделю я наконец запустил Dcoin на нодах и увидев, как идет генерации блоков и как они летают между нодами, наполняя базы данных. Мне показалось, что это можно считать завершением моего временного отшельничества и я написал Кате.
Она очень позитивно отреагировала на то, что я вышел с ней на связь, согласилась встретиться. Потом сказала, что у неё всё плохо, подружка с которой она снимала квартиру съехала и что она из-за стрессов каждый день плачет, еще и уволиться решила. Я решил, что, когда мы встретимся, предложу ей переехать жить ко мне и ни о чем не париться.
Скомпилировалось и запустилось всё без особых проблем. Открыл в браузере и… ничего. Но зато если зайти по сети на 127.0.0.1 [11]:8089 то выдавало кошелек. Стало очевидным, что при нажатии кнопки home приложение переходит в какой-то спящий режим.
По аналогии с андроидом решил сделать сервис. Но, оказывается сервисы на ios невозможны. Максимум что можно сделать — это повисеть в бэкграунде 600 секунд. Так то оно, конечно, логично — борьба за сохранность заряда аккумулятора. В общем, пришлось изучать, как там вообще работают приложения в ios.
Создал простенькое приложение в xcode, кинул на тел, работает. Начал копать структуру файлов и параллельно искать что-то похожее в gomobile, нашел вот этот файлик [12]. Узнал про NSLog, определил место, куда он выдает инфу
Помню свою радость, когда увидел строки в логе, которые выводило мое приложение. Это было круто, связь налажена, дальше будет проще. Для меня возможность писать и читать логи — это, наверное, самое важное при разработке приложения.
Objectve-C я не знал, да и сейчас толком не знаю. Но было очевидно, что без понимания, как минимум, синтаксиса ничего не получится. Немного почитал уроки про Objectve-C, стало проще понимать код.
Погуглил про фоновый режим, выяснил, что надо в didFinishLaunchingWithOptions добавить вот такой код
// UIApplicationBackgroundFetchIntervalMinimum - чтобы наше приложение запустилось в бэкграунде при любом возможном случае
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
И добавить в info.plist
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
Gomobile генерит свой info.plist. Внести в него правки можно тут [13].
То, что в браузере всё работало было конечно круто, но этого хватало лишь на 3 минуты, ведь когда открывается браузер приложение идет в фоновый режим и через 3 минуты падает. Без webView тут никак. Довольно долго разбирался, куда и как вставить webView, чтобы оно отображалось. GUI-то нет, всё в текстовом файле надо писать, а учитывая, что с разработкой под IOS я был вообще не знаком, мне было очень тяжко
В итоге, конечно, всё получилось и оказалось крайне просто.
- (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))
}
В 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)];
}
Это чтобы при запуске у пользователя вылезло сообщение с запросом прав на использование уведомлений.
На этом я заканчиваю серию статей про свой опыт перехода с PHP на Go. Надеюсь мой материал был кому-то полезен. Если будут вопросы про кроссплатформенную разработку на Go, пишите в личку, помогу.
Автор: c-darwin
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/go/118091
Ссылки в тексте:
[1] Image: https://habrahabr.ru/post/281709/
[2] Первая часть: http://habrahabr.ru/company/dcoin/blog/272695/
[3] вторая: http://habrahabr.ru/post/273333/
[4] третья: https://habrahabr.ru/post/274885/
[5] четвертая: https://habrahabr.ru/post/277099/
[6] Win, OSX, Linux, FreeBSD: https://github.com/c-darwin/dcoin-go/releases/
[7] Android: https://play.google.com/store/apps/details?id=org.golang.app
[8] IOS : http://dcoin.club/ru/ios.html
[9] darwin@dcoin.club: mailto:darwin@dcoin.club
[10] html/template: https://golang.org/pkg/html/template/
[11] 127.0.0.1: http://127.0.0.1
[12] вот этот файлик: https://github.com/golang/mobile/blob/master/app/darwin_armx.m
[13] тут: https://github.com/golang/mobile/blob/master/cmd/gomobile/build_iosapp.go#L171
Нажмите здесь для печати.