स्विफ्ट भाषा में #ifdef प्रतिस्थापन


735

C / C ++ / Objective C में आप कंपाइलर प्रीप्रोसेसर का उपयोग करके एक मैक्रो को परिभाषित कर सकते हैं। इसके अलावा, आप संकलक प्रीप्रोसेसर का उपयोग करके कोड के कुछ हिस्सों को शामिल / बाहर कर सकते हैं।

#ifdef DEBUG
    // Debug-only code
#endif

क्या स्विफ्ट में एक समान समाधान है?


1
एक विचार के रूप में, आप इसे अपने obj-c ब्रिजिंग हेडर में लगा सकते हैं ..
Matej

42
आपको वास्तव में एक जवाब देना चाहिए क्योंकि आपके पास चुनने के लिए कई हैं, और इस सवाल ने आपको बहुत अधिक वोट दिए हैं।
डेविड एच

जवाबों:


1069

हां तुम यह कर सकते हो।

स्विफ्ट में आप अभी भी Apple डॉक्स के अनुसार "# if / # if / # endif" प्रीप्रोसेसर मैक्रोज़ (हालांकि अधिक विवश) का उपयोग कर सकते हैं । यहाँ एक उदाहरण है:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

हालांकि, आपको "DEBUG" प्रतीक को कहीं और सेट करना होगा, हालांकि। इसे "स्विफ्ट कंपाइलर - कस्टम फ्लैग" अनुभाग, "अन्य स्विफ्ट फ्लैग" लाइन में सेट करें। आप -D DEBUGप्रविष्टि के साथ DEBUG प्रतीक जोड़ें ।

हमेशा की तरह, आप डिबग में या रिलीज़ होने पर एक अलग मान सेट कर सकते हैं।

मैंने इसे वास्तविक कोड में परीक्षण किया और यह काम करता है; यह एक खेल के मैदान में मान्यता प्राप्त नहीं लगता है, हालांकि।

आप मेरी मूल पोस्ट यहाँ पढ़ सकते हैं ।


महत्वपूर्ण नोट: -DDEBUG=1 काम नहीं करता है। केवल -D DEBUGकाम करता है। लगता है कि संकलक एक विशिष्ट मूल्य के साथ एक ध्वज की अनदेखी कर रहा है।


41
यह सही उत्तर है, हालांकि यह ध्यान दिया जाना चाहिए कि आप केवल ध्वज की उपस्थिति के लिए जांच कर सकते हैं लेकिन विशिष्ट मूल्य नहीं।
चार्ल्स हार्ले

19
अतिरिक्त नोट : जोड़ने के शीर्ष पर -D DEBUGके रूप में ऊपर कहा गया है, तो आप भी परिभाषित करने की जरूरत DEBUG=1में Apple LLVM 6.0 - Preprocessing-> Preprocessor Macros
मैथ्यू क्विरोस

38
मैं जब तक मैं करने के लिए स्वरूपण बदल काम करने के लिए इस प्राप्त नहीं कर सका -DDEBUGइस उत्तर से: stackoverflow.com/a/24112024/747369
क्रेमर

11
@MattQuiros को इसमें जोड़ने की जरूरत नहीं DEBUG=1है Preprocessor Macros, अगर आप इसे ऑब्जेक्टिव-सी कोड में इस्तेमाल नहीं करना चाहते हैं।
derpoliuk

7
@ डैनियल आप मानक बूलियन ऑपरेटरों का उपयोग कर सकते हैं (उदा: `#if!
डेबग`

353

जैसा कि Apple डॉक्स में कहा गया है

स्विफ्ट कंपाइलर में प्रीप्रोसेसर शामिल नहीं है। इसके बजाय, यह समान कार्यक्षमता को पूरा करने के लिए संकलन-समय विशेषताओं, कॉन्फ़िगरेशन का निर्माण और भाषा सुविधाओं का लाभ उठाता है। इस कारण से, स्विफ्ट में प्रीप्रोसेसर निर्देश आयात नहीं किए जाते हैं।

मैं कस्टम बिल्ड कॉन्फ़िगरेशन का उपयोग करके जो मैं चाहता था उसे प्राप्त करने में कामयाब रहा:

  1. अपनी परियोजना पर जाएं / अपना लक्ष्य चुनें / सेटिंग बनाएँ / कस्टम झंडे की खोज करें
  2. अपने चुने हुए लक्ष्य के लिए, डीबग और रिलीज़ दोनों के लिए -D उपसर्ग (सफेद रिक्त स्थान के बिना) का उपयोग करके अपने कस्टम ध्वज को सेट करें
  3. आपके पास प्रत्येक लक्ष्य के लिए ऊपर दिए गए चरणों को करें

यहाँ आप लक्ष्य के लिए कैसे जाँचें:

#if BANANA
    print("We have a banana")
#elseif MELONA
    print("Melona")
#else
    print("Kiwi")
#endif

यहां छवि विवरण दर्ज करें

स्विफ्ट 2.2 का उपयोग करके परीक्षण किया गया


4
1. सफेद अंतरिक्ष काम के साथ भी, 2.should केवल डिबग के लिए झंडा सेट?
c0ming

3
@ c0ming यह आपकी ज़रूरतों पर निर्भर करता है, लेकिन अगर आप चाहते हैं कि कुछ केवल डिबग मोड में ही हो, और रिलीज़ में नहीं, तो आपको रिलीज़ से -DDEBUG को निकालना होगा।
cdf1982

1
-DLOCALमेरे द्वारा कस्टम ध्वज सेट करने के बाद #if LOCAl #else #endif, यह #elseअनुभाग में आता है । मैंने मूल लक्ष्य को डुप्लिकेट किया AppTargetऔर इसका नाम बदलकर AppTargetLocalअपना कस्टम ध्वज सेट किया।
पेरविले लियू

3
@ और क्या आपको पता है कि एक्ससीएस्ट बनाने के साथ-साथ कस्टम झंडे को कैसे पहचानें? मुझे लगता है कि यह #if LOCAL सिम्युलेटर के साथ चलने पर और #else परीक्षण के दौरान गिरने पर इच्छित परिणाम में आता है । मैं चाहता हूं कि यह #if LOCALपरीक्षण के दौरान गिर जाए ।
पेरविल लियू जुएल

3
यह स्वीकृत उत्तर होना चाहिए। स्विफ्ट के लिए वर्तमान स्वीकृत उत्तर गलत है क्योंकि यह केवल ऑब्जेक्टिव-सी पर लागू होता है।
miken.mkndev

171

कई स्थितियों में, आपको वास्तव में सशर्त संकलन की आवश्यकता नहीं है ; आपको बस सशर्त व्यवहार की आवश्यकता है जिसे आप चालू और बंद कर सकते हैं। उसके लिए, आप एक पर्यावरण चर का उपयोग कर सकते हैं। इसका बहुत बड़ा फायदा है कि आपको वास्तव में recompile नहीं करना है।

आप योजना के संपादक में, पर्यावरण चर को सेट कर सकते हैं और आसानी से इसे चालू या बंद कर सकते हैं:

यहां छवि विवरण दर्ज करें

आप NSProcessInfo के साथ पर्यावरण चर प्राप्त कर सकते हैं:

    let dic = NSProcessInfo.processInfo().environment
    if dic["TRIPLE"] != nil {
        // ... do secret stuff here ...
    }

यहाँ एक वास्तविक जीवन उदाहरण है। मेरा ऐप केवल डिवाइस पर चलता है, क्योंकि यह संगीत लाइब्रेरी का उपयोग करता है, जो सिम्युलेटर पर मौजूद नहीं है। फिर, मेरे पास जो डिवाइस नहीं हैं, उसके लिए सिम्युलेटर पर स्क्रीन शॉट्स लेने के लिए कैसे? उन स्क्रीन शॉट्स के बिना, मैं AppStore को प्रस्तुत नहीं कर सकता।

मुझे नकली डेटा और इसे संसाधित करने का एक अलग तरीका चाहिए । मेरे पास दो पर्यावरण चर हैं: एक, जो जब स्विच किया जाता है, तो ऐप को मेरे डिवाइस पर चलने के दौरान वास्तविक डेटा से नकली डेटा उत्पन्न करने के लिए कहता है; दूसरा, जिसे स्विच करने पर, सिम्युलेटर पर चलते समय नकली डेटा (अनुपस्थित संगीत लाइब्रेरी नहीं) का उपयोग करता है। उन सभी विशेष मोड को चालू / बंद करना स्कीम एडिटर में पर्यावरण चर चेकबॉक्स के लिए आसान है। और बोनस यह है कि मैं गलती से उन्हें अपने ऐप स्टोर के निर्माण में उपयोग नहीं कर सकता, क्योंकि संग्रह में कोई पर्यावरण चर नहीं है।


किसी कारण से मेरा पर्यावरण चर दूसरे ऐप लॉन्च पर नील के रूप में वापस आ गया
यूजीन

60
बाहर देखें : पर्यावरण चर सभी बिल्ड कॉन्फ़िगरेशन के लिए सेट हैं, वे अलग-अलग लोगों के लिए सेट नहीं किए जा सकते हैं। तो यह एक व्यवहार्य समाधान नहीं है यदि आपको इसके रिलीज या डिबग बिल्ड के आधार पर व्यवहार को बदलने की आवश्यकता है।
एरिक

5
@ एरिक सहमत हैं, लेकिन वे सभी योजना कार्यों के लिए सेट नहीं हैं। तो आप बिल्ड-एंड-रन पर एक चीज़ और आर्काइव पर एक अलग चीज़ कर सकते हैं, जो अक्सर वास्तविक जीवन का अंतर है जिसे आप आकर्षित करना चाहते हैं। या आपके पास कई योजनाएं हो सकती हैं, जो वास्तविक जीवन का सामान्य पैटर्न भी हैं। साथ ही, जैसा कि मैंने अपने जवाब में कहा है, एक योजना में पर्यावरण चर को बंद करना आसान है।
मैट

10
पर्यावरण चर संग्रह मोड में काम नहीं करते हैं। वे केवल तभी लागू होते हैं जब ऐप को XCode से लॉन्च किया जाता है। यदि आप किसी डिवाइस पर इन्हें एक्सेस करने का प्रयास करते हैं, तो ऐप क्रैश हो जाएगा। कठिन रास्ता खोज लिया।
इपक्रिस

2
@ iupchris10 "आर्काइविंग का कोई पर्यावरण चर नहीं है" मेरे उत्तर के अंतिम शब्द हैं, ऊपर। जैसा कि मैंने अपने जवाब में कहा, अच्छा है । यह बात है
मैट

159

ifdefप्रतिस्थापन का एक बड़ा बदलाव Xcode 8 के साथ आया। यानी सक्रिय संकलन शर्तों का उपयोग ।

Xcode 8 रिलीज़ नोट में बिल्डिंग और लिंकिंग का संदर्भ लें ।

नई बिल्ड सेटिंग्स

नई सेटिंग: SWIFT_ACTIVE_COMPILATION_CONDITIONS

Active Compilation Conditionsis a new build setting for passing conditional compilation flags to the Swift compiler.

इससे पहले, हमें सेटिंग में "-D" को याद करते हुए OTHER_SWIFT_FLAGS के तहत अपने सशर्त संकलन झंडे को घोषित करना होगा। उदाहरण के लिए, सशर्त रूप से एक MYFLAG मान के साथ संकलित करें:

#if MYFLAG1
    // stuff 1
#elseif MYFLAG2
    // stuff 2
#else
    // stuff 3
#endif

सेटिंग में जोड़ने का मूल्य -DMYFLAG

अब हमें नई सेटिंग में केवल MYFLAG को मान देना होगा। समय उन सभी सशर्त संकलन मूल्यों को स्थानांतरित करने के लिए!

कृपया Xcode 8 में अधिक स्विफ्ट बिल्ड सेटिंग्स सुविधा के लिए नीचे दिए गए लिंक पर जाएं : http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/


बिल्ड टाइम पर सेट सक्रिय संकलन शर्तों को अक्षम करने के लिए वैसे भी क्या है? परीक्षण के लिए डिबग कॉन्फ़िगरेशन का निर्माण करते समय मुझे DEBUG स्थिति को अक्षम करना होगा।
जॉनी

1
@ जॉनी मेरे पास एकमात्र तरीका है जो परियोजना के लिए एक 3 जी बिल्ड कॉन्फिगर बनाना है। प्रोजेक्ट से> जानकारी टैब> कॉन्फ़िगरेशन, हिट '+', फिर डीबग डुप्लिकेट करें। फिर आप इस कॉन्फ़िगरेशन के लिए सक्रिय संकलन शर्तों को अनुकूलित कर सकते हैं। नए बिल्ड कॉन्फ़िगरेशन का उपयोग करने के लिए अपने लक्ष्य> टेस्ट योजनाओं को संपादित करना न भूलें!
मथियास

1
यह सही उत्तर होना चाहिए..एक ही चीज है जो मेरे लिए xCode 9 पर स्विफ्ट 4.x का उपयोग करके काम करती है!
शोकावेली

1
BTW, Xcode 9.3 स्विफ्ट में 4.1 DEBUG पहले से ही सक्रिय संकलन शर्तों में है और आपको DEBUG कॉन्फ़िगरेशन की जांच करने के लिए कुछ भी जोड़ने की आवश्यकता नहीं है। सिर्फ #if DEBUG और #endif।
डेनिस कुतलुबाएव

मुझे लगता है कि यह दोनों विषय है, और एक बुरी बात है। आप सक्रिय संकलन शर्तों को अक्षम नहीं करना चाहते हैं। आपको परीक्षण के लिए एक नए और अलग कॉन्फ़िगरेशन की आवश्यकता है - उस पर "डीबग" टैग नहीं होगा। योजनाओं के बारे में जानें।
मोटी शन्नोर

93

स्विफ्ट 4.1 के अनुसार, अगर आपको जरूरत है तो बस यह जांचें कि क्या कोड डीबग या रिलीज़ कॉन्फ़िगरेशन के साथ बनाया गया है, आप अंतर्निहित कार्यों का उपयोग कर सकते हैं:

  • _isDebugAssertConfiguration()(सच जब अनुकूलन सेट है -Onone)
  • _isReleaseAssertConfiguration()(सच जब अनुकूलन सेट है -O) (स्विफ्ट 3+ पर उपलब्ध नहीं)
  • _isFastAssertConfiguration()(सच जब अनुकूलन सेट है -Ounchecked)

जैसे

func obtain() -> AbstractThing {
    if _isDebugAssertConfiguration() {
        return DecoratedThingWithDebugInformation(Thing())
    } else {
        return Thing()
    }
}

प्रीप्रोसेसर मैक्रोज़ की तुलना में,

  • To आपको -D DEBUGइसका उपयोग करने के लिए कस्टम ध्वज को परिभाषित करने की आवश्यकता नहीं है
  • ~ यह वास्तव में अनुकूलन सेटिंग्स के संदर्भ में परिभाषित किया गया है, न कि Xcode बिल्ड कॉन्फ़िगरेशन
  • Removed अनिर्धारित, जिसका अर्थ है कि फ़ंक्शन को किसी भी अपडेट में हटाया जा सकता है (लेकिन यह AppStore-safe होना चाहिए क्योंकि ऑप्टिमाइज़र इन्हें स्थिरांक में बदल देगा)

  • ✗ अगर / में प्रयोग करना हमेशा चेतावनी "कभी निष्पादित नहीं होगा" उत्पन्न करेगा।


1
क्या ये अंतर्निहित कार्यों का मूल्यांकन संकलन समय या रनटाइम पर किया जाता है?
1911 में ma11hew28

@MattDiPasquale अनुकूलन समय। रिलीज मोड में if _isDebugAssertConfiguration()मूल्यांकन किया जाएगा if falseऔर if trueडीबग मोड है।
kennytm

2
हालाँकि, मैं इन फ़ंक्शंस का उपयोग रिलीज़ में कुछ डीबग-केवल चर को चुनने के लिए नहीं कर सकता।
फ्रैंकलिन यू

3
क्या ये कार्य कहीं दस्तावेज हैं?
टॉम हेरिंगटन

7
स्विफ्ट 3.0 और एक्सकोड 8 के रूप में, ये फ़ंक्शन अमान्य हैं।
कोडबेंडर

86

Xcode 8 और ऊपर

बिल्ड सेटिंग्स / स्विफ्ट कंपाइलर - कस्टम फ्लैग में सक्रिय संकलन शर्तों का उपयोग करें ।

  • यह स्विफ्ट कंपाइलर के लिए सशर्त संकलन झंडे को पारित करने के लिए नई बिल्ड सेटिंग है।
  • इस तरह सरल ऐड झंडे: ALPHA, BETAआदि

फिर इसे इस तरह संकलित शर्तों के साथ जांचें :

#if ALPHA
    //
#elseif BETA
    //
#else
    //
#endif

सुझाव: आप भी उपयोग कर सकते हैं #if !ALPHAआदि


77

कोई स्विफ्ट प्रीप्रोसेसर नहीं है। (एक बात के लिए, मनमाने ढंग से कोड प्रतिस्थापन प्रकार और स्मृति-सुरक्षा को तोड़ता है।)

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

उदाहरण के लिए:

#if os(iOS)
    let color = UIColor.redColor()
#else
    let color = NSColor.redColor()
#endif

34
"एक बात के लिए, मनमाने ढंग से कोड प्रतिस्थापन प्रकार और स्मृति-सुरक्षा को तोड़ता है।" कंपाइलर (इसलिए नाम) करने से पहले प्री-प्रोसेसर अपना काम नहीं करता है? इसलिए ये सभी जाँच अभी भी हो सकती हैं।
थिलो

10
@Thilo मुझे लगता है कि यह टूट जाता है आईडीई समर्थन है
Aleksandr Dubinsky

1
मुझे लगता है कि @rickster में जो मिल रहा है वह यह है कि सी प्रीप्रोसेसर मैक्रोज़ को प्रकार की कोई समझ नहीं है और उनकी उपस्थिति स्विफ्ट की प्रकार की आवश्यकताओं को तोड़ देगी। C में मैक्रोज़ काम करता है, क्योंकि C निहित प्रकार के रूपांतरण की अनुमति देता है, जिसका अर्थ है कि आप अपने को INT_CONSTकहीं भी रख सकते हैं float। स्विफ्ट यह अनुमति नहीं देगा। इसके अलावा, यदि आप var floatVal = INT_CONSTअनिवार्य रूप से कर सकते हैं तो यह बाद में कहीं टूट जाएगा जब कंपाइलर उम्मीद करता है Intलेकिन आप इसे एक के रूप में उपयोग करते हैं Float(प्रकार का floatValअनुमान लगाया जाएगा Int)। 10 कास्ट और बाद में मैक्रोज़ को हटाने के लिए बस क्लीनर ...
एपेमेरा

मैं इसका उपयोग करने की कोशिश कर रहा हूं, लेकिन यह काम नहीं कर रहा है, यह अभी भी आईओएस बिल्ड पर मैक कोड को संकलित कर रहा है। वहाँ एक और सेटअप स्क्रीन कहीं है कि tweaked किया जाना है?
मॉरी मार्कोविट

1
@ आप सही हैं - एक पूर्व-प्रोसेसर किसी भी प्रकार या मेमोरी सुरक्षा को नहीं तोड़ता है।
tcurdt

50

Xcode 8 के लिए मेरे दो सेंट:

क) -Dउपसर्ग का उपयोग कर एक कस्टम ध्वज ठीक काम करता है, लेकिन ...

बी) सरल उपयोग:

Xcode 8 में एक नया खंड है: "सक्रिय संकलन शर्तें", पहले से ही दो पंक्तियों के साथ, डिबग और रिलीज़ के लिए।

बस अपने परिभाषित जोड़ने के बिना -D


यह उल्लेख करने के लिए धन्यवाद कि DEBUG AND RELEASE के लिए TW ROWS हैं
Yitzchak

किसी ने रिलीज में यह परीक्षण किया?
ग्लेन

यह स्विफ्ट उपयोगकर्ताओं के लिए अद्यतन उत्तर है। अर्थात बिना -D
मणि

46

isDebug लगातार संकलित सक्रियण शर्तों के आधार पर

एक और, शायद सरल, समाधान जो अभी भी एक बूलियन में परिणाम करता है जिसे आप #ifअपने कोडबस में बिना किसी शर्त के कार्य कर सकते हैं DEBUG, अपने प्रोजेक्ट बिल्ड लक्ष्य Active Compilation Conditionsमें से एक के रूप में परिभाषित करना है और इसमें निम्नलिखित शामिल हैं (मैं इसे एक वैश्विक स्थिरांक के रूप में परिभाषित करता हूं)

#if DEBUG
    let isDebug = true
#else
    let isDebug = false
#endif

संकलक अनुकूलन सेटिंग्स पर आधारित है

यह अवधारणा kennytm के उत्तर पर बनती है

केनीटीएम के खिलाफ तुलना करने पर मुख्य लाभ यह है कि यह निजी या अनिर्दिष्ट तरीकों पर निर्भर नहीं करता है।

में स्विफ्ट 4 :

let isDebug: Bool = {
    var isDebug = false
    // function with a side effect and Bool return value that we can pass into assert()
    func set(debug: Bool) -> Bool {
        isDebug = debug
        return isDebug
    }
    // assert:
    // "Condition is only evaluated in playgrounds and -Onone builds."
    // so isDebug is never changed to true in Release builds
    assert(set(debug: true))
    return isDebug
}()

प्रीप्रोसेसर मैक्रोज़ और kennytm के उत्तर की तुलना में ,

  • To आपको -D DEBUGइसका उपयोग करने के लिए कस्टम ध्वज को परिभाषित करने की आवश्यकता नहीं है
  • ~ यह वास्तव में अनुकूलन सेटिंग्स के संदर्भ में परिभाषित किया गया है, न कि Xcode बिल्ड कॉन्फ़िगरेशन
  • प्रलेखित , जिसका अर्थ है कि फ़ंक्शन सामान्य एपीआई रिलीज़ / अपग्रेड पैटर्न का पालन करेगा।

  • ✓ में अगर / बाकी होगा का उपयोग नहीं एक "कभी नहीं निष्पादित किया जाएगा" चेतावनी उत्पन्न करते हैं।


25

Moignans जवाब यहाँ ठीक काम करता है। यहाँ जानकारी के मामले में यह मदद करता है की एक और शांति है,

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

आप नीचे की तरह मैक्रोज़ को नकार सकते हैं,

#if !RELEASE
    let a = 2
#else
    let a = 3
#endif

23

Xcode संस्करण 9.4.1 के साथ बनाई गई स्विफ्ट परियोजनाओं में, स्विफ्ट 4.1

#if DEBUG
#endif

डिफ़ॉल्ट रूप से काम करता है क्योंकि Preprocessor Macros DEBUG = 1 में Xcode पहले से ही सेट है।

तो आप #if DEBUG "आउट ऑफ बॉक्स" का उपयोग कर सकते हैं।

वैसे, सामान्य रूप से स्थिति संकलन ब्लॉकों का उपयोग कैसे किया जाए, यह एप्पल की पुस्तक द स्विफ्ट प्रोग्रामिंग लैंग्वेज 4.1 (सेक्शन कंपाइलर कंट्रोल स्टेटमेंट) में लिखा गया है और कंपाइल फ़्लैग को कैसे लिखना है और स्विफ्ट में सी मैक्रोज़ का समकक्ष क्या है, यह लिखा है। कोको और ऑब्जेक्टिव सी के साथ स्विफ्ट का उपयोग करते हुए एक और ऐप्पल की पुस्तक (अनुभाग प्रीप्रोसेसर निर्देश में)

भविष्य में आशा है कि Apple अपनी पुस्तकों के लिए अधिक विस्तृत सामग्री और अनुक्रमित लिखेगा।


17

XCODE 9 और ABOVE

#if DEVELOP
    //
#elseif PRODCTN
    //
#else
    //
#endif

3
वाह कि सबसे बदसूरत संक्षिप्त नाम मैंने कभी देखा है: पी
rmp251

7

DEBUG=1अपनी GCC_PREPROCESSOR_DEFINITIONSबिल्ड सेटिंग्स में सेट करने के बाद, मैं इस कॉल को करने के लिए एक फ़ंक्शन का उपयोग करना पसंद करता हूं:

func executeInProduction(_ block: () -> Void)
{
    #if !DEBUG
        block()
    #endif
}

और फिर इस फ़ंक्शन को डिबग बिल्ड में छोड़े गए किसी भी ब्लॉक में संलग्न करें:

executeInProduction {
    Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
}

तुलना करने पर फायदा:

#if !DEBUG
    Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
#endif

क्या यह संकलक मेरे कोड के सिंटैक्स की जाँच करता है, इसलिए मुझे यकीन है कि इसका सिंटैक्स सही है और बनाता है।


3

तुम यहाँ पर मारा है! स्विफ्ट #if कस्टम झंडे नहीं प्रीप्रोसेसर मैक्रोज़ को देखता है। कृपया लिंक से सामग्री के साथ अपने उत्तर को अपडेट करें, अक्सर समय लिंक थोड़ी देर के बाद टूट जाएंगे
डेल

2
func inDebugBuilds(_ code: () -> Void) {
    assert({ code(); return true }())
}

स्रोत


1
यह सशर्त संकलन नहीं है। उपयोगी होते हुए भी, यह सिर्फ एक सादे पुराने रनटाइम सशर्त है। ओपी मेटाप्रोग्रामिंग प्रयोजनों के लिए संकलन के बाद पूछ रहा है
Shayne

3
बस @inlinableसामने जोड़ें funcऔर यह स्विफ्ट के लिए सबसे सुंदर और मुहावरेदार तरीका होगा। रिलीज में आपके code()ब्लॉक को पूरी तरह से अनुकूलित और समाप्त किया जाएगा। एक समान फ़ंक्शन का उपयोग ऐप्पल के अपने एनआईओ ढांचे में किया जाता है।
मोज़ुबा

1

यह जॉन विलिस के उत्तर पर निर्भर करता है जो मुखरता पर निर्भर करता है, जिसे केवल डिबग संकलन में निष्पादित किया जाता है:

func Log(_ str: String) { 
    assert(DebugLog(str)) 
}
func DebugLog(_ str: String) -> Bool { 
    print(str) 
    return true
}

मेरा उपयोग मामला प्रिंट स्टेटमेंट लॉग करने के लिए है। यहाँ iPhone X पर रिलीज़ संस्करण के लिए एक बेंचमार्क है:

let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
    Log ("⧉ unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: \(time2-time1)" )

प्रिंट:

Log: 0.0

लगता है कि स्विफ्ट 4 पूरी तरह से फ़ंक्शन कॉल को समाप्त कर देता है।


डिबग में नहीं होने पर कॉल को पूरी तरह से हटा दिया जाता है - फ़ंक्शन खाली होने के कारण? ये बिल्कुल सही होगा।
जोहान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.