Финал той самой истории.

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

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 мне очень вовремя одолжили. Можно было с головой погрузиться в разработку.

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

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

Скомпилировалось и запустилось всё без особых проблем. Открыл в браузере и… ничего. Но зато если зайти по сети на 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-м свидании я предложил ей переехать ко мне. Маша согласилась. Заехал к ней в общагу и перевез вещи.

Заключение


На примере Dcoin можно понять, что почти любой человек может писать на GO приложения, которые будут работать на всех основых ОС, в том числе и на мобильных.

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


P.S.


1. 21 апреля едем в Нью-Йорк на выставку стартапов TechDay, если будете там же, велкам к нашему стенду.
2. В Dcoin сейчас можно получить бесплатные монеты (хватит на оплату инета на несколько месяцев).

Комментарии (0)