Arm1.ru

Tag: «xcode»

Carthage vs. CocoaPods

Пара мыслей о Carthage в сравнении с CocoaPods.

Что у Carthage так же, как и у CocoaPods:

  • Для CocoaPods создаётся Podfile. Для Carthage нужно создать Cartfile.
  • И там, и там можно указать конкретную версию зависимости и конкретный git-репозиторий.
  • После установки зависимостей создаётся Podfile.lock для CocoaPods и Cartfile.resolved для того, чтобы установить конкретные версии зависимостей/библиотек.
  • И для CocoaPods, и для Carthage довольно просто всё устанавливается одной командой из консоли.

Минусы:

  • Все зависимости необходимо добавлять ручками в проект и раздел Build Phases. Делается это один раз, но ручками, в отличие от CocoaPods, где он сам генерит WorkSpace. С одной стороны это неудобство, с другой - просто мы избалованы CocoaPods. Например, в мире Node.js мало сделать npm install package, ты всё равно должен заинклудить зависимость там где надо через require.
  • Меньше выбор. Меньше популярности. CocoaPods старше, популярнее и многие библиотеки распространялись через CocoaPods. Многие до сих пор только через них распространяются, включая, например, SDK от Google. Для Carthage проще найти что-то более менее свежее. Зато оно, как правило, доступно и через CocoaPods, и через Carthage, и даже через Swift Package Manager.

Плюсы:

  • Зависимости билдятся один раз. При любой сборке проекта библиотеки и зависимости не собираются заново, даже если очистить все кэши и сделать все clean'ы. В итоге каждый билд идёт быстрее.
  • Не создаётся ещё одного файла .xcworkspace, файл проекта остаётся нетронутым. Создание WorkSpace в последних версиях CocoaPods глючит уже чуть ли не полгода и создаёт этот WorkSpace так, что проект просто не собирается и приходится лезть ручками что-нибудь исправлять. Например, путь для поиска файлов-заголовков.
  • При обновлении зависимости до последней версии, опять же, не трогается файл проекта. Просто пересобираются, они уже добавлены в проект.
  • Можно сбилдить зависимость сразу для всех платформ, или для конкретной, например, для tvOS.
  • У CocoaPods центральный репозиторий. Если он упадёт - ничего не будет работать. У Carthage такого нет, он просто берёт с GitHub зависимости. С одной стороны это тоже некий центральный репозиторий, но без промежуточного звена, и шансы, что он выстоит от нагрузки, выше.
comment comments

Баг Xcode 7 с [NSLocalizableString length]

В Xcode 7 есть баг с локализацией, при котором приложение падает, вызывая много много раз [NSLocalizableString length]. У меня в проекте я словил его в связи с тем, что некоторые xib'ы у меня лежали вне папки самого проекта в папке Base.lproj. В итоге каждый раз, когда что-то загружалось в приложении из этих xib'ов - происходило падение без внятной причины. Причём в последнем Xcode 6 всё было прекрасно. Разрулить удалось переименовав Base.lproj в en.lproj и добавив в проект файлы заново из этой папки.

Ещё пара решений есть на Stack Overflow, суть та же, просто некоторым помогло просто включить/выключить галочку Use Base Localization либо отметить у файла Storyboard английский язык, но это скорее для тех, у кого весь UI внутри Storyboard нарисован. Есть ещё тема на форуме разработчиков Apple.

Причём баг, похоже, давно в 7 версии Xcode, в бетах тоже, по-моему, наблюдался. В текущей версии 7.01 присутствует. Надеюсь исправят в ближайшем будущем.

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 
#import 

@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

Автоувеличение номера билда в Xcode

Автоувеличение номера билда в Xcode

Ещё одна шпаргалка, чтобы потом быстро найти, в случае чего. В Xcode, как известно, можно при билде проекта запускать свои bash-скрипты.

Эти 2 строчки кода позволяют автоматически увеличивать номер билда в приложении:

buildNumber=$(git rev-list --all | wc -l)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Первая строка считает количество коммитов в git-репозитории. Вторая - пишет их количество в .plist-файл таргета как номер билда. Каждый новый коммит увеличивает номер билда на единицу. Это один из способов.

Пихать в Build Phases нужного таргета.

comment comments

Выход за пределы песочницы в iOS

Пост боли. Так получилось, что сейчас ковыряю чужой проект, который рассчитан на работу на айфонах с Jailbreak. Да не просто рассчитан, а ему нужно иметь доступ за пределы песочницы.

Как известно, все приложения в iOS работают внутри песочницы, за пределы которой они выходить не могут. Все приложения из App Store устанавливаются в /var/mobile/Applications/ (приложения, которые ставятся в iPhone из Xcode - туда же), где для них создаётся отдельная папка с нечитаемым именем. Выходить за пределы этой папки нельзя. Ни для чтения, ни, тем более, для записи.

Выход за пределы песочницы в iOS
Это, например, папка гугловой игры Ingress.

Выход за пределы песочницы в iOS
А это айосный калькулятор, например, лежащий в /Applications.

Если мы хотим, например, прочитать в приложении SMS-сообщения телефона, то нам нужно прочитать файл /var/mobile/Library/SMS/sms.db - это обычная SQLite база данных, без шифрования и защиты. Её можно скачать с джейлбрейкнутого телефона и открыть любой тулзой, которая умеет открывать SQLite-файлы, и посмотреть все SMS-ки и даже фигачить по ней sql-запросы для поиска и прочего.

Выход за пределы песочницы в iOS
Тут, например, лежит файл со всеми смс-ками iPhone.

Так вот, доступа к этому файлу из песочницы нет. И Jailbreak от этого не спасает, он даёт полный доступ к файловой системе, но только если ты работаешь вне песочницы.

Чтобы приложение работало вне песочницы - его нужно переместить из /var/mobile/Applications/ в директорию /Applications. Тогда приложение будет в папке системных программ, будет иметь доступ на брейкнутом девайсе к файловой системе, не будет удаляться из телефона удержанием пальца на иконке и всё такое.

И вот боль тут в том, Xcode ну никак не может установить приложение туда, только в песочницу. Можно делать это руками - заходить в телефон, перемещать через какой-нибудь iFunBox, и вот такой вот геморрой каждый раз. И самая боль в том, что ты теряешь удобство отладки. Нельзя запустить в Xcode апп на девайсе и спокойно смотреть в консольку - что же там приложение твоё пишет - работает или нет?

Никакие твики из Cydia, типа дающие для приложений доступ к файловой системе даже для приложений из песочницы, не дали эффекта. По крайней мере, у меня на iOS 7.1.2. Говорят, что даже если запустить приложение от root'а, но всё равно в песочнице - и это не даст прав на чтение системных директорий. Хотя, такое ощущение, что раньше такое работало, но и джейлбрейки были другие.

Такой вот ад. В ближайшее время буду пробовать найденные в инете скрипты для автоматизации перемещения приложения внутри айфона после билда через SSH с отлавливанием syslog'а. Хочу ещё расписать, чего я наковырял внутри айфона в плане «где что хранится», но позже, по окончании ада :)

comment comments