Saya telah melihat banyak pengembang yang menambahkan berbagai makro kemudahan ke Prefix.pch proyek iOS mereka.
Apa yang (atau tidak) Anda rekomendasikan untuk ditambahkan ke file iOS Prefix.pch? Seperti apa Prefix.pch Anda?
Saya telah melihat banyak pengembang yang menambahkan berbagai makro kemudahan ke Prefix.pch proyek iOS mereka.
Apa yang (atau tidak) Anda rekomendasikan untuk ditambahkan ke file iOS Prefix.pch? Seperti apa Prefix.pch Anda?
Macros.h
, lalu impor file ini ke file prefix.pch
.
Jawaban:
Ewww… jangan letakkan makro dalam file .pch! File .pch, menurut definisi, adalah header khusus proyek yang telah dikompilasi. Ini benar-benar tidak boleh digunakan di luar konteks proyek dan tidak boleh berisi apa pun kecuali #include
s dan#import
s.
Jika Anda memiliki beberapa makro dan yang ingin Anda bagi di antara header, maka tempelkan di file header mereka sendiri - Common.h
atau apa pun - dan #include
itu di awal .pch.
Untuk iOS dan OS X modern, orang harus menggunakan Modul . Ini diaktifkan secara default untuk proyek baru, dan pengimporan / penyertaan dilakukan dengan menggunakan @import
.
Modul memungkinkan kompilator untuk membuat representasi perantara dari konten modul (misalnya header kerangka kerja). Sama seperti PCH, representasi perantara ini dapat dibagikan ke berbagai terjemahan. Tetapi modul mengambil satu langkah lebih jauh karena modul belum tentu spesifik target, dan deklarasinya tidak perlu dilokalkan (ke a *.pch
). Representasi ini dapat menghemat banyak pekerjaan kompilator yang berlebihan.
Dengan menggunakan modul, Anda tidak memerlukan PCH, dan Anda mungkin harus menghapusnya sepenuhnya - mendukung penggunaan @import
lokal ke dependensi. Dalam hal ini, PCH hanya menyelamatkan Anda dari mengetik inklusi lokal ke dependensi (yang tetap harus Anda lakukan IMO).
Sekarang, jika kita melihat kembali ke pertanyaan awal: Anda harus menghindari mengisi PCH Anda dengan segala macam hal acak; Makro, konstanta, #defines
dan semua jenis perpustakaan kecil. Umumnya, Anda harus menghilangkan apa yang sebenarnya tidak diperlukan untuk sebagian besar file sumber Anda . Menempatkan segala macam barang di PCH Anda hanya menambah banyak beban dan ketergantungan. Saya melihat orang-orang meletakkan semua yang mereka tautkan dan lebih banyak lagi ke PCH. Pada kenyataannya, kerangka kerja tambahan biasanya hanya perlu terlihat oleh beberapa terjemahan dalam banyak kasus. Misalnya "Ini barang StoreKit kami - mari impor StoreKit hanya di tempat yang seharusnyaterlihat. Khususnya, 3 terjemahan ini ". Ini membuat waktu build Anda turun, dan membantu Anda melacak dependensi Anda, sehingga Anda dapat menggunakan kembali kode dengan lebih mudah. Jadi dalam proyek ObjC, Anda biasanya berhenti di Foundation. Jika ada banyak UI, maka Anda dapat mempertimbangkan untuk menambahkan UIKit atau AppKit ke PCH Anda. Ini semua dengan asumsi Anda ingin mengoptimalkan waktu build. Salah satu masalah dengan PCH besar yang mencakup (hampir) semuanya adalah menghapus dependensi yang tidak perlu sangat memakan waktu. Sekali Ketergantungan proyek Anda bertambah dan waktu pembangunan Anda meningkat, Anda perlu melawan dengan menghilangkan ketergantungan yang tidak perlu untuk mengurangi waktu pembangunan Anda. Selain itu, segala sesuatu yang sering berubah umumnya harus dijauhkan dari PCH Anda. Perubahan memerlukan pembangunan kembali sepenuhnya. Ada beberapa opsi untuk berbagi PCH. Jika Anda menggunakan PCH,
Sejauh yang saya masukkan ke PCH saya: Saya berhenti menggunakannya untuk sebagian besar target tahun lalu. Biasanya tidak ada cukup kesamaan untuk memenuhi syarat. Ingatlah, saya menulis C ++, ObjC, ObjC ++ dan C - kompilator mengeluarkan satu untuk setiap bahasa dalam target Anda. Jadi mengaktifkannya sering kali menghasilkan waktu kompilasi yang lebih lambat dan I / O yang lebih tinggi. Pada akhirnya, meningkatkan ketergantungan bukanlah cara yang baik untuk melawan ketergantungan dalam proyek yang kompleks. Bekerja dengan banyak bahasa / dialek, ada banyak variasi dalam ketergantungan yang diperlukan untuk target tertentu. Tidak, saya tidak menyarankan itu seoptimal untuk setiap proyek, tetapi itu memberikan beberapa perspektif untuk manajemen ketergantungan dalam proyek yang lebih besar.
Referensi
Catatan
#import "MyLib/MyLib.h"
. Setiap kali file disertakan oleh MyLib.h
perubahan, setiap file sumber dalam aplikasi harus dikompilasi ulang. Jika Anda menggunakan MyLib hanya dalam satu file sumber, maka hanya file itu yang harus dikompilasi ulang saat MyLib berubah. Percaya atau tidak, saya tidak menggunakan file PCH hari ini.
Saya setuju dengan bbum. Pandangan saya tentang file PCH adalah bahwa file tersebut harus berisi cukup banyak saja #include
atau #import
pernyataan. Jadi, jika Anda memiliki banyak makro tingkat tinggi yang bermanfaat, tentukan mereka dalam sesuatu seperti Common.h
dan #import
file itu, seperti yang disarankan bbum.
Saya biasanya melangkah lebih jauh dan menggunakan file PCH untuk #import
sebuah file bernama XXCategories.h
(di mana XX
adalah kelas konvensi penamaan awalan yang Anda gunakan) yang berisi #import
s untuk semua kategori UIKit saya dan kelas Yayasan: NSString+XXAdditions.h
, UIColor+XXAdditons.h
, dll
#import
dan hanya mengimpornya #import
secara langsung? Bukankah itu sama ?, atau apakah itu memengaruhi kinerja apa pun?
#import
dan #include
.
buat file header "macros.h"
impor header ini ke Prefix.pch
Di macro.h ini meletakkan semua framework dan hal penting lainnya.
Jika Anda khawatir tentang kinerja, jangan khawatir, lihat apa yang dikatakan apel:
Header dan Performa
Jika Anda khawatir bahwa menyertakan file header master dapat menyebabkan program Anda membengkak, jangan khawatir. Karena antarmuka OS X diimplementasikan menggunakan kerangka kerja, kode untuk antarmuka tersebut berada di pustaka bersama dinamis dan bukan di file yang dapat dieksekusi. Selain itu, hanya kode yang digunakan oleh program Anda yang pernah dimuat ke dalam memori saat runtime, sehingga jejak dalam memori Anda juga tetap kecil. Adapun memasukkan sejumlah besar file header selama kompilasi, sekali lagi, jangan khawatir. Xcode menyediakan fasilitas header yang telah dikompilasi untuk mempercepat waktu kompilasi. Dengan mengompilasi semua header framework sekaligus, Anda tidak perlu mengompilasi ulang header kecuali Anda menambahkan framework baru. Sementara itu, Anda dapat menggunakan antarmuka apa pun dari kerangka yang disertakan dengan sedikit atau tanpa penalti kinerja.
juga di macros.h saya, saya meletakkan banyak konstanta seperti:
// 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__ )
... untuk menjalankan blok di utas utama:async(^{ self.someLabel.text = @":D"; });