iOS Prefix.pch лучшие практики

Я видел много разработчиков, которые добавляли различные удобные макросы в Prefix.pch своих проектов iOS.

Что (или нет) вы рекомендуете добавить в файл iOS Prefix.pch? Как выглядит ваш Prefix.pch?

4 ответа

Решение

Ewww... не помещайте макросы в файл.pch! Файл.pch по определению является прекомпилированным заголовком конкретного проекта. Он действительно не должен использоваться вне контекста проекта, и он не должен содержать ничего, кроме #includeс и #imports.

Если у вас есть какие-то макросы и такие, которые вы хотите разделить между заголовками, вставьте их в собственный файл заголовка - Common.h или что угодно - и #include что в начале.пч.

Для современных iOS и OS X люди должны использовать Модули. Это включено по умолчанию для новых проектов, а импорт / включение выполняется с помощью @import,

Модули позволяют компилятору создавать промежуточное представление содержимого модуля (например, заголовки фреймворка). Как и PCH, это промежуточное представление может быть общим для нескольких переводов. Но модули делают этот шаг еще дальше, потому что модуль не обязательно ориентирован на конкретную цель, и их объявления не должны быть локализованы (для *.pch). Это представление может сэкономить вам массу работы компилятора.

При использовании модулей вам не нужен PCH, и вам, вероятно, следует просто полностью отказаться от них - в пользу использования @import локальный для зависимости. В этом случае PCH только спасает вас от ввода включений, локальных для зависимостей (какой IMO вы должны делать в любом случае).

Теперь, если мы вернемся к первоначальному вопросу: вам следует избегать наполнения вашего PCH всевозможными случайными вещами; Макросы, константы, #definesи всякие маленькие библиотеки. Как правило, вы должны пропустить то, что действительно не нужно для большинства ваших исходных файлов. Помещение всевозможных вещей в ваш PCH - это просто добавление веса и зависимости. Я вижу, что люди помещают все, что они связывают и больше в PCH. В действительности, вспомогательные структуры обычно должны быть видны только нескольким переводам в большинстве случаев. Например, "Вот наш материал StoreKit - давайте импортировать StoreKit только там, где он должен быть виден. В частности, эти 3 перевода". Это сокращает время сборки и помогает отслеживать ваши зависимости, чтобы вам было проще повторно использовать код. Так что в проекте ObjC вы обычно останавливаетесь в Foundation. Если пользовательского интерфейса много, вы можете добавить UIKit или AppKit к своему PCH. Это все при условии, что вы хотите оптимизировать время сборки. Одна из проблем с большими PCH, которые включают (почти) все, состоит в том, что удаление ненужных зависимостей занимает очень много времени. Как только зависимости вашего проекта растут, а время сборки увеличивается, вам нужно дать отпор, удалив ненужные зависимости, чтобы сократить время сборки. Кроме того, все, что часто меняется, следует избегать вашего PCH. Изменение требует полной перестройки. Есть несколько вариантов обмена PCH. Если вы используете PCH, постарайтесь поддержать обмен.

Что касается того, что я положил в свой PCH: я перестал использовать их для подавляющего большинства целей много лет назад. Там просто обычно не хватает общего, чтобы претендовать. Имейте в виду, я пишу C++, ObjC, ObjC++ и C - компилятор генерирует один для каждого языка в вашей цели. Поэтому их включение часто приводило к снижению времени компиляции и увеличению числа операций ввода-вывода. В конечном счете, рост зависимости не является хорошим способом борьбы с зависимостью в сложных проектах. Работая с несколькими языками / диалектами, существует много различий в зависимостях, необходимых для данной цели. Нет, я бы не советовал это как оптимальное для каждого проекта, но это дает некоторую перспективу управления зависимостями в более крупных проектах.


Рекомендации


Заметки

  • Этот вопрос изначально задавался за несколько лет до введения модулей.
  • В настоящее время (Xcode 5.0) модули работают на C и ObjC, но не на C++.

Я согласен с Bbum. Я считаю, что файл PCH должен содержать только #include или же #import заявления. Поэтому, если у вас есть несколько полезных макросов высокого уровня, определите их как Common.h а также #import этот файл, как предложил bbum.

Я обычно иду дальше и использую файл PCH, чтобы #import файл называется XXCategories.h (где XX это соглашение о префиксе именования классов, которое вы используете), которое содержит #imports для всех моих категорий классов UIKit и Foundation: NSString+XXAdditions.h, UIColor+XXAdditons.h, так далее.

Создать заголовочный файл "macros.h"

импортировать этот заголовок в Prefix.pch

В этот macros.h помещены все фреймворки и другие важные вещи.

Если вы беспокоитесь о производительности, не беспокойтесь, посмотрите, что говорит Apple:

Заголовки и производительность

Если вы беспокоитесь о том, что включение основного заголовочного файла может привести к расширению вашей программы, не беспокойтесь. Поскольку интерфейсы OS X реализованы с использованием каркасов, код для этих интерфейсов находится в динамической общей библиотеке, а не в вашем исполняемом файле. Кроме того, только код, используемый вашей программой, загружается в память во время выполнения, поэтому ваш объем памяти в памяти также остается небольшим. Что касается включения большого количества заголовочных файлов во время компиляции, еще раз, не беспокойтесь. Xcode предоставляет предварительно скомпилированный заголовок для ускорения времени компиляции. Скомпилируя все заголовки фреймворка одновременно, нет необходимости перекомпилировать заголовки, если вы не добавите новый фреймворк. В то же время, вы можете использовать любой интерфейс из включенных фреймворков практически без потери производительности.

также в моем macros.h я поместил много констант, таких как:

// delegate
#define UIAppDelegate (AppDelegate *)[[UIApplication sharedApplication] delegate]
#define APPDELEGATE   ((AppDelegate *)[[UIApplication sharedApplication] delegate])

// system
#define IS_IPHONE_4INCH (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height==568)
#define IS_IPAD                     (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)

// screen size
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)
#define IS_RETINA_DISPLAY ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
#define IS_PORTRAIT                 UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])
#define IS_LANDSCAPE                UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])

//system version
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)

// math
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))

// cores
#define RGB(r,g,b)    [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define RGBA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]
#define MAKECOLOR(R, G, B, A) [UIColor colorWithRed:((float)R/255.0f) green:((float)G/255.0f) blue:((float)B/255.0f) alpha:A]
#define MAKECOLORFROMHEX(hexValue) [UIColor colorWithRed: ((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]



//customizations
#define SHOW_STATUS_BAR               [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
#define HIDE_STATUS_BAR               [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

#define SHOW_NAVIGATION_BAR           [self.navigationController setNavigationBarHidden:FALSE];
#define HIDE_NAVIGATION_BAR           [self.navigationController setNavigationBarHidden:TRUE];

#define VC_OBJ(x) [[x alloc] init]
#define VC_OBJ_WITH_NIB(x) [[x alloc] initWithNibName : (NSString *)CFSTR(#x) bundle : nil]

#define RESIGN_KEYBOARD [[[UIApplication sharedApplication] keyWindow] endEditing:YES];

#define CLEAR_NOTIFICATION_BADGE                       [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
#define REGISTER_APPLICATION_FOR_NOTIFICATION_SERVICE  [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]

#define HIDE_NETWORK_ACTIVITY_INDICATOR                 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
#define SHOW_NETWORK_ACTIVITY_INDICATOR                 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
Другие вопросы по тегам