iOS के उपसर्ग। सबसे अच्छा अभ्यास


90

मैंने कई डेवलपर्स को देखा है जो अपने iOS प्रोजेक्ट्स के Prefix.pch में विभिन्न सुविधा मैक्रो जोड़ते हैं।

आप iOS Prefix.pch फ़ाइल में जोड़ने की क्या सलाह देते हैं (या नहीं)? आपका Prefix.pch कैसा दिखता है?


इस विषय पर एक विस्तृत ब्लॉग पोस्ट: cimgf.com/2010/05/02/my-current-prefix-pch-file
hpique

2
उदाहरण के लिए Macros.h, अपने मैक्रोज़ को हेडर फ़ाइल में रखें , और फिर इस फ़ाइल को अपने में आयात करें prefix.pch
मल्लोक

मैं भी एक ही मुद्दे का सामना कर रहा हूँ ... Xcode 6.1 में कैसे हल किया जाए
यलमंडाराओ

जवाबों:


121

Ewww… .pch फ़ाइल में मैक्रोज़ न डालें! .Pch फ़ाइल, परिभाषा के अनुसार, एक परियोजना विशिष्ट पूर्वनिर्धारित हेडर है। यह वास्तव में परियोजना के संदर्भ से परे इस्तेमाल नहीं किया जाना चाहिए और इसमें वास्तव में कुछ भी नहीं होना चाहिए लेकिन #includeएस और #importएस।

यदि आपके पास कुछ मैक्रोज़ हैं और आप हेडर के बीच साझा करना चाहते हैं, तो उन्हें अपने स्वयं के हेडर फ़ाइल में चिपकाएँ - Common.hया जो कुछ भी है - और #include जो कि .pch की शुरुआत में है।


आप उस Common.h में क्या शामिल करेंगे?
hpique

4
कुछ भी तो नहीं; मैं केवल विभिन्न #defines डाल सकता हूँ, आदि ... इसमें।
बीबीम

37

आधुनिक आईओएस और ओएस एक्स के लिए, लोगों को मॉड्यूल का उपयोग करना चाहिए । यह नई परियोजनाओं के लिए डिफ़ॉल्ट रूप से सक्षम है, और आयात / शामिल करने का उपयोग करके पूरा किया जाता है @import

मॉड्यूल एक मॉड्यूल की सामग्री का एक मध्यवर्ती प्रतिनिधित्व (उदाहरण के लिए एक रूपरेखा के हेडर) बनाने के लिए संकलक की अनुमति देता है। एक PCH की तरह, इस मध्यवर्ती प्रतिनिधित्व को कई अनुवादों में साझा किया जा सकता है। लेकिन मॉड्यूल इसे एक कदम आगे ले जाते हैं क्योंकि एक मॉड्यूल आवश्यक रूप से विशिष्ट लक्ष्य नहीं है, और उनकी घोषणाओं को स्थानीयकृत (ए *.pch) करने की आवश्यकता नहीं है । यह प्रतिनिधित्व आपको एक टन निरर्थक संकलक कार्य बचा सकता है।

मॉड्यूल का उपयोग करना, आपको पीसीएच की आवश्यकता नहीं है, और आपको शायद पूरी तरह से उनके साथ दूर करना चाहिए - @importनिर्भरता के लिए स्थानीय का उपयोग करने के पक्ष में । उस स्थिति में, एक PCH केवल निर्भरता के लिए स्थानीय (जो आपको IMO वैसे भी होना चाहिए) समावेशी टाइपिंग से बचा रहा है।

अब, यदि हम मूल प्रश्न पर पीछे मुड़कर देखते हैं: आपको अपने पीसीएच को सभी प्रकार की यादृच्छिक चीजों से भरने से बचना चाहिए; मैक्रों, स्थिरांक, #definesऔर छोटे पुस्तकालयों के सभी प्रकार। आम तौर पर, आपको अपने स्रोत फ़ाइलों के बहुमत के लिए वास्तव में अनावश्यक है , इसे छोड़ देना चाहिए । अपने पीसीएच में सभी प्रकार के सामान डालना सिर्फ वजन और निर्भरता का एक गुच्छा जोड़ रहा है। मैं देखता हूं कि लोग पीसीएच में सब कुछ लिंक करते हैं और बहुत कुछ करते हैं। वास्तव में, सहायक ढांचे को आमतौर पर केवल ज्यादातर मामलों में कुछ अनुवादों के लिए दिखाई देने की आवश्यकता होती है। जैसे “यहाँ हमारा StoreKit सामान है - चलिए StoreKit को केवल वहीं आयात करें जहाँ यह होना चाहिएदिखाई देना। विशेष रूप से, ये 3 अनुवाद "। यह आपके बिल्ड समय को कम रखता है, और आपको अपनी निर्भरता पर नज़र रखने में मदद करता है, ताकि आप कोड को अधिक आसानी से पुन: उपयोग कर सकें। इसलिए एक ओबीजीसी परियोजना में, आप आमतौर पर फाउंडेशन पर रुक जाएंगे। यदि बहुत कुछ है। UI, तो आप अपने PCH में UIKit या AppKit जोड़ने पर विचार कर सकते हैं। यह सब मान रहा है कि आप बिल्ड समय का अनुकूलन करना चाहते हैं। बड़े PCH के साथ समस्याओं में से एक जिसमें (लगभग) सब कुछ शामिल है, अनावश्यक निर्भरता को दूर करने में बहुत समय लगता है। आपकी परियोजना की निर्भरताएँ बढ़ती हैं और आपका निर्माण समय बढ़ता जाता है, आपको अपने निर्माण समय को कम करने के लिए अनावश्यक निर्भरता को समाप्त करके वापस लड़ने की आवश्यकता होती है। PCHs साझा करने के लिए कुछ विकल्प हैं। यदि आप PCHs का उपयोग करते हैं,

जहाँ तक मैंने अपने PCH में रखा है: मैंने वर्षों पहले लक्ष्य के विशाल बहुमत के लिए उनका उपयोग करना बंद कर दिया था। वहाँ आम तौर पर अर्हता प्राप्त करने के लिए पर्याप्त नहीं है। ध्यान में रखते हुए, मैं C ++, ObjC, ObjC ++ और C लिखता हूं - संकलक आपके लक्ष्य में प्रत्येक लैंग के लिए एक का उत्सर्जन करता है। इसलिए उन्हें सक्षम करने से अक्सर धीमी गति के समय और उच्चतर I / O हो जाते हैं। अंततः, बढ़ती निर्भरता जटिल परियोजनाओं में निर्भरता से लड़ने का एक अच्छा तरीका नहीं है। कई भाषाओं / बोलियों के साथ काम करना, किसी दिए गए लक्ष्य के लिए आवश्यक निर्भरता में बहुत भिन्नता है। नहीं, मैं सलाह नहीं दूंगा कि हर परियोजना के लिए इष्टतम, लेकिन यह बड़ी परियोजनाओं में निर्भरता प्रबंधन के लिए कुछ दृष्टिकोण देता है।


संदर्भ


टिप्पणियाँ

  • यह सवाल मूल रूप से मॉड्यूल के परिचय से कुछ साल पहले पूछा गया था।
  • वर्तमान में (Xcode 5.0), मॉड्यूल C और ObjC के लिए काम करते हैं, लेकिन C ++ के लिए नहीं।

मॉड्यूल सक्षम परियोजना के लिए पूर्ण पुनर्निर्माण से इसका क्या मतलब है। आप जानते हैं कि यह नया -Swift.h ब्रिजिंग हेडर निश्चित रूप से .pch के लिए एक सही उम्मीदवार नहीं है। लेकिन मैंने लोगों को ऐसा करते देखा है। तो जैसा कि आप देख सकते हैं कि कोई ऐसा करता है। हमारे पास .pch में हमेशा बदलते हेडर होते हैं। तो यह .pch फ़ाइल में हर बार पुनर्निर्माण करता है -Swift.h पुनर्जीवित। क्या आप इस बात से सहमत हैं? आपके पास और इनपुट्स हैं?
मडनिक

@MadNik मान लीजिए कि आपके ऐप के PCH में लाइब्रेरी / फ्रेमवर्क का एक मास्टर हेडर शामिल है जिसे आप सक्रिय रूप से विकसित कर रहे हैं। उदाहरण के लिए #import "MyLib/MyLib.h":। किसी भी समय MyLib.hपरिवर्तन द्वारा शामिल की गई फ़ाइल, ऐप में मौजूद प्रत्येक स्रोत फ़ाइल को फिर से स्थापित किया जाना चाहिए। यदि आप MyLib का उपयोग केवल एक स्रोत फ़ाइल में करते हैं, तो MyLib में परिवर्तन होने पर केवल उस फ़ाइल को फिर से इंस्टॉल किया जाना चाहिए। मानो या न मानो, मैं इन दिनों किसी भी PCH फ़ाइलों का उपयोग नहीं कर रहा हूँ।
जस्टिन

8

मैं बीबूम के साथ सहमत हूं। पीसीएच फाइल पर मेरा कहना है कि इसमें बहुत अधिक #includeया केवल #importकथन होने चाहिए। इसलिए यदि आपके पास सहायक, उच्च-स्तरीय मैक्रोज़ का एक गुच्छा है, तो उन्हें कुछ Common.hऔर #importउस फ़ाइल में परिभाषित करें , जैसा कि bbum ने सुझाव दिया है।

मैं आमतौर पर एक कदम और आगे जाने के लिए और करने के लिए PCH फ़ाइल का उपयोग #importनामक एक फ़ाइल XXCategories.h(जहां XXकि है जिसका उपयोग वर्ग नामकरण उपसर्ग सम्मेलन है) #importमेरे सभी UIKit और फाउंडेशन वर्ग श्रेणियों के लिए रों: NSString+XXAdditions.h, UIColor+XXAdditons.h, आदि


मैं सिर्फ उत्सुक हूँ। .PCH फ़ाइल में, एक Common.h आयात करने में क्या अंतर है, जिसमें विभिन्न #importऔर सिर्फ #importसीधे आयात करने वाले हैं? क्या वे समान नहीं होंगे ?, या क्या यह किसी प्रदर्शन को प्रभावित करता है?
हुलंग

मेरे ज्ञान के लिए, कोई वास्तविक अंतर नहीं है। मुझे लगता है कि यह सबसे अच्छा अभ्यास है। अपनी PCH फ़ाइल में मैक्रोज़ और अन्य चीज़ों का एक समूह बनाने के बजाय, यह केवल #importऔर के लिए होना चाहिए #include
Cifilter

1
अंतर पुन: प्रयोज्य है। PCH परियोजना विशिष्ट है। Common.h कई परियोजनाओं के लिए सामान्य होगा। यह पूछने के लिए कि आप अपने सभी उपयोग वर्गों को अपनी परियोजना में क्यों नहीं डालते हैं, एक उप परियोजना बनाने के बजाय जिसे आप पुन: उपयोग कर सकते हैं। यद्यपि यह एक सरल उदाहरण है, क्योंकि यह केवल एक सरल कॉपी पेस्ट है ... लेकिन कॉपी पेस्ट शरारती है।
बंदगीजैसा

6

एक हेडर फ़ाइल बनाएं "macros.h"

इस शीर्ष लेख को Prefix.pch में आयात करें

इस macros.h में सभी चौखटे और अन्य महत्वपूर्ण चीजें डालते हैं।

यदि आप प्रदर्शन के बारे में चिंतित हैं, तो चिंता न करें, देखें कि सेब क्या कहता है:

हेडर और प्रदर्शन

यदि आप चिंतित हैं कि मास्टर हेडर फ़ाइल सहित आपके प्रोग्राम को ब्लोट हो सकता है, तो चिंता न करें। क्योंकि OS X इंटरफेस को फ्रेमवर्क का उपयोग करके कार्यान्वित किया जाता है, उन इंटरफेस के लिए कोड एक गतिशील साझा पुस्तकालय में रहता है और आपके निष्पादन योग्य में नहीं। इसके अलावा, केवल आपके प्रोग्राम द्वारा उपयोग किए जाने वाले कोड को कभी-कभी रनटाइम में मेमोरी में लोड किया जाता है, इसलिए आपका इन-मेमोरी फ़ुटप्रिंट इसी तरह छोटा रहता है। संकलन के दौरान हेडर फ़ाइलों की एक बड़ी संख्या को शामिल करने के लिए, एक बार फिर, चिंता न करें। Xcode संकलन समय को तेज करने के लिए एक पूर्वनिर्धारित हेडर सुविधा प्रदान करता है। एक ही बार में सभी ढांचे के हेडर को संकलित करके, हेडर को फिर से जोड़ने की आवश्यकता नहीं है जब तक कि आप एक नया ढांचा नहीं जोड़ते हैं। इस बीच, आप शामिल फ़्रेमवर्क से किसी भी इंटरफ़ेस का उपयोग बहुत कम या कोई प्रदर्शन जुर्माना नहीं कर सकते हैं।

मेरे macros.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];

2
यहां एक और उपयोगी: #define async(...) dispatch_async(dispatch_get_main_queue(), __VA_ARGS__ )... मुख्य धागे पर ब्लॉक चलाने के लिए:async(^{ self.someLabel.text = @":D"; });
एलेजांद्रो इवान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.