iOS Prefix.pch лучшие практики - PullRequest
88 голосов
/ 16 мая 2010

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

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

Ответы [ 4 ]

121 голосов
/ 17 мая 2010

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

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

36 голосов
/ 02 октября 2013

Для современных 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 ++.
8 голосов
/ 11 декабря 2010

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

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

6 голосов
/ 01 января 2015

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

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

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

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

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

Если вы беспокоитесь, что включение основного заголовочного файла может привести к Программа, чтобы раздуться, не волнуйтесь. Потому что интерфейсы 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];
...