Показаны сообщения с ярлыком Xcode. Показать все сообщения
Показаны сообщения с ярлыком Xcode. Показать все сообщения

1 сент. 2016 г.

Objectve C: немножно макросов для облегчения имплементации протокола NSCoding

Для поддержки протокола NSCoding в Objective C класс должен реализовать два метода для (де)сериализации каждого поля объекта. Ниже привожу набор макросов, которые упрощают этот процесс:

In order to support NSCoding protocol in Objective C class must implement 2 methods to (de)serialize every object's field. Below is set of macro to make it little easy:


#define encObj(__name__) {if(__name__) {[aCoder encodeObject:__name__ forKey:@#__name__];} }
#define encPoint(__name__) [aCoder encodeCGPoint:__name__ forKey:@#__name__];
#define encSize(__name__) [aCoder encodeCGSize:__name__ forKey:@#__name__];

#define encInt(__name__) [aCoder encodeInt:__name__ forKey:@#__name__];
#define encFloat(__name__) [aCoder encodeFloat:__name__ forKey:@#__name__];
#define encDouble(__name__) [aCoder encodeDouble:__name__ forKey:@#__name__];
#define encBool(__name__) [aCoder encodeBool:__name__ forKey:@#__name__];

////////////////////
////////////////////
#define decObj(__name__) __name__ = [[aDecoder decodeObjectForKey:@#__name__] retain];
#define decInt(__name__) __name__ = [aDecoder decodeIntForKey:@#__name__];
#define decFloat(__name__) __name__ = [aDecoder decodeFloatForKey:@#__name__];
#define decDouble(__name__) __name__ = [aDecoder decodeDoubleForKey:@#__name__];
#define decBool(__name__) __name__ = [aDecoder decodeBoolForKey:@#__name__];
#define decPoint(__name__) __name__ = [aDecoder decodeCGPointForKey:@#__name__];
#define decSize(__name__) __name__ = [aDecoder decodeCGSizeForKey:@#__name__];

29 мар. 2016 г.

Unicode последовательности и NSString. Unicode composed sequence and NSString.

Завязался с оперированием эмотиконками из набора Unicode символов строке NSString. Одна из сложностей с Unicode в том, что он бывает не только UTF-8, но и UTF-16, и UTF-32. В данном случае стояла задача удаления последней эмотиконки из строки текста. Посимвольное удаление не работает, поскольку даже при том, что для этих значков используется UTF-32 (то есть длина символа понятна — 4 байта), существую так называемые Композиционные последовательности Unicode (вольный перевод). Например, такой неоднозначный значок как "👨‍👨‍👦‍👦"(Family: MAN, MAN, BOY, BOY) состоит из 7 символов: U+1F468 U+200D U+1F468 U+200D U+1F466 U+200D U+1F466. Соответственно, чтобы удалить одну иконку, нужно удалять до 7 символов. Причем от иконки к иконке их количество меняется. У NSString для этих случаев есть набор методов для работы с такими последовательностями. Они описываются в статье "NSString and Unicode", поэтому их все я тут описывать не буду. Конкретная задача удаления последней иконки, вне зависимости от количества составляющих ее Unicode символов была решена так:

NSRange rng = [str rangeOfComposedCharacterSequenceAtIndex:[str length]-1];
        str = [str substringToIndex:rng.location];

В частности, здесь использован метод rangeOfComposedCharacterSequenceAtIndex, который возвращает NSRange, указывающий на первый символ последовательности и на длину самой последовательности. Дальнейшее оперирование производится как с обычными символами.

2 дек. 2013 г.

Tips: Размеры некоторых элементов экрана iPhone/iPad

CGRect rect;

// Get screen dimensions
rect = [[UIScreen mainScreenbounds];
NSLog(@"Bounds: %@", NSStringFromCGRect(rect));

// Get application frame dimensions (basically screen - status bar)
rect = [[UIScreen mainScreenapplicationFrame];
NSLog(@"App Frame: %@"NSStringFromCGRect(rect));

// Get status bar frame dimensions
rect = [[UIApplication sharedApplicationstatusBarFrame];
NSLog(@"Statusbar frame: %@"NSStringFromCGRect(rect));

7 нояб. 2013 г.

25 мая 2013 г.

Шпаргалка по разработке Objective-C приложений

Вольный... Нет. Очень вольный перевод статьи Стюарта Холла "iOS Development Tips I Would Want If I Was Starting Out Today" (Шпаргалка по iOS разработке, которую я хотел бы иметь, если бы начинал разрабатывать сегодня).

Программирование под iOS становится легче с каждым релизом Xcode. И каждая новая фича увеличивает количество вариантов выбора. 
В мои годы (запах плесени) было гораздо тяжелее! Это так. Но сейчас предъявляют все более высокие требования к качеству. Планка качества постоянно растет. И это хорошо.
И доведись мне начинать свое знакомство с iOS-разработкой сегодня, я бы сильно хотел, чтобы мне кто-то дал почитать этот текст. Надеюсь он кому-то поможет.

Используйте ARC!

ARC — это замечательно. Эта фича избавляет нас от тонны геморроя в работе с памятью, с которыми приходилось сталкиваться ранее. Однако ARC не исключает необходимости понимания того, как работает память, и как держать ее в сухости и чистоте без включенной опции ARC. Я, как олдфаг от плюсов боролся с ARC какое-то время. Но даже многие популярные библиотеки переходят на использование ARC. Не борись. Это внутри тебя. Расслабься и получай удовольствие.

Тулим блоки где только можно

Блоки похожи на ARC. По крайней мере в том, что блоки — это тоже замечательно. Используя блок ты пишешь меньше кода, и он значительно лучше, чем раньше. Меньше кода == меньше багов. Вот тут - классное введение к использованию блоков (ахтунг - тут и далее много нерусских букв - прим. переводчика). 
NSNotifications и _delegate/@protocol все еще на коне. Но сначала подумайте о блоках, а потом уже — про Акима

Опасносте детектед! Retain Cycles в Блоках

Тут тема разжована. Кратко: retain cycles, это когда два объекта (будь-то блок, таймер или вездесущий self) ретейнят друг друга и не могут со спокойной душой отойти в мир иной и устраивают утечку памяти. С блоками такое легко подхватить.

Потоки? Не, не слышал. Пользуй GCD

"Был у дева головняк. Он решил заюзать thread. Головняк теперь двояк."
GCD облегчает нам жизнь. Он — наш друг. Только не забудьте вернуться в главный поток, если делаете что-то с UI.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    // Your code
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        // Now you can interact with the UI
    });
});
Хорошее объяснение GCD можно найти хере

Singletons / Shared Objects

В продолжение о GCD. Он помогает забыть про ручное выпиливание синглтона:
    + (MyClass *)sharedClass {
static MyClass *_shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    _shared = [[MyClass alloc] init];
});   
return _shared;
}
Все! Боле ничего не нужно. А зацените, сколько весит NSDateFormatter и его создание при каждом обращении! Хороший повод засунуть его в синглтон.

Story Boards — только для быстрых прототипов

ИМХО, со Story Boards больше геморроя, чем пользы. Но это мое мнение. Многие любят их. Решите сами.

XIBы — только для базовых набросков

У Interface Builder столько "низзя", что проще собрать нужную вьюшку в рантайме. К тому же, мержинг двух версий XIB-файла — тот еще трюк, который обычно никто и не делает. Гораздо проще смержить два сорца.
Можно что-то набросать базовое. Но ровнять все равно лучше в коде.

Держите свой проект упорядоченным

Я подзавязал с Ruby on Rails. Но организация проекта мне понравилась. Я так организую свои проекты в Xcode:
Xcode structure
Чистота — залог здоровья!

Присмотритесь к Open Source

Существует множество бесплатных опенсорсных библиотек и компонент. Github забит выдающимися сорцами, который можно просто кинуть в свой проект и пользовать их. Кроме того есть Cocoa Controls. Там тоже полно вкусняшек.
Некоторые либы я включаю почти в каждый свой проект:
Если вы гуглите какой-то модуль, он скорее всего уже тут есть. Ну, по крайней мере что-то похожее.

Управление зависимостями проекта

Чтобы управляться с набором либ, подключенных к проекту, рекомендую пользовать CocoaPods. Этот инструмент делает amazing job. Прямо как Ruby's gems.
Или можете просто использовать отдельные модули.

Попробуйте полюбить Stack Overflow

Тут много действительно толковых девелоперов. Еще больше шансов, что искомая задача уже была решена тут. Только сначала напрягитесь и поищите в ответах перед написанием нового поста.

Элегантная деградация

Зачастую хочется использовать свежие фичи новых версий iOS. Но девайсы со старой версией iOS все еще в ходу, и фишки типа  Tweet Sheets в iOS 5, SKStoreProductViewController & UIActivityViewController в iOS 6 приходится поддерживать и для более взрослых версий.
В этом нам поможет не Бахметьев, а проверка существования класса в рантайме:
if (NSClassFromString(@"SKStoreProductViewController")) {
// Класс существует, значит мы в iOS 6+
    SKStoreProductViewController *storeController = [[SKStoreProductViewController alloc] init];
….
}
else {
    // Нет такого класса - значит мы на старом корыте
}

Кастомные шрифты

В прежних версиях iOS (lj 3.2) это была жопа. Поэтому все использовали штатную Helvetica. Но теперь все стало шикарно!
Тутe — краткое описание. Если непонятно как называется шрифт, загляните в Font Book и посмотрите PostScript-имя шрифта.

Локализация должна начинаться до проекта

Локализация реализуется с помощью Xcode очень просто. Особенно, если не использовать xib-файлы. Но легкость локализации проекта в самом начале пропорциональна сложности локализации уже существующего проекта.
Это — замечательный пример локализации приложения под iPhone.

Отслеживайте краши

Креш-логи — это тяжко. Но в помощь нам — сервисы, которые их собирают и приобразуют в читабельный вид. Два стандарта дефакто на сегодня — HockeyApp и TestFlight

Analyze

Инструмент Product -> Analyze должен стать вашим другом. Статические анализаторы — мощное орудие в борьбе с Хейзенбергом.

Instruments

Product -> Profile билдит приложение и запускает Instruments. Instruments — коллекция инструментов (внезапно) проверки вашего приложения. Во-первых стоит взглянуть на "Time Profiler", который покажет сколько процессорного времени занимает ваше приложение. Если ваша табличка скроллится как растекшееся масло, скорее всего она потреблят слишком много процессорного времени.
Instruments

Отслеживайте обзоры

<без ложной скромности>Баги были, есть и будут. Никуда от них не деться. И в отзывах они будут упомянуты. И будут вести они к плохим обзорам. В том числе от юзверей из стран, про которые вы даже не слышали. Не игнорируйте их. Обрабатывайте и получайте их с помощью AppBot. </без ложной скромности>
Уверен, что забыл кучу полезных советов. Да и не все мои советы будут приняты единогласно. Но буде единая заблудшая душа спасена сим постом, буду считать свою миссию выполненной.

29 июн. 2012 г.

Tips and tricks in Xcode.

    Дорвался до видео с WWDC 2012. Видео бесплатны, в хорошем качестве, с субтитрами. Но и без субтитров все понятно - язык технический. Первое из-за чего проспал на работу - сессия по советам работы с Xcode (про Delphi и Visual Studio умолчали). Выступали три инженера. Лиц на видео не показывали, поэтому выдержана ли была политкорректность - не знаю. Но два голоса были мужские и один, кажется, женский. Описывались три схемы работы с IDE: однооконная, с несколькими закладками и многооконная. Хинты, показанные на сессии удобны для всех схем работы. Главный тезис, звучавший сквозь всю сессию, - хоткеи, хоткеи и еще раз автоматизация!
    ИтаГ, какие хоткеи я вынес для себя из просмотра видео:

  • Cmd+Shift+{ напару с Cmd+Shift+} - переключение между закладками приложения (я и раньше эти хоткеи пользовал, но пришлись к столу)
  • Ctrl-Cmd-E - позволяет редактировать идентификатор, на котором установлен текстовый курсор, одновременно со всеми его упоминания в его области видимости (функция, цикл, блок...).
  • Cmd-J - открывает декоративное окошко выбора панели IDE, в которое нужно поместить фокус ввода. В принципе, есть комбинация Cmd-Opt-., которая переключает циклично этот фокус по панелям окна, но про нее почему-то скромно умолчали
  • Мышинный Opt-Click или клавиатурный Cmd-Ctrl-Shift-/ - отобразить всплывающую подсказку по объекту клика. Причем не просто тип, а довольно объемный талмуд 
  • Cmd-Option-[ - переместить текущую строку текста вниз 
  • Cmd-Option-] - переместить текущую строку текста вверх (этих двух я сам нашел - иногда полезно) 
  • Cmd-Shift-O - удобная фича (почти мега-) быстрый поиск идентификатора сквозняком по проекту во всплывающем окошке. После выбора подходящей строки Return открывает соответствующий файл в текущем окне редактора, Opt-Return открывает декоративное окошко, в котором можно выбрать куда поместить файл, Opt-Shift-Return открывает файл во второстепенном редакторе (вертикальное окно рядом с основным).
  • Cmd-Opt-Return - открывает файл объявления идентификатора над текстовом курсором во второстепенном редакторе
  • Cmd-Return - закрывает окно второстепенного редактора.
  • Cmd+Opt+Click (Cmd-Ctrl-Opt-J) - открывает объявление идентификатора в главном редакторе
  • Cmd+Opt+2Click - открывает объявление идентификатора в новом окне. Вообще, двойной клик в Xcode в основном приводит к открытию нового окна
  • Cmd-T - дублирует текущую закладку в новую со всеми текущими настройками
  • Cmd-E - поместить выделенный текст в поле поиска (и в окне редактора, и в окне навигатора проекта). При этом выделенный текст уже считается результатом поиска и можно использовать следующую комбинацию:
  • Cmd-G - перемещаться между результатами поиска в текущем окне
  • Opt-Return в форме поиска в окне редактора - замена в выделенном тексте
  • Двойной клик по скобке выделяет содержимое всего блока внотри пары скобок 
  • Комментарии, предваренные текстом TODO: и FIXME: работают так же, как #pragma mark, то бишь отображаются в списке методов вверху окна редактора
  • При открытом списке этих самых методов можно вводить текст, который будет фильтровать список.
Пара хоткеев от меня - странно, что их не упомянули на сессии:

  • Cmd-Ctrl-D - отобразить словарную карточку слова над текстовым курсором. Имена сущностей должны соответствовать их назначению и писаться орфографически правильно. Фишка эта общекокошная, но и в Xcode ее игнорировать не стоит.
  • Cmd-Ctrl-Down - открыть counterpart (связанный с текущим файл - заголовок или имплементацию)
  • Cmd-Shift-J - отбразить текущий файл в Project Navigator.


    На другом видео рассказывали про навороченность работы Xcode с системами контроля версий - SVN и Git. Работа с репозиториями находится в соответствующем разделе Organizer. Commit, Add и проче команды находятся в меню File/Source Control. Режимы просмотра логов, конфликтов и merging-а переключаются в правом верхнем наборе пиктограмок. Внизу навигатора проекта имеется пиктограммка с хинтом "Show only files with source-control status". Она заставляет навигатор показывать только те файлы, которые каким-то образом отмечены в рабочей версии - A, M, C и т.д. Инструменты для работы с контролем версий довольно стандартны и ничего нового про них рассказать не получится. Но сделаны они с умом. Таймлайн для SVN я первый раз увидел тут. До сих пор видел его только в перфорсе.

    Очень понравился трик, не относящийся, однако, напрямую к Xcode. Это вариант использования Automator. Xcode, как любое Cocoa-приложение работает с ним, как с родным. Точнее, он с Xcode. Записал видюшку с примером.