87

Tôi đã thấy nhiều nhà phát triển thêm các macro tiện lợi khác nhau vào Prefix.pch trong các dự án iOS của họ.

Bạn nên (hoặc không) làm gì để khuyên bạn nên thêm vào tệp Prefix.pch của iOS? Prefix.pch của bạn trông như thế nào?

|
121

Ewww không đặt macro trong tệp .pch! Theo định nghĩa, một tệp .pch là một tiêu đề được biên dịch trước cụ thể của dự án. Nó thực sự không nên được sử dụng ngoài bối cảnh của dự án và nó thực sự không nên chứa bất cứ thứ gì ngoài #includes và #imports.

Nếu bạn có một số macro và như vậy mà bạn muốn chia sẻ giữa tiêu đề, sau đó dính 'em trong một tập tin tiêu đề của riêng mình - Common.hhoặc bất cứ điều gì - và #include rằng vào đầu của .pch.

|
36

Đối với iOS và OS X hiện đại, mọi người nên sử dụng Mô-đun . Điều này được bật theo mặc định cho các dự án mới và việc nhập / đưa vào được thực hiện bằng cách sử dụng @import.

Các mô-đun cho phép trình biên dịch tạo một biểu diễn trung gian của nội dung của mô-đun (ví dụ: các tiêu đề của khung). Giống như PCH, đại diện trung gian này có thể được chia sẻ trên nhiều bản dịch. Nhưng các mô-đun tiến thêm một bước này bởi vì một mô-đun không nhất thiết phải nhắm mục tiêu cụ thể và các khai báo của chúng không cần phải được bản địa hóa (đến a *.pch). Đại diện này có thể giúp bạn tiết kiệm một tấn công việc biên dịch dự phòng.

Sử dụng các mô-đun, bạn không cần PCH và có lẽ bạn chỉ nên loại bỏ chúng hoàn toàn - ủng hộ việc sử dụng @importcục bộ cho phụ thuộc. Trong trường hợp đó, PCH chỉ giúp bạn tiết kiệm từ việc nhập các vùi cục bộ vào các phụ thuộc (mà IMO bạn nên làm bằng mọi cách).

Bây giờ, nếu chúng ta nhìn lại câu hỏi ban đầu: Bạn nên tránh làm đầy PCH của mình với tất cả các loại điều ngẫu nhiên; Macro, hằng, #definesvà tất cả các loại thư viện nhỏ. Nói chung, bạn nên bỏ qua những gì thực sự không cần thiết đối với phần lớn các tệp nguồn của bạn . Đặt tất cả các loại công cụ vào PCH của bạn chỉ là thêm một loạt các trọng lượng và phụ thuộc. Tôi thấy mọi người đặt mọi thứ họ liên kết và nhiều thứ khác vào PCH. Trong thực tế, các khung phụ trợ thường chỉ cần hiển thị với một vài bản dịch trong hầu hết các trường hợp. Ví dụ: "Đây là công cụ StoreKit của chúng tôi - chỉ nhập StoreKit ở nơi phảiđược hiển thị. Cụ thể, 3 bản dịch này ". Điều này giúp giảm thời gian xây dựng của bạn và giúp bạn theo dõi các phụ thuộc của mình, để bạn có thể sử dụng lại mã dễ dàng hơn. Vì vậy, trong một dự án ObjC, bạn thường sẽ dừng lại ở Foundation. Nếu có nhiều về UI, sau đó bạn có thể cân nhắc thêm UIKit hoặc AppKit vào PCH. Đây là tất cả giả định bạn muốn tối ưu hóa thời gian xây dựng. Một trong những vấn đề với PCH lớn bao gồm (gần) mọi thứ là việc loại bỏ các phụ thuộc không cần thiết rất tốn thời gian. Sự phụ thuộc của dự án của bạn tăng lên và thời gian xây dựng của bạn tăng lên, bạn cần phải chống lại bằng cách loại bỏ các phụ thuộc không cần thiết để giảm thời gian xây dựng của bạn. Ngoài ra, bất kỳ thay đổi nào thường phải được loại bỏ khỏi PCH của bạn. Có một số tùy chọn để chia sẻ PCH. Nếu bạn sử dụng PCH,

Theo như những gì tôi đưa vào PCH của mình: Tôi đã ngừng sử dụng chúng cho phần lớn các mục tiêu từ nhiều năm trước. Thường thì không đủ điểm chung để đủ điều kiện. Hãy nhớ rằng, tôi viết C ++, ObjC, ObjC ++ và C - trình biên dịch phát ra một cho mỗi lang trong mục tiêu của bạn. Vì vậy, cho phép chúng thường dẫn đến thời gian biên dịch chậm hơn và I / O cao hơn. Cuối cùng, tăng sự phụ thuộc không phải là một cách tốt để chống lại sự phụ thuộc trong các dự án phức tạp. Làm việc với nhiều ngôn ngữ / phương ngữ, có nhiều biến thể trong các phụ thuộc cần thiết cho một mục tiêu nhất định. Không, tôi sẽ không khuyên rằng tối ưu cho mọi dự án, nhưng điều đó mang lại một số quan điểm cho quản lý phụ thuộc trong các dự án lớn hơn.


Tài liệu tham khảo


Ghi chú

  • Câu hỏi này ban đầu được hỏi vài năm trước khi giới thiệu Mô-đun.
  • Hiện tại (Xcode 5.0), các mô-đun hoạt động cho C và ObjC, nhưng không phải C ++.
|
  • 1

    Điều đó có nghĩa là gì khi xây dựng lại hoàn toàn cho một dự án kích hoạt mô-đun. Bạn biết tiêu đề bắc cầu -Swift.h mới này chắc chắn không phải là một ứng cử viên phù hợp cho một .pch. Nhưng tôi đã thấy mọi người làm điều đó. Vì vậy, như bạn có thể thấy nếu ai đó làm điều đó. Chúng tôi có một tiêu đề luôn thay đổi trong .pch. Vì vậy, nó xây dựng lại mọi thứ trong tệp .pch mỗi khi -Swift.h được tạo lại. Bạn có đồng ý với điều này? Bạn có nhiều đầu vào?

    – Tạ Lan Vy 08:54:16 03/12/2016
  • 1

    @MadNik Giả sử PCH của ứng dụng của bạn bao gồm tiêu đề chính của thư viện / khung mà bạn đang tích cực phát triển. Ví dụ : #import "MyLib/MyLib.h". Bất cứ khi nào một tệp được bao gồm bởi các MyLib.hthay đổi, mọi tệp nguồn trong ứng dụng phải được biên dịch lại. Nếu bạn sử dụng MyLib chỉ trong một tệp nguồn, thì chỉ tệp đó phải được biên dịch lại khi MyLib thay đổi. Tin hay không, tôi không sử dụng bất kỳ tệp PCH nào trong những ngày này.

    – Hương Nguyễnn 06:30:59 13/12/2016
8

Tôi đồng ý với bbum. Tôi coi tập tin PCH là nó chỉ chứa khá nhiều câu lệnh #includehoặc #importcâu lệnh. Vì vậy, nếu bạn có một loạt các macro cấp cao, hữu ích, hãy xác định chúng trong một cái gì đó giống như Common.h#importtệp đó, như bbum đề xuất.

Tôi thường đi một bước xa hơn và sử dụng các tập tin PCH đến #importmột tập tin gọi là XXCategories.h(nơi XXlà quy ước đặt tên lớp tiền tố bạn sử dụng) có chứa #imports cho tất cả UIKit tôi và loại lớp Foundation: NSString+XXAdditions.h, UIColor+XXAdditons.hvv

|
  • 1

    Tôi chỉ tò mò thôi. Trong tệp .PCH, sự khác biệt giữa việc nhập Common.h có khác nhau #importvà chỉ nhập #importtrực tiếp? Những cái đó có giống nhau không?, Hay nó có ảnh hưởng đến hiệu suất nào không?

    – Tạ Lan Vy 09:57:56 04/04/2012
  • 1

    Theo hiểu biết của tôi, không có sự khác biệt thực sự. Đó là nhiều hơn một thực hành tốt nhất, tôi đoán. Thay vì đẩy một loạt các macro và những thứ khác vào tệp PCH của bạn, nó chỉ nên dành cho #import#include.

    – Hương Nguyễnn 17:54:17 04/04/2012
  • 1

    Sự khác biệt là khả năng sử dụng lại. PCH là dự án cụ thể. Common.h sẽ là phổ biến cho nhiều dự án. Nó giống như hỏi tại sao bạn không đặt tất cả các lớp tiện dụng của bạn vào dự án của bạn thay vì tạo một dự án phụ mà bạn có thể sử dụng lại. Mặc dù là một ví dụ giả định, bởi vì nó chỉ là một bản sao chép đơn giản ... nhưng bản sao dán là nghịch ngợm.

    – Ngô Việt Hương 10:34:08 20/06/2013
6

tạo một tệp tiêu đề "macros.h"

nhập tiêu đề này vào Prefix.pch

Trong macros.h này đặt tất cả các khung và những thứ quan trọng khác.

Nếu bạn lo lắng về hiệu suất, đừng lo lắng, hãy xem apple nói gì:

Tiêu đề và hiệu suất

Nếu bạn lo lắng rằng việc bao gồm tệp tiêu đề chính có thể khiến chương trình của bạn bị phồng lên, đừng lo lắng. Vì các giao diện OS X được triển khai bằng các khung công tác, mã cho các giao diện đó nằm trong thư viện chia sẻ động chứ không phải trong tệp thực thi của bạn. Ngoài ra, chỉ có mã được sử dụng bởi chương trình của bạn được tải vào bộ nhớ khi chạy, do đó, dấu chân trong bộ nhớ của bạn tương tự ở mức nhỏ. Đối với việc bao gồm một số lượng lớn các tệp tiêu đề trong quá trình biên dịch, một lần nữa, đừng lo lắng. Xcode cung cấp một tiện ích tiêu đề được biên dịch sẵn để tăng tốc thời gian biên dịch. Bằng cách biên dịch tất cả các tiêu đề khung cùng một lúc, không cần phải biên dịch lại các tiêu đề trừ khi bạn thêm một khung công tác mới. Trong khi đó, bạn có thể sử dụng bất kỳ giao diện nào từ các khung được bao gồm với rất ít hoặc không có hình phạt hiệu suất.

cũng trong macro của tôi. Tôi đặt rất nhiều hằng số như:

// 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];
|
  • 1

    Một cách hữu ích khác ở đây: #define async(...) dispatch_async(dispatch_get_main_queue(), __VA_ARGS__ )... để chạy các khối trên luồng chính:async(^{ self.someLabel.text = @":D"; });

    – Tạ Lan Vy 15:42:02 30/03/2016

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.