Главная > Coding, Творчество > +(AppStore *) Занимательная таблица

+(AppStore *) Занимательная таблица

Давненько ничего не сабмитил в AppStore — печально, ибо 99-тидоллоравая подписка на iOS developer program простаивает без дела. Есть задумки, есть даже наброски/черновики, но они все такие грандиозные, что скорым релизом и не пахнет — еще очень много нужно дорабатывать. С пару месяцев назад я решил во что бы то ни стало отрелизить, и совершенно случайно на просторах рунета мне попалась одна незамысловатая фишка, которая показалась не сложной в плане реализации, и сразу же начала оформляться в идею для AppStore-приложения. Суть простая. Таблица для проверки наблюдательности. В таблице расположены числа от 1 до 90, которые нужно найти по порядку.  
Фрагмент того, как выглядела эта таблица в каком-то старом советском журнале, можно видеть на главной иллюстрации к посту, и так она выглядит в AppStore.
Слышал не раз, что пользователи AppStore в первую очередь смотрят на скриншоты, потом на описание, поэтому постарался сделать cкрины пооригинальнее:

Честно говоря, я ее так до конца и не прошел. Когда пытался сделать это первый раз, мои мысли уже были далеко от процесса наблюдения. В голове были только думы о том, как бы это все дело поприличнее оформить, поскольку функциональность копеечная и не сулила больших трудностей в реализации. Изначально я планировал минимальную функциональность — поле с числами, человек находит число за числом и тыкает их, сверху банальный счетчик текущего хода и секундомер (чтобы ориентироваться примерно по времени) — по крайней мере мне этого не хватало, когда я разгадывал газетный вариант. Буквально за пару дней я слепил рабочий прототип с задуманной функциональностью — настолько я был вдохновлен идеей сделать что-то по-быстрому и засабмитить уже наконец. Образец был очень сырой, я тупо взял ту же самую картинку, отрихтовал ее немного и запихал в приложение. Разбил на кусочки изображение, сделал анимацию нажатия на каждый кусочек, и все.
Показал друзьям, сказали — нормально, только выглядит позорно, даже на рисованный стиль не потянет (как я к примеру делал Коня).
Согласен, выглядело действительно жутко. Надо было что-то делать. Биг тханкс моему брату — он перевел растр в векторный шаблон таблицы и изображение мгновенно преобразилось. Теперь стала другая проблема — как расставлять числа? Теперь мне уже хотелось сделать абсолютно динамическое распределение, генерацию случайных последовательностей, короче, чтобы при каждой новой игре генерировалась новая таблица. И тут понеслось… Как же я долго изобретал алгоритм, сколько же пришлось написать дополнительной оснастки (на Delphi и даже на php). Такой

и такой

и еще много всякой другой (: На это ушел целый месяц, но задача была решена.

Потом пришла в голову мысль про таблицу рекордов — это же очевидно, раз есть единица измерения результата игры. Сначала про локальную таблицу. Благо ее было недолго делать, так как заготовка была с предыдущей моей поделки — TakeMeHome. Затем мне захотелось сделать глобальную таблицу рекордов. Вот тут и началось самое интересное. Я знал о существовании таких вещей как GameCenter и OpenFeint, но, во-первых, давно хотелось сделать такое самому (отточить навыки работы с сетью в iOS), а во-вторых, я не был уверен, что разбирательства с движками GameCenter и OpenFeint займут меньше времени чем разработка собственного движка. Поэтому было решено эти разбирательства отложить до следующего раза. Сначала была спроектирована серверная часть, затем клиентская, причем попыхтеть больше пришлось именно над серверной. Дело в том, что я поставил себе задачу во что бы то ни стало показывать в глобальной таблице рекордов иконку с флагом страны пользователя. Совершенно определенно копать нужно было в сторону GeoIP. Изучая вопрос, наткнулся на интересный проект.
У них имеется online-API, с помощью которого можно получать геоинформацию по IP-адресу. Сервис не бесплатный, условия покупки имеют много опций. Например, может быть $20 за 200тыс запросов или анлим за $400 в месяц и т.д. Причем, платный сервис предоставляет очень подробную информацию чуть ли не вплоть до района города. Но есть и бесплатный вариант — это локальная база данных и php-библиотека для удобного использования (есть реализации и для других сервеных платформ). Она позволяет определять только страну. Как заявлено на странице продукта, точность определения составляет 99,5% — просто обалденный результат, то, что мне и надо. То есть это stand-alone решение. Кроме того, она делает попытки вытащить страну клиента с помощью tracert и тому подобных утилит. Использование библы до невозможности простое:

include('geoip.php');
function getRealIpAddr() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {  //check ip from share internet
      $ip=$_SERVER['HTTP_CLIENT_IP'];
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {  //to check ip is pass from proxy
      $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else {
      $ip=$_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}
 
function getCountryCode($ip) {
  $gi = geoip_open("GeoIP.dat",GEOIP_STANDARD);
  $country_code = geoip_country_code3_by_addr($gi, $ip);
  if ($country_code == '')
    error_log('colud not obtain country for ip '.$ip);
  else
    error_log('ip: '. $ip . ' country: '. $country_code);
  geoip_close($gi);
  return $country_code;
}
echo('Your country code is '. getCountryCode(getRealIpAddr()));

getRealIpAddr — функция, которая гарантированно возвращает ip-адрес клиента — как выяснилось $_SERVER[‘REMOTE_ADDR’] не всегда способен это сделать.

Проблему с иконками для флагов государств решил Гугл (:
Авторизацию я решил основывать на идентификаторе устройства — это общепринятный подход в мобильной разработке. И тут возникло небольшое замешательство. Дело в том, что излюбленный вариант iOS-developer’ов в таком случае — уникальный идентификатор устройства (UDID) — он спокойно получается банальным

[UIDevice currentDevice].uniqueIdentifier

Но прознал я, что в iOS5 это свойство переведено в состояние deprecated, что означает, что вскоре оно выведется из эксплуатации. Официальная позиция Apple по этому поводу основана на соображениях безопасности, мол не пристало личную информацию пользователя направо-налево рассылать. Возникает желание использовать MAC. Но какой? В системе может быть несколько сетевых интерфейсов (wifi, 3g, loopback). Тут я считерил немного — взял чужую стабильную заготовку, которая представляет собой категорию UIDevice (IdentifierAddition) автор Georg Kitz. С ее помощью можно всегда получать гарантированно один и тот же deviceID, правда несколько абстрактный.
Дальше дело техники, клиент запрашивает — сервер отвечает. Чтобы избежать читерства со стороны юзера (анализ трафика, подделка запроса), я немного зашифровал исходящий трафик, используя симметричный ключ. Кстати, этот вопрос меня давно интересовал в связи с необходимостью указывать при регистрации приложения в AppStore, не используются ли в программе криптостойкие алгоритмы шифрования. Все оказалось ОК, видимо Apple не счел мой алгоритм криптостойким (:
Для реализации сетевого обмена на клиенте использовал фреймворк CFNetwork, а также неплохую асинхронную библиотеку-обертку. Подробно описывать ее здесь не стану — Она очень проста в применении, вот пример:

- (IBAction)sendRequest:(NSString *) action {
    NSString * params = [NSString stringWithFormat:@"¶m=%@¶m2=%d", param1, param];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", REQEUST_URL, params];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request startAsynchronous];
}
 
- (void)requestFinished:(ASIHTTPRequest *)request {
    NSString *responseString = [request responseString];
    NSLog(@"got response");
}
 
- (void)requestFailed:(ASIHTTPRequest *)request {
	NSLog(@"get error: %d %d", request.responseStatusCode, request.responseStatusMessage);
}

Очень напоминает jQuery.ajax (:
Из интересного, с чем пришлось столкнуться, пожалуй еще можно было бы упомянуть работу с UITabBarController, но этого хватит еще на одну статью, поэтому не буду. Так же стоит отметить, что это был первый проект, который я разрабатывал в IDE xCode версии 4, в котором, как известно, имеются некоторые отличия от предыдущей версии как в плане самого процесса разработки, так и процесса подготовки приложения к регистрации в AppStore. Об этом я собираюсь написать в ближайшее время. Скорее всего, совмещу со статьей о создании бесплатной версии этого приложения с интегрированным in-App purchase и iAd.

  1. 31 May 2012 в 22:09 | #1

    приложение сделал платным?
    если да, то как идут дела с монетизацией?

  2. 31 May 2012 в 23:26 | #2

    Да, изначально зарелизил платную версию. Недельку-две поскачивалось, потом сошло на нет. Продвижением не занимался совсем, времени нет(
    Чуть позже выпустил бесплатную версию с некоторыми ограничениями. Но тоже спрос не ахти.

  3. 4 June 2012 в 23:52 | #3

    Но молодец, что сделал — молодец
    Теоретически — ты можешь прощупать и то что пойдет — надо найти просто то, что тебя самого прикольнёт — мне так нравится — если тебя прикольнёт и ты вложишь душу — то пойдёт..
    А если не пойдет — все равно кайф — ведь тебя прёт
    У меня знакомый за год — на приложении навигаторе, который написал для апп-сторе — поднялся от безработного с пустыми карманами, до довльно нормального оборота, взял офис и народ

  4. 5 June 2012 в 09:37 | #4

    Полностью согласен с данной позицией. Главное, чтоб самому понравилось. Мне понравилось)
    По поводу истории со стремительным взлетом — тоже знаю пару таких лично. Мы живем в инновационную эпоху и такой шанс есть у каждого. Главное, не сдаваться и продолжать искать.
    Qui quaerit inveniet!
    (:

  5. Андрей
    12 October 2012 в 23:55 | #5

    Привет. Где можно найти твою таблицу, хочу посмотреть как хоть получилось.

  6. 16 October 2012 в 16:17 | #6

    Да в общем в статье была iTunes-ссылка ;)

    https://itunes.apple.com/us/app/amusing-table/id483897374

  7. Андрей
    16 October 2012 в 17:53 | #7

    Как я понял вас зовут Павел, я указал свою эл.почту, вы наверное её видите, можете прислать на нее адрес своего мыла, у меня к вам пара вопросов, предложений.

Подписаться на комментарии по RSS