Я бачив багато розробників, які додають різні макроси зручності до Prefix.pch своїх проектів iOS.
Що (або ні) ви рекомендуєте додавати до файлу iOS Prefix.pch? Як виглядає ваш Prefix.pch?
Я бачив багато розробників, які додають різні макроси зручності до Prefix.pch своїх проектів iOS.
Що (або ні) ви рекомендуєте додавати до файлу iOS Prefix.pch? Як виглядає ваш Prefix.pch?
Macros.h
, а потім імпортуйте цей файл у свій prefix.pch
.
Відповіді:
Ewww ... не вкладайте макроси у файл .pch! Файл .pch, за визначенням, є попередньо скомпільованим заголовком проекту. Його справді не слід використовувати поза контекстом проекту, і він насправді не повинен містити нічого, крім #include
s та #import
s.
Якщо у вас є деякі макроси та такі, якими ви хочете поділитися між заголовками, то вставте їх у власний файл заголовка - Common.h
або що завгодно - і #include
це на початку .pch.
Для сучасних iOS та OS X люди повинні використовувати модулі . Це ввімкнено за замовчуванням для нових проектів, а імпорт / включення здійснюється за допомогою @import
.
Модулі дозволяють компілятору створювати проміжне представлення вмісту модуля (наприклад, заголовки фреймворку). Як і PCH, це проміжне подання може бути спільним для кількох перекладів. Але модулі роблять цей крок далі, оскільки модуль не обов'язково є цільовим, і їх оголошення не потрібно локалізувати (до a *.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 - компілятор видає по одному для кожного lang у вашій цілі. Тому їх увімкнення часто призводило до повільнішого часу компіляції та вищих входів / виходів. Зрештою, збільшення залежності не є хорошим способом боротьби із залежністю в складних проектах. Працюючи з кількома мовами / діалектами, існує значна різниця в залежностях, необхідних для даної мети. Ні, я б не радив, щоб це було оптимально для кожного проекту, але це дає певну перспективу для управління залежністю у великих проектах.
Список літератури
Примітки
#import "MyLib/MyLib.h"
. Щоразу, коли файл, включений до MyLib.h
змін, кожен вихідний файл у програмі повинен бути перекомпільований. Якщо ви використовуєте MyLib лише в одному вихідному файлі, тоді лише цей файл повинен бути перекомпільований, коли MyLib змінюється. Вірте чи ні, але сьогодні я не використовую жодних файлів PCH.
Я згоден з bbum. Мій погляд на файл PCH є те , що він повинен містити в значній мірі тільки #include
або #import
заяви. Так що якщо у вас є купа корисних макросів, високого рівня, визначити їх у чому - то начебто Common.h
і #import
цей файл, як це було запропоновано bbum.
Я зазвичай йду на крок далі і використовувати файл PCH в #import
файл з ім'ям XXCategories.h
(де XX
є клас імена префікс конвенція використовується) , який містить #import
S для всіх моїх UIKit і класу Foundation категорій: NSString+XXAdditions.h
, UIColor+XXAdditons.h
і т.д.
#import
і просто імпортом #import
безпосередньо? Чи не будуть вони однаковими ?, чи це впливає на якісь результати?
#import
та #include
.
створити файл заголовка "macros.h"
імпортуйте цей заголовок у Prefix.pch
У цьому macros.h поміщені всі рамки та інші важливі речі.
Якщо вас турбує продуктивність, не хвилюйтеся, подивіться, що говорить яблуко:
Заголовки та продуктивність
Якщо ви переживаєте, що включення головного файлу заголовка може спричинити здуття програми, не хвилюйтеся. Оскільки інтерфейси OS X реалізовані за допомогою фреймворків, код цих інтерфейсів знаходиться в динамічній спільній бібліотеці, а не у вашому виконуваному файлі. Крім того, лише код, який використовує ваша програма, коли-небудь завантажується в пам’ять під час виконання, тому розмір пам’яті в пам'яті залишається невеликим. Що стосується включення великої кількості файлів заголовків під час компіляції, ще раз, не хвилюйтеся. 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];
#define async(...) dispatch_async(dispatch_get_main_queue(), __VA_ARGS__ )
... для запуску блоків в основному потоці:async(^{ self.someLabel.text = @":D"; });