Я видел много разработчиков, которые добавляют различные макросы удобства в Prefix.pch своих проектов iOS.
Что (или нет) вы рекомендуете добавлять в файл iOS Prefix.pch? Как выглядит ваш Prefix.pch?
Я видел много разработчиков, которые добавляют различные макросы удобства в Prefix.pch своих проектов iOS.
Что (или нет) вы рекомендуете добавлять в файл iOS Prefix.pch? Как выглядит ваш Prefix.pch?
Ewww... не ставьте макросы в файл .pch! Файл .pch является, по определению, конкретным проектом с предварительно скомпилированным заголовком. Он действительно не должен использоваться вне контекста проекта, и он действительно не должен содержать ничего, кроме #include
и #import
s.
Если у вас есть макросы и вы хотите делиться между заголовками, тогда вставьте их в собственный файл заголовка - Common.h
или что-то еще - и #include
, что в начале .pch.
Для современных iOS и OS X люди должны использовать Модули. Это включено по умолчанию для новых проектов, а импорт/включение выполняется с помощью @import
.
Модули позволяют компилятору создавать промежуточное представление содержимого модуля (например, заголовков рамок). Подобно PCH, это промежуточное представление может быть разделено между несколькими переводами. Но модули делают это еще на один шаг, потому что модуль не обязательно предназначен для конкретных целей, и их объявления не обязательно должны быть локализованы (до *.pch
). Это представление может сэкономить вам тонкую избыточную работу компилятора.
Используя модули, вам не нужен PCH, и вы, вероятно, должны просто покончить с ними полностью - в пользу использования @import
local для зависимости. В этом случае PCH избавляет вас от ввода включений локально в зависимости (что ИМО вы должны делать в любом случае).
Теперь, если мы оглянемся на исходный вопрос: вы должны избегать заполнения вашего PCH всякими случайными вещами; Макросы, константы, #defines
и всевозможные маленькие библиотеки. Как правило, вы должны опустить то, что действительно не нужно большинству исходных файлов. Ввод всех видов материала в ваш PCH - это просто добавление веса и зависимости. Я вижу, что люди ставят все, что они связывают, и больше в PCH. На самом деле, вспомогательные структуры обычно должны быть видны только для нескольких переводов в большинстве случаев. Например. "Вот наш материал StoreKit - пусть импортирует StoreKit только там, где он должен быть видимым. В частности, эти 3 перевода". Это сокращает время сборки и помогает отслеживать ваши зависимости, чтобы вы могли легче использовать код. Поэтому в проекте ObjC вы обычно останавливаетесь в Фонде. Если есть много пользовательского интерфейса, вы можете подумать о добавлении UIKit или AppKit к вашему PCH. Все это предполагает, что вы хотите оптимизировать время сборки. Одна из проблем с большими PCH, которые включают (почти) все в том, что удаление ненужных зависимостей занимает много времени. Как только ваши зависимости проекта растут, а время сборки увеличивается, вам нужно бороться, устраняя ненужные зависимости, чтобы сократить время сборки. Кроме того, что-либо, что часто меняется, обычно должно быть исключено из вашего PCH. Для изменения требуется полная перестройка. Есть несколько вариантов совместного использования PCH. Если вы используете PCH, старайтесь поддерживать общий доступ.
Насколько я добавил в свой PCH: я прекратил использовать их для подавляющего большинства целей несколько лет назад. Обычно обычно недостаточно, чтобы квалифицироваться. Имейте в виду, я пишу С++, ObjC, ObjС++ и C - компилятор испускает один для каждого lang в вашей цели. Поэтому включение их часто приводило к более медленному времени компиляции и более высоким ввода-выводам. В конечном счете, возрастающая зависимость не является хорошим способом борьбы с зависимостью от сложных проектов. Работая с несколькими языками/диалектами, существует много изменений в зависимостях, необходимых для данной цели. Нет, я бы не советовал, что это оптимально для каждого проекта, но это дает некоторую перспективу управлению зависимостями в крупных проектах.
Ссылки
Примечания
Я согласен с bbum. Я беру файл PCH в том, что он должен содержать довольно много операторов #include
или #import
. Поэтому, если у вас есть куча полезных макросов высокого уровня, определите их в виде Common.h
и #import
этого файла, как предположил bbum.
Я обычно делаю еще один шаг и использую файл PCH для #import
файла с именем XXCategories.h
(где XX
- это соглашение о назначении именования классов, которое вы используете), которое содержит #import
для всех моих классов UIKit и Foundation категорий: NSString+XXAdditions.h
, UIColor+XXAdditons.h
и т.д.
создать файл заголовка "macros.h"
импортировать этот заголовок в Prefix.pch
В этом macros.h помещены все фреймворки и другие важные вещи.
Если вы беспокоитесь о производительности, не волнуйтесь, посмотрите, что говорит яблоко:
Заголовки и производительность
Если вы обеспокоены тем, что включение главного файла заголовка может привести к программа для раздувания, не волнуйтесь. Поскольку интерфейсы OS X реализованы используя фреймворки, код для этих интерфейсов находится в динамическом а не в вашем исполняемом файле. Кроме того, только код используемый вашей программой, всегда загружается в память во время выполнения, поэтому ваш In-Memory след также остается небольшим. Что касается включения большого количества файлов заголовков во время компиляции, еще раз не беспокойтесь. Xcode обеспечивает предварительно скомпилированный чтобы ускорить время компиляции. Скомпилировав все рамочные заголовки сразу, нет необходимости перекомпилировать заголовки если вы не добавите новую структуру. Тем временем вы можете использовать любые интерфейс из встроенных фреймворков с небольшой или отсутствующей производительностью штраф.
также в моих макросах .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];