Arm1.ru

Пара слов про Parse.com

Ковырял тут кое-что на Parse. В двух словах - штука очень крутая, есть крутые SDK для разных платформ, в том числе можно на Javascript юзать их как на фронт-энде, так и на бэкенде. Можно прям у них в облаке написать на node.js его, даже можно Express подключить, если нужно. Но есть два но:

  1. Когда ты создаёшь отложенный push notification с расписанием - ты указываешь время отправки. Так вот через Javascript SDK он выставляет его по GMT и всё. Всем пуш будет отправлен по GMT вне зависимости от их часовой зоны, просто по расписанию. Указать, что ты хочешь отправить push всем, например, в 19:00 местного времени, чтобы клиент в любом часовом поясе получил сообщение в свои 19:00, в Javascript SDK ты не можешь. Этому багу уже 2 года. Вместо этого, тебе предлагается использовать из Javascript их REST API (sic!).
  2. Окей, ты используешь REST API, благо это можно из того же Javascript SDK удобно сделать, и всё работает как надо, пуши планируются по местному времени, но... В тексте заголовка из сообщения вырезаются все русские буквы. Во всех примерах в документации к REST API просят указать заголовок запроса "Content-Type: application/json", вот только этого мало, чтобы кириллица и прочие символы не из латиницы не вырезались, оказывается, нужно указать кодировку в заголовке: "Content-Type: application/json; charset=utf-8". Чёрт его знает, в какой кодировке они ожидают по умолчанию данные, выкатывая международный сервис, но тем не менее.

А в остальное, конечно, сервис очень классный.

comment comments

Сборка iOS проекта из консоли через xcodebuild

Оставлю себе шпаргалку, как сделать на bash скрипт, который соберёт тебе проект в ipa файл.

В папке с исходниками iOS-проекта делаем папку, например, scripts, в нем создаём файл build.sh

mkdir scripts
touch build.sh
chmod +x build.sh

В папку кладём наш provision profile. Скажем, называется он arm1.ru.mobileprovision. После этого внутрь build.sh кладём код:

#!/bin/bash

# идём в директорию скрипта
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "${CURRENT_DIR}"

# вводим то же имя, которое в настройках проекта выбрано в Build Settings в разделе Code Signing Identity
CODE_SIGN_IDENTITY="iPhone Distribution: Your Code Signing Identity"

# имя provision profile, который лежит тут же
PROVISION="$PWD/arm1.ru.mobileprovision"

# имя схемы, которую собираем
SCHEME="appScheme"
WORKSPACE="$PWD/../your-app.xcworkspace"

echo "Building..."

BUILDDIR="$PWD/build"
DSYMDIR="$PWD/dSYM"

if [ ! -d "$BUILDDIR" ]; then
    mkdir -p "$BUILDDIR"
fi

if [ ! -d "$DSYMDIR" ]; then
    mkdir -p "$DSYMDIR"
fi

# ищем UUID в provision profile
UUID=`grep UUID -A1 -a "${PROVISION}" | grep -io "[-A-Z0-9]\{36\}"`


xcodebuild \
    -workspace "${WORKSPACE}" \
    -scheme "${SCHEME}" \
    -sdk iphoneos \
    -configuration Release \
    CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" \
    PROVISIONING_PROFILE="${UUID}" \
    OBJROOT=$BUILDDIR \
    SYMROOT=$BUILDDIR

if [ $? != 0 ]; then
    echo "Build failed"
    exit 1
fi

echo "Packaging..."

NOW=$(date +"%d_%m_%Y_%H_%M_%S")

xcrun -sdk iphoneos PackageApplication -v "${BUILDDIR}/Release-iphoneos/${SCHEME}.app" -o "$PWD/${SCHEME}_${NOW}.ipa"
if [ $? != 0 ]; then
    echo "Packaging failed"
    exit 2
fi

mv "${BUILDDIR}/Release-iphoneos/${SCHEME}.app.dSYM" "${DSYMDIR}/${SCHEME}_${NOW}.app.dSYM"

echo "Build succeeded."

Вуаля, в папке со скриптом лежит appScheme.ipa - собранный проект. В папке dSYM лежат dSYM-файлы. В конце скрипта можно дописать что-нибудь. У меня в одном из проектов в конце идёт заливка билда на наш самодельный Testflight и отправка ссылки на установку всем кому нужно. Удобно, два раза кликнул по sh-файлу и всё собралось и отправилось.

comment comments

Как отключить жест swipe back в iOS 8

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

В общем для iOS 8 надо в текущем UIViewController добавить:

в YouViewController.h:

// ставим протокол обработки жеста
@interface YouViewController : UIViewController <UIGestureRecognizerDelegate>

в YouViewController.m:

- (void)viewDidLoad {
  [super viewDidLoad];

  self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  // отключаем жест если это swipe back
  if ([gestureRecognizer isEqual:self.navigationController.interactivePopGestureRecognizer]) {
    return NO;
  } else {
    return YES;
  }
}
comment comments

Правильный парсинг дат через RestKit. Из NSString в NSDate

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

Внутри RestKit уже есть несколько NSDateFormatter для того, чтобы спарсить дату. Если один не смог - используется второй и т.д. Но для формата, в котором я получал даты через API, ни один не подошёл. Чтобы правильно парсить даты, нужно добавить свой NSDateFormatter, причём самым первым в список, чтобы он первым применялся:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss Z"];

[RKObjectMapping alloc];
[[RKValueTransformer defaultValueTransformer] insertValueTransformer:dateFormatter atIndex:0];
comment comments

Жизненный цикл UIVIewController

Жизненный цикл UIVIewController

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

Читать далее...

comment comments

Transparent Image Viewer для OS X

Transparent Image Viewer для OS X

Я всё пытаюсь что-нибудь придумать, чтобы можно было удобно делать pixel perfect вёрстку экранов при разработке iOS-приложений. Чтобы можно было удобно и наглядно сравнивать макет и результат. Запилил сегодня вот такую тулзу для OS X - почти прозрачное окно, в котором можно открыть макет, наложить на Xcode или на симулятор и смотреть, что получилось. Ползунком можно менять прозрачность, чтобы проверять соответствие.

Может кому пригодится. А может кто-то тоже чувствует боль и поучаствует в разработке.

Исходники лежат на github.

Скачать бинарник.

P.S. моё первое приложение для OS X.

comment comments

Категория CALayer+UIColor

Хорошую штуку нашёл на Stack Overflow. В Xcode в Interface Builder можно задать что-то для UI через User Defined Runtime Attributes. Мне понадобилось задать border. Так вот толщину границы layer.borderWidth задать можно и она подхватится, а вот цвет - нет. layer.borderColor хранит значение типа CGColorRef, а цвет, который ты можешь выбрать в Interface Builder - это UIColor. Простая категория позволяет использовать UIColor через свойство layer.borderUIColor.

CALayer+UIColor.h :

//
// CALayer+UIColor.h
//
// Created by Sergey Armodin on 29/05/15.
// Copyright (c) 2015 Sergey Armodin. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer (UIColor)
/**
* CGColor to borderColor
*/
@property(nonatomic, assign) UIColor* borderUIColor;
@end

CALayer+UIColor.m :

//
// CALayer+UIColor.m
//
// Created by Sergey Armodin on 29/05/15.
// Copyright (c) 2015 Sergey Armodin. All rights reserved.
//

#import "CALayer+UIColor.h"

@implementation CALayer (UIColor)
/**
* Setter
*
* @param color UIColor
*/
- (void)setBorderUIColor:(UIColor *)color {
    self.borderColor = color.CGColor;
}

/**
* Getter
*
* @return UIColor
*/
- (UIColor *)borderUIColor {
    return [UIColor colorWithCGColor:self.borderColor];
}
@end

И вуаля:

Категория CALayer+UIColor

comment comments