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

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, указывающий на первый символ последовательности и на длину самой последовательности. Дальнейшее оперирование производится как с обычными символами.

3 нояб. 2015 г.

Оповещение снятия скришота с экрана приложения в iOS

Наткнулся на оповещение UIApplicationUserDidTakeScreenshotNotification, которое приходит от NSNotificationCenter когда пользователь нажал кнопку Home + Power. Приходит оповещение постфактум, но это и логично — чтобы приложение не могло запретить пользователю делать скриншоты. Ютуб бы этим очень стал пользоваться.

1
2
3
4
5
6
7
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
                                                  object:nil
                                                   queue:mainQueue
                                              usingBlock:^(NSNotification *note) {
                                                 // executes after screenshot
                                              }];

Android предлагает похожее решение:


1
NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenshotTook);

10 нояб. 2013 г.

Однострочники: Макрос получения локализированных строк

Простой Objective-C-макрос для получения строковых ресурсов в зависимости от дефолтной локали
#define LOC(__key__) [[NSBundle mainBundle] localizedStringForKey:(__key__) value:nil table:nil] 

17 мар. 2013 г.

Objective-C: однострочник для логгирования CGRect

Периодически приходится выводить в лог размер и положение какого-то контрола. Может даже двух. А то и вовсе трех. Сваял вот такой макрос для более удобного логгирования. Кстати, подумалось, что из-за используемого #x этот макрос сложно реализовать в виде функции. Обработка передаваемого параметра как строки, насколько я знаю, фишка именно препроцессора C/C++ сотоварищи.

#define LOGRect(x) NSLog(@"Logging Rect %s: %@", (#x), NSStringFromCGRect(x))

29 окт. 2012 г.

Objective-C. Макрос-оболочка к NSLog

Последнее время использую такой макрос, оборачивающий штатный NSLog в Objective-C:
#ifndef DLog
#ifdef DEBUG
#define DLog(_format_, ...) NSLog([NSString stringWithFormat:@"%s: %@", __PRETTY_FUNCTION__, (_format_)], ## __VA_ARGS__)
#else
#define DLog(_format_, ...)
#endif
#endif
Он автоматом добавляет к строке лога имя функции и номер строки в исходнике. Ну и заодно можно отключить логи одним андефайном. Заменить, например #ifdef DEBUG на #ifdef DEBUG1

UPD 2015-01-07:
Макрос постепенно перерос вот в такое:

#ifdef DEBUG
#define DLog( s, ... ) NSLog( @"%@%s:(%d)> %@", [[self class] description], __PRETTY_FUNCTION__ , __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__);
#define DLogv( var ) NSLog( @"%@%s:(%d)> "# var "=%@", [[self class] description], __PRETTY_FUNCTION__ , __LINE__, var ] )
#elif DEBUG_PROD
#define DLog( s, ... ) NSLog( @"%@%s:(%d)> %@", [[self class] description], __PRETTY_FUNCTION__ , __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define DLogv( var ) NSLog( @"%@%s:(%d)> "# var "=%@", [[self class] description], __PRETTY_FUNCTION__ , __LINE__, var ] )
#define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__);
#else
#define DLog( s, ... )
#define DAssert(...)
#define DLogv(...)
#endif
Интересно отметить: наткнулся в сети на вопрос почему именно _DLog_, а не, скажем, ALog, MLog?.. Оказывается, что в используемых на данный момент в Xcode фреймворках нет классов, начинающихся с DL. Потому это относительно безопасный префикс для избежания перекрытия классов.

12 февр. 2012 г.

iOS. Objective-C. Удаление содержимого вьюшки

Однострочник для удаления всех дочерних представлений (view) из родительского.

[[parentView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];