2010-07-05 6 views
37

मैं एक ऐसे प्रोजेक्ट पर काम कर रहा हूं जिसमें एक मैक एप्लिकेशन और एक आईपैड एप्लिकेशन शामिल है जो कोड साझा करता है। मैं आईफोन प्रोजेक्ट से मैक-विशिष्ट कोड को बाहर करने के लिए सशर्त संकलन स्विच का उपयोग कैसे कर सकता हूं और इसके विपरीत? मैंने देखा है कि TARGET_OS_IPHONE और TARGET_OS_MAC दोनों 1 हैं, और इसलिए वे दोनों हमेशा सत्य हैं। क्या कोई और स्विच है जिसका उपयोग मैं कर सकता हूं जो एक विशिष्ट लक्ष्य के लिए संकलन करते समय केवल सत्य लौटाएगा?मैक और आईफोन विशिष्ट कोड के बीच स्विच करने के लिए उपयोग करने के लिए कौन सा सशर्त संकलन?

अधिकांश भाग के लिए, मुझे दो परियोजनाओं के लिए प्रीकंपाइल हेडर में #include <UIKit/UIKit.h> और #include <Cocoa/Cocoa.h> स्थानांतरित करके फ़ाइलों को सहयोग करने के लिए मिल गया है। मैं मॉडल और कुछ उपयोगिता कोड साझा कर रहा हूं जो आरएसएस फ़ीड और एवरोनीट से डेटा प्राप्त करता है।

विशेष रूप से, [NSData dataWithContentsOfURL:options:error:] फ़ंक्शन विकल्प पैरामीटर आईओएस 3.2 और पहले और मैक ओएस 10.5 के लिए एक अलग स्थिरता लेता है और इससे पहले आईओएस 4 और मैक ओएस 10.6 के लिए करता है। सशर्त मैं उपयोग कर रहा हूँ है:

#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2)) || (TARGET_OS_MAC && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5))

यह काम करने के लिए लगता है, लेकिन मुझे यकीन है कि यह बुलेटप्रूफ है बनाना चाहते हैं। मेरी समझ यह है कि यदि मैक संस्करण 10.6 पर सेट किया गया है, लेकिन आईओएस संस्करण 3.2 पर सेट है, तो यह अभी भी नए स्थिरांक का उपयोग करेगा, भले ही यह आईओएस 3.2 के लिए संकलित हो, जो गलत लगता है।

किसी भी मदद के लिए अग्रिम धन्यवाद!

उत्तर

64

आपने अपने अवलोकनों में गलती की है। :)

TARGET_OS_MAC मैक या आईफोन एप्लिकेशन बनाने के दौरान 1 होगा। आप सही हैं, इस तरह की चीज़ के लिए यह काफी बेकार है।

हालांकि, मैक एप्लिकेशन बनाने के दौरान TARGET_OS_IPHONE 0 है। मैं इस उद्देश्य के लिए हर समय अपने शीर्षकों में TARGET_OS_IPHONE का उपयोग करता हूं।

इस तरह

: http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

+0

दुर्भाग्यवश, यदि आपके पास आईओएस और ओएसएक्स दोनों के लिए एक परियोजना है तो TARGET_OS_IPHONE को किसी भी मामले में परिभाषित किया जाना प्रतीत होता है। –

+5

हां। इसे आईओएस के लिए ओएसएक्स, 1 के लिए 0 के रूप में परिभाषित किया गया है। आपको '#if TARGET_OS_IPHONE' का उपयोग करने की आवश्यकता है, न कि' #ifdef TARGET_OS_IPHONE'। एक उदाहरण जोड़ा गया। –

+0

बीटीडब्ल्यू, चार्ट ऐप्पल के "रनटाइम wrangler" से है। अगर वास्तविकता उसके साथ असहमत प्रतीत होती है, तो सवाल वास्तविकता। :) –

7

"करने के लिए सही काम केवल नए स्थिरांक का उपयोग है, क्योंकि यदि आप हेडर को देखते हैं तो आप देखेंगे कि उन्हें enum में पुराने लोगों के बराबर घोषित किया गया है, जिसका अर्थ है कि नए स्थिरांक पुराने पर भी काम करेंगे रिलीज (दोनों स्थिरांक एक ही चीज़ के लिए संकलित होते हैं, और चूंकि एम्स को ऐप में संकलित किया जाता है, इसलिए वे द्विआधारी संगतता को तोड़ने के बिना नहीं बदल सकते हैं)। ऐसा करने का एकमात्र कारण यह नहीं है कि आपको पुराने एसडीके को फिर से बनाना जारी रखना होगा (यानी पुरानी रिलीज का समर्थन करने की तुलना में एक अलग बात, जो आप नए एसडीके के खिलाफ संकलन करते समय कर सकते हैं)

यदि आप वास्तव में ओएस संस्करण के आधार पर विभिन्न झंडे का उपयोग करना चाहते हैं (क्योंकि नए संस्करण ने वास्तव में नई कार्यक्षमता को जोड़ा है, के विपरीत बस एक निरंतर नामकरण) तो वहाँ हैं दो समझदार जिन्हें आप कर सकते हैं, जिनमें से न तो अपने ऊपर मैक्रो सिद्ध:

  1. हमेशा पुराने झंडे का उपयोग करने के लिए जब तक मिनट संस्करण की अनुमति संस्करण वे (कुछ इस तरह) में शुरू किए गए थे से अधिक है:

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) 
        NSDataReadingOptions options = NSDataReadingMapped; 
    #else 
        NSDataReadingOptions options = NSMappedRead; 
    #end 
    
  2. सशर्त केवल नए मूल्यों का उपयोग केवल नए संस्करण पर आधारित है, कर सकते हैं, और कोड में संकलन रनटाइम पर झंडे निर्धारित करने के लिए बनाता है के लिए है कि दोनों संस्करणों का समर्थन:

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) 
        NSDataReadingOptions options = NSDataReadingMapped; 
    #else 
        NSDataReadingOptions options; 
        if ([[UIDevice currentDevice] systemVersion] compare:@"4.0"] != NSOrderedAscending) { 
        options = NSDataReadingMapped; 
        } else { 
        options = NSMappedRead; 
        } 
    #end 
    

ध्यान दें कि यदि आप वास्तव में यह तुलना कर रहे थे तो आप कहीं भी [[UIDevice currentDevice] systemVersion] compare:@"4.0"] के परिणाम को छीनना चाहते हैं। आप आमतौर पर संस्करण तुलना करने की बजाय कमजोर लिंकिंग जैसी चीजों का उपयोग करके सुविधाओं के लिए स्पष्ट रूप से परीक्षण करना चाहते हैं, लेकिन यह enums के लिए एक विकल्प नहीं है।

+0

धन्यवाद! यह अच्छी चीजें है, लेकिन मुझे लगता है कि यहां कुछ संभावित मुद्दे भी हो सकते हैं। लक्ष्य के लिए बिल्ड विकल्प में, परिनियोजन, मैक ओएस एक्स परिनियोजन लक्ष्य और आईफ़ोन ओएस परिनियोजन लक्ष्य के तहत दो अलग-अलग सेटिंग्स हैं। इन दोनों उदाहरणों में, यदि मैक ओएस एक्स परिनियोजन लक्ष्य मैक ओएस एक्स 10.6 पर सेट है, तो यह नए एनम का उपयोग करेगा, भले ही आप आईफोन ओएस 3.2 के लिए निर्माण कर रहे हों। क्या रन है या अन्यथा, यह निर्धारित करने के लिए कि कौन सा ओएस लक्षित किया जा रहा है? –

+0

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

5

उपयोग करने के लिए मैक्रो एसडीके हेडर फाइल TargetConditionals.h में परिभाषित कर रहे हैं:

#if TARGET_OS_IPHONE 
// iOS code 
#else 
// OSX code 
#endif 

यहाँ इस पर एक बड़ा चार्ट है। 10.11 एसडीके से लिया:

TARGET_OS_WIN32   - Generated code will run under 32-bit Windows 
TARGET_OS_UNIX   - Generated code will run under some Unix (not OSX) 
TARGET_OS_MAC    - Generated code will run under Mac OS X variant 
    TARGET_OS_IPHONE   - Generated code for firmware, devices, or simulator 
     TARGET_OS_IOS    - Generated code will run under iOS 
     TARGET_OS_TV    - Generated code will run under Apple TV OS 
     TARGET_OS_WATCH   - Generated code will run under Apple Watch OS 
    TARGET_OS_SIMULATOR  - Generated code will run under a simulator 
    TARGET_OS_EMBEDDED  - Generated code for firmware 

के बाद से यहाँ सब कुछ एक "मैक ओएस एक्स संस्करण" है, TARGET_OS_MAC इस मामले में उपयोगी नहीं है। MacOS के लिए विशेष रूप संकलन करने के लिए, उदाहरण के लिए:

#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED 
    // macOS-only code 
#endif 
0

मैक्रो का उपयोग करने के लिए के सेट अब TARGET_OS_OSX में शामिल हैं:

TARGET_OS_WIN32   - Generated code will run under 32-bit Windows 
    TARGET_OS_UNIX   - Generated code will run under some Unix (not OSX) 
    TARGET_OS_MAC    - Generated code will run under Mac OS X variant 
     TARGET_OS_OSX   - Generated code will run under OS X devices 
     TARGET_OS_IPHONE   - Generated code for firmware, devices, or simulator 
      TARGET_OS_IOS    - Generated code will run under iOS 
      TARGET_OS_TV    - Generated code will run under Apple TV OS 
      TARGET_OS_WATCH   - Generated code will run under Apple Watch OS 
      TARGET_OS_BRIDGE   - Generated code will run under Bridge devices 
     TARGET_OS_SIMULATOR  - Generated code will run under a simulator 
     TARGET_OS_EMBEDDED  - Generated code for firmware 

MacOS कोड की सशर्त संकलन के लिए ठीक काम करने के लिए लगता है।

संबंधित मुद्दे