ฉันเคยเห็นนักพัฒนาหลายคนที่เพิ่มมาโครอำนวยความสะดวกต่างๆให้กับ 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
ถ้าคุณมีแมโครบางและเช่นว่าคุณต้องการที่จะใช้ร่วมกันระหว่างส่วนหัวแล้วติด 'em ในไฟล์ส่วนหัวของตัวเอง - Common.h
หรืออะไรก็ตาม - และ#include
ที่จุดเริ่มต้นของ .pch ที่
สำหรับ iOS ที่ทันสมัยและ OS X คนควรจะใช้โมดูล นี้จะเปิดใช้งานโดยเริ่มต้นสำหรับโครงการใหม่และนำเข้า / @import
รวมสามารถทำได้โดยใช้
โมดูลอนุญาตให้คอมไพเลอร์สร้างการแสดงเนื้อหาของโมดูลในระดับกลาง (เช่นส่วนหัวของเฟรมเวิร์ก) เช่นเดียวกับ PCH การเป็นตัวแทนระดับกลางนี้อาจใช้ร่วมกันในการแปลหลาย ๆ แต่โมดูลจะก้าวไปอีกขั้นเพราะโมดูลไม่จำเป็นต้องกำหนดเป้าหมายเฉพาะและการประกาศไม่จำเป็นต้องแปลเป็นภาษาท้องถิ่น (ถึง a *.pch
) การเป็นตัวแทนนี้สามารถช่วยคุณประหยัดงานคอมไพเลอร์ที่ซ้ำซ้อนได้
การใช้โมดูลคุณไม่จำเป็นต้องมี PCH และคุณอาจจะต้องกำจัดมันออกไปทั้งหมด - เพื่อเป็นการสนับสนุนการใช้@import
Local เพื่อการพึ่งพา ในกรณีนี้ PCH จะช่วยให้คุณไม่ต้องพิมพ์การรวมในเครื่องไปยังการอ้างอิง (ซึ่ง IMO ที่คุณควรทำต่อไป)
ตอนนี้หากเรามองย้อนกลับไปที่คำถามเดิม: คุณควรหลีกเลี่ยงการเติม PCH ของคุณด้วยสิ่งสุ่มทุกประเภท มาโครค่าคงที่#defines
และไลบรารีเล็ก ๆ ทุกประเภท โดยทั่วไปแล้วคุณควรละเว้นสิ่งที่เป็นจริงไม่จำเป็นส่วนใหญ่ของไฟล์ที่มาของคุณ การใส่สิ่งของทุกประเภทลงใน PCH ของคุณเป็นเพียงการเพิ่มน้ำหนักและการพึ่งพา ฉันเห็นผู้คนใส่ทุกสิ่งที่พวกเขาเชื่อมโยงและอื่น ๆ ในปชช. ในความเป็นจริงเฟรมเวิร์กเสริมมักจะต้องมองเห็นได้ในการแปลบางส่วนเท่านั้นในกรณีส่วนใหญ่ เช่น "นี่คือข้อมูล StoreKit ของเรา - มานำเข้า StoreKit เฉพาะที่ที่ต้องใช้เท่านั้นมองเห็นได้ โดยเฉพาะอย่างยิ่งการแปลทั้ง 3 นี้ "ซึ่งจะช่วยลดเวลาในการสร้างของคุณและช่วยให้คุณติดตามการอ้างอิงของคุณเพื่อให้คุณสามารถใช้โค้ดซ้ำได้ง่ายขึ้นดังนั้นในโครงการ ObjC คุณมักจะหยุดที่ Foundation หากมีจำนวนมาก ของ UI จากนั้นคุณอาจพิจารณาเพิ่ม UIKit หรือ AppKit ใน PCH ของคุณทั้งหมดนี้สมมติว่าคุณต้องการเพิ่มประสิทธิภาพเวลาในการสร้างปัญหาอย่างหนึ่งของ PCH ขนาดใหญ่ที่รวมทุกอย่าง (เกือบ) ทุกอย่างคือการลบการอ้างอิงที่ไม่จำเป็นออกไปนั้นใช้เวลานานมากครั้งเดียว การอ้างอิงของโปรเจ็กต์ของคุณเพิ่มขึ้นและเวลาในการสร้างของคุณเพิ่มขึ้นคุณต้องต่อสู้กลับโดยการกำจัดการพึ่งพาที่ไม่จำเป็นเพื่อลดเวลาในการสร้างของคุณนอกจากนี้สิ่งที่เปลี่ยนแปลงมักจะถูกเก็บไว้ให้พ้นจาก PCH ของคุณการเปลี่ยนแปลงต้องการการสร้างใหม่ทั้งหมด มีตัวเลือกบางอย่างในการแบ่งปัน PCH หากคุณใช้ PCHs
เท่าที่ฉันใส่ไว้ใน PCH: ฉันหยุดใช้มันสำหรับเป้าหมายส่วนใหญ่เมื่อหลายปีก่อน มักจะมีไม่เพียงพอที่จะมีคุณสมบัติเหมือนกัน จำไว้ว่าฉันเขียน C ++, ObjC, ObjC ++ และ C - คอมไพเลอร์จะปล่อยหนึ่งสำหรับแต่ละ lang ในเป้าหมายของคุณ ดังนั้นการเปิดใช้งานจึงมักส่งผลให้เวลาคอมไพล์ช้าลงและ I / O สูงขึ้น ท้ายที่สุดแล้วการเพิ่มการพึ่งพาไม่ใช่วิธีที่ดีในการต่อสู้กับการพึ่งพาในโครงการที่ซับซ้อน การทำงานกับหลายภาษา / ภาษาถิ่นมีการเปลี่ยนแปลงมากมายในการอ้างอิงที่จำเป็นสำหรับเป้าหมายที่กำหนด ไม่ฉันจะไม่แนะนำว่าเหมาะสมที่สุดสำหรับทุกโครงการ แต่นั่นจะให้มุมมองบางประการเกี่ยวกับการจัดการการพึ่งพาในโครงการขนาดใหญ่
อ้างอิง
หมายเหตุ
#import "MyLib/MyLib.h"
. ทุกครั้งที่มีMyLib.h
การเปลี่ยนแปลงไฟล์ต้นฉบับทุกไฟล์ในแอปจะต้องคอมไพล์ใหม่ หากคุณใช้ MyLib ในไฟล์ต้นฉบับเพียงไฟล์เดียวจะต้องคอมไพล์ไฟล์นั้นใหม่เมื่อ MyLib เปลี่ยนแปลง เชื่อหรือไม่ว่าทุกวันนี้ฉันไม่ได้ใช้ไฟล์ PCH เลย
ฉันเห็นด้วยกับ bbum สิ่งที่ฉันใช้กับไฟล์ PCH คือมันควรมีเฉพาะ#include
หรือ#import
คำสั่งเท่านั้น ดังนั้นหากคุณมีมาโครระดับสูงที่เป็นประโยชน์จำนวนมากให้กำหนดมันในสิ่งที่ชอบCommon.h
และ#import
ไฟล์นั้นตามที่ bbum แนะนำ
ฉันมักจะไปขั้นตอนต่อไปและใช้แฟ้ม PCH เพื่อ#import
ไฟล์ที่เรียกว่าXXCategories.h
(ในกรณีที่XX
เป็นชั้นตั้งชื่อการประชุมคำนำหน้าคุณใช้) ที่มี#import
สำหรับทุก UIKit และชั้นมูลนิธิของฉันประเภทNSString+XXAdditions.h
, UIColor+XXAdditons.h
ฯลฯ
#import
และนำเข้า#import
โดยตรงคืออะไร สิ่งเหล่านี้จะไม่เหมือนกันหรือไม่หรือมีผลต่อประสิทธิภาพการทำงานหรือไม่?
#import
และ#include
.
สร้างไฟล์ส่วนหัว "macros.h"
นำเข้าส่วนหัวนี้ไปยัง Prefix.pch
ใน macros.h นี้ใส่กรอบและสิ่งสำคัญอื่น ๆ ทั้งหมด
หากคุณกังวลเกี่ยวกับประสิทธิภาพไม่ต้องกังวลดูสิ่งที่ Apple พูด:
ส่วนหัวและประสิทธิภาพ
หากคุณกังวลว่าการรวมไฟล์ส่วนหัวหลักอาจทำให้โปรแกรมของคุณขยายตัวไม่ต้องกังวล เนื่องจากอินเทอร์เฟซ OS X ถูกนำไปใช้โดยใช้เฟรมเวิร์กโค้ดสำหรับอินเทอร์เฟซเหล่านั้นจึงอยู่ในไลบรารีที่แบ่งใช้แบบไดนามิกและไม่อยู่ในไฟล์ปฏิบัติการ นอกจากนี้รหัสที่ใช้โดยโปรแกรมของคุณเท่านั้นที่เคยโหลดลงในหน่วยความจำขณะรันไทม์ดังนั้นรอยในหน่วยความจำของคุณจึงมีขนาดเล็กเช่นเดียวกัน สำหรับการรวมไฟล์ส่วนหัวจำนวนมากในระหว่างการคอมไพล์อีกครั้งไม่ต้องกังวล Xcode มีสิ่งอำนวยความสะดวกส่วนหัวที่คอมไพล์ไว้ล่วงหน้าเพื่อเร่งเวลาในการคอมไพล์ การรวบรวมส่วนหัวของกรอบงานทั้งหมดในครั้งเดียวไม่จำเป็นต้องคอมไพล์ส่วนหัวใหม่เว้นแต่คุณจะเพิ่มกรอบงานใหม่ ในระหว่างนี้คุณสามารถใช้อินเทอร์เฟซใดก็ได้จากเฟรมเวิร์กที่ให้มาโดยมีโทษประสิทธิภาพเพียงเล็กน้อยหรือไม่มีเลย
ในมาโครของฉันด้วยฉันใส่ค่าคงที่จำนวนมากเช่น:
// 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"; });