रिलीज संस्करण iOS स्विफ्ट के लिए प्रिंटलाइन () निकालें


84

println()अगर मैं डिबग बिल्ड में नहीं हूं, तो मैं अपने स्विफ्ट कोड में सभी कॉल को विश्व स्तर पर अनदेखा करना चाहूंगा । मैं इसके लिए कदम से कदम निर्देश द्वारा कोई मजबूत कदम नहीं मिल सकता है और मार्गदर्शन की सराहना करेंगे। वहाँ इस विश्व स्तर पर करते हैं, या ऐसा करने के लिए मैं हर चारों ओर जरूरत है एक तरीका है println()के साथ #IF DEBUG/#ENDIFबयान?



6
डिवाइस कंसोल में अब कोई आउटपुट प्रिंट नहीं करता है, लेकिन डीबगर कंसोल में करता है..हमें रिलीज़ संस्करण के लिए निकालने की आवश्यकता नहीं है।
अनीश पराजुली

1
Xcode 8 और स्विफ्ट 3 के रूप में मुझे रिलीज़ मोड में कंसोल में प्रिंट नहीं दिख रहे हैं।
सीएनएनएन

जवाबों:


101

सबसे आसान तरीका स्विफ्ट के सामने अपना खुद का वैश्विक कार्य करना है println:

func println(object: Any) {
    Swift.println(object)
}

जब लॉगिंग बंद करने का समय हो, तो उस फ़ंक्शन के मुख्य भाग पर टिप्पणी करें:

func println(object: Any) {
    // Swift.println(object)
}

या आप एक सशर्त का उपयोग करके इसे स्वचालित बना सकते हैं:

func println(object: Any) {
    #if DEBUG
        Swift.println(object)
    #endif
}

EDIT इन स्विफ्ट 2.0 printlnको बदल दिया गया है print। दुर्भाग्य से इसमें अब एक वैरेडिक पहला पैरामीटर है; यह अच्छा है, लेकिन इसका मतलब है कि आप इसे आसानी से ओवरराइड नहीं कर सकते क्योंकि स्विफ्ट का कोई "स्प्लैट" ऑपरेटर नहीं है, इसलिए आप कोड में एक वैरेडिक पास नहीं कर सकते (यह केवल शाब्दिक रूप से बनाया जा सकता है)। लेकिन आप एक कम संस्करण बना सकते हैं जो काम करता है, जैसा कि आमतौर पर होता है, आप सिर्फ एक मूल्य छाप रहे हैं:

func print(items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}

स्विफ्ट 3 में, आपको पहले पैरामीटर के बाहरी लेबल को दबाने की जरूरत है:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}

3
अच्छा समाधान, धन्यवाद। मुझे बताया गया है कि iOS (लेकिन OS X नहीं) में, println()रिलीज़ मोड में निष्पादित नहीं किया जाता है।
नैट बिरखोलज़

13
@NateBirkholz नहीं, यह बकवास है। (यह सुनिश्चित करने के लिए परीक्षण के बाद उन्होंने कहा!)
मैट

स्विफ्ट 2 में, फंक्शन को प्रिंट करने के लिए नाम बदलने के साथ, क्या आप फंक को मैच करने का मौका देंगे? इसके अलावा, आप इसे विश्व स्तर पर कैसे परिभाषित करेंगे? मैंने इसे AppDelegate में अपनी कक्षा के बाहर रखने की कोशिश की और मेरे पास एक मिलियन प्रिंट () कॉल होने के बावजूद इसे कभी नहीं बुलाया गया। यहाँ मैंने क्या कोशिश की है: फंक प्रिंट (ऑब्जेक्ट: एनी) {स्विफ्ट.प्रिंट (ऑब्जेक्ट)}
चार्ली

@Charlie हाँ, मैं अभी भी इसे printlnबदलकर उपयोग कर रहा हूँ print। आपके लिए काम नहीं करने का कारण यह है कि आपकी printपरिभाषा स्विफ्ट से मेल नहीं खाती है, इसलिए आप इसे ओवरराइड नहीं कर रहे हैं। एक मामूली समस्या है क्योंकि, जैसा कि कई बार टिप्पणी की गई है, स्विफ्ट के पास कोई स्पैट ऑपरेटर नहीं है, इसलिए आप वैराडिक पास नहीं कर सकते। लेकिन यह एक आइटम के लिए ठीक काम करता है, जिसे आप पास कर सकते हैं items[0]
मैट

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

46

स्विफ्ट 4.x के लिए अपडेट किया गया:

स्विफ्ट 2.0 / 3.0 और Xcode 7/8 अब बीटा से बाहर हो गए हैं, कुछ बदलाव हुए हैं कि आप रिलीज़ बिल्ड में प्रिंट फ़ंक्शन को कैसे अक्षम करते हैं।

ऊपर दिए गए @matt और @Nate Birkholz द्वारा उल्लेखित कुछ महत्वपूर्ण बिंदु हैं जो अभी भी मान्य हैं।

  1. println()समारोह द्वारा प्रतिस्थापित किया गयाprint()

  2. #if DEBUG मैक्रो का उपयोग करने के लिए फिर आपको "स्विफ्ट कंपाइलर - कस्टम फ्लैग्स -ऑथर फ्लैग्स" को परिभाषित करना होगा जिसमें मूल्य शामिल हो-D DEBUG

  3. मैं Swift.print()वैश्विक दायरे में फ़ंक्शन को ओवरराइड करने की अनुशंसा करूंगा ताकि आप print()फ़ंक्शन को अपने कोड में सामान्य रूप से उपयोग कर सकें , लेकिन यह गैर-डीबग बिल्ड के लिए आउटपुट निकाल देगा। यहां एक फ़ंक्शन हस्ताक्षर है जिसे आप स्विफ्ट 2.0 / 3.0 में ऐसा करने के लिए वैश्विक दायरे में जोड़ सकते हैं:

    func print(items: Any..., separator: String = " ", terminator: String = "\n") {
    
        #if DEBUG
    
        var idx = items.startIndex
        let endIdx = items.endIndex
    
        repeat {
            Swift.print(items[idx], separator: separator, terminator: idx == (endIdx - 1) ? terminator : separator)
            idx += 1
        }
        while idx < endIdx
    
        #endif
    }
    

नोट: हमने डिफॉल्ट सेपरेटर को यहां स्पेस के लिए सेट किया है, और न्यू टर्म होने के लिए डिफॉल्ट टर्मिनेटर है। यदि आप चाहें तो आप इसे अपनी परियोजना में अलग तरीके से कॉन्फ़िगर कर सकते हैं।

उम्मीद है की यह मदद करेगा।

अपडेट करें:

इस कार्य को आमतौर पर वैश्विक दायरे में रखना बेहतर होता है, ताकि यह स्विफ्ट के printकार्य के सामने बैठे । मुझे लगता है कि इसे व्यवस्थित करने का सबसे अच्छा तरीका यह है कि आप अपनी परियोजना में एक उपयोगिता फ़ाइल (जैसे DebugOptions.Swift) जोड़ दें जहां आप इस फ़ंक्शन को वैश्विक दायरे में रख सकते हैं।

स्विफ्ट 3 के रूप में ++ऑपरेटर को पदावनत किया जाएगा। मैंने इस बदलाव को प्रतिबिंबित करने के लिए ऊपर स्निपेट को अपडेट किया है।


1
मुझे क्षमा करें, लेकिन फ़ंक्शन कहाँ रखा जाए?
15

@ User9527 संभवतः आप इसे वैश्विक दायरे में रखना चाहते हैं, ताकि यह आपके पूरे प्रोजेक्ट में उपलब्ध हो। अपनी परियोजनाओं में, मैं एक उपयोगिता स्विफ्ट फ़ाइल (DebugOptions.swift या कुछ समान) जोड़ता हूं और इस कार्य को वैश्विक दायरे में रखता हूं (अर्थात संलग्न वर्ग में नहीं)।
Glavid

क्या आप स्विफ्ट-एक्सकोड के वर्तमान संस्करण की पुष्टि कर सकते हैं, प्रिंट स्टेटमेंट डिवाइस-कंसोल को बिना डी-डीबग फ्लैट को सेट किए बिना आउटपुट देगा? कम से कम आज जो मैंने परीक्षण किया है।
user523234

1
स्विफ्ट 3 के रूप में, किसी को तर्कों की सूची की शुरुआत में अंडरस्कोर जोड़कर थोड़ी अधिक संक्षिप्तता मिल सकती है: "प्रिंट (_ आइटम ..."
जोनाथन ज़ैन

7
तो मैंने प्रिंट के संदर्भ को देखा (didFinishLaunching में इस्तेमाल किया गया ...) और इसने मुझे मूल प्रिंट फंक्शन दरार की ओर इशारा किया। उस और @ जोनाथनज़ैन की टिप्पणी को एक साथ रखते हुए, मैंने फ़ंक्शन को इस तरह से देखने के लिए समायोजित किया और यह काम करता है:public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
जॉनी

38

खदान सहित इन सभी दृष्टिकोणों के साथ समस्या यह है कि वे printतर्कों का मूल्यांकन करने के ओवरहेड को दूर नहीं करते हैं। कोई फर्क नहीं पड़ता कि आप उनमें से किसका उपयोग करते हैं, यह महंगा होने जा रहा है:

print(myExpensiveFunction())

एकमात्र सभ्य समाधान सशर्त संकलन में वास्तविक प्रिंट कॉल को लपेटना है (मान लें कि DEBUGकेवल डिबग बिल्ड के लिए परिभाषित किया गया है):

#if DEBUG
print(myExpensiveFunction())
#endif

वह, और केवल यही, myExpensiveFunctionरिलीज बिल्ड में बुलाया जाने से रोकता है।

हालाँकि, आप स्वत: प्रकटीकरण का उपयोग करके मूल्यांकन का एक स्तर पीछे धकेल सकते हैं । इस प्रकार, आप मेरे समाधान को फिर से लिख सकते हैं (यह स्विफ्ट 3 है) इस तरह:

func print(_ item: @autoclosure () -> Any, separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    Swift.print(item(), separator: separator, terminator: terminator)
    #endif
}

यह समस्या को उस स्थिति में हल करता है, जब आप सिर्फ एक चीज को प्रिंट कर रहे होते हैं, जो आमतौर पर सच होती है। ऐसा इसलिए item()है क्योंकि इसे रिलीज़ मोड में नहीं कहा जाता है। print(myExpensiveFunction())इस प्रकार महंगा होना बंद हो जाता है, क्योंकि कॉल का मूल्यांकन किए बिना बंद कर दिया जाता है, और रिलीज़ मोड में, इसका मूल्यांकन बिल्कुल नहीं किया जाएगा।


का क्या उपयोग है @autoclosure?
kelin

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

@ छिपा-उपयोगकर्ता नाम हां, मैं अपने printबयानों को अपने शिपिंग कोड में छोड़ता हूं , लेकिन यहां जो मेरा उत्तर है उससे अलग है। printआपके Xcode- स्वतंत्र रिलीज़ बिल्ड में कंसोल के लिए एक स्टेटमेंट आउटपुट नहीं भेजा जाता है, लेकिन इसका मूल्यांकन अभी भी किया जाता है , इसलिए यह जानना उपयोगी है कि उस मूल्यांकन को कैसे दबाया जाए क्योंकि यह महंगा है या अवांछित दुष्प्रभाव हैं।
मैट

@ ओम ओह ठीक है ... हाँ मैंने इसे गलत समझा। मैं उन्हें टिप्पणी करूंगा। साभार
हिडन-यूजर

क्या यह दृष्टिकोण बाइनरी फ़ाइल से मुद्रित स्ट्रिंग को हटा देगा? उदाहरण के लिए यदि मैंने उस पद्धति का उपयोग किया है और कहीं न कहीं मेरे ऐप में मैंने "प्रिंट (" उपयोगकर्ता लॉग इन ") डाल दिया है और फिर अगर कोई मेरे इंजीनियर को रिवर्स करने की कोशिश करता है तो क्या वह इस स्ट्रिंग को कहीं खोजेगा या यह बिल्कुल भी नहीं होगा?
लेसज़ेक सुज़री

18

जैसा कि कहा गया है, मैं एक छात्र हूं और चीजों को साथ चलने के लिए कुछ और स्पष्ट रूप से परिभाषित करने की आवश्यकता है। बहुत सारे शोध के बाद, मुझे जिस अनुक्रम का पालन करने की आवश्यकता थी वह है:

Xcode प्रोजेक्ट विंडो के बाईं ओर स्थित फ़ाइल नेविगेटर के शीर्ष पर प्रोजेक्ट नाम पर क्लिक करें। यह वह रेखा है जिसमें परियोजना का नाम है, कितने निर्माण लक्ष्य हैं और आईओएस एसडीके संस्करण है।

चुनें सेटिंग्स बिल्ड टैब और के लिए नीचे स्क्रॉल " स्विफ्ट संकलक - कस्टम झंडे " तल के पास अनुभाग। अनुभाग का विस्तार करने के लिए अन्य झंडे के बगल में नीचे तीर पर क्लिक करें ।

इसे चुनने के लिए डीबग लाइन पर क्लिक करें । अपने माउस कर्सर को लाइन के दाईं ओर रखें और डबल-क्लिक करें। एक सूची दृश्य दिखाई देगा। मान जोड़ने के लिए सूची दृश्य के निचले बाईं ओर + बटन पर क्लिक करें । एक पाठ क्षेत्र सक्रिय हो जाएगा।

पाठ फ़ील्ड में, पाठ दर्ज करें -D DEBUGऔर लाइन को कम करने के लिए रिटर्न दबाएँ ।

अपने प्रोजेक्ट में एक नई स्विफ्ट फ़ाइल जोड़ें। आप फ़ाइल के लिए एक कस्टम क्लास बनाना चाहते हैं, इसलिए निम्न की तर्ज पर टेक्स्ट दर्ज करें:

class Log {

  var intFor : Int

  init() {
    intFor = 42
   }

  func DLog(message: String, function: String = __FUNCTION__) {
    #if DEBUG
      println("\(function): \(message)")
    #endif
  }
}

मुझे आज Xcode द्वारा स्वीकार किए जाने वाले वर्ग को प्राप्त करने में समस्या हो रही थी, इसलिए यह आवश्यकता से थोड़ा अधिक भारी हो सकता है।

अब आपको किसी भी वर्ग में अपने कस्टम वर्ग का संदर्भ देना होगा जिसमें आप println()प्रत्येक लागू वर्ग में एक संपत्ति के रूप में इसे जोड़ने के स्थान पर नए कस्टम फ़ंक्शन का उपयोग करने का इरादा रखते हैं:

   let logFor = Log()

अब आप से किसी उदाहरण की जगह ले सकता है println()के साथ logFor.DLog()। आउटपुट में फ़ंक्शन का नाम भी शामिल होता है जिसमें लाइन कहा जाता था।

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


8
डिबग लॉग के लिए एक कस्टम वर्ग बनाने की आवश्यकता नहीं है। वैश्विक फ़ंक्शन का उपयोग करना आसान और अधिक व्यावहारिक है।
Vojtech Vrbka

इंटफ़ोर = ४२ का उपयोग क्या है?
टेड

15

स्विफ्ट 5

बस अपनी परियोजना में एक नई फ़ाइल बनाएं और इस कोड को इसमें पेस्ट करें:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    items.forEach {
        Swift.print($0, separator: separator, terminator: terminator)        
    }
    #endif
}

यह फ़ंक्शन हस्ताक्षर डिफ़ॉल्ट स्विफ्ट से मेल खाता है इसलिए यह आपकी परियोजना में फ़ंक्शन को "अधिलेखित" करता है। यदि आवश्यक हो तो आप अभी भी मूल का उपयोग करके पहुंच सकते हैं Swift.print()

एक बार जब आपने ऊपर कोड जोड़ लिया, तो print()हमेशा की तरह उपयोग करते रहें और यह केवल डिबग बिल्ड में प्रिंट होगा।

नोट: forEachप्रत्येक आइटम को प्रिंट करने के लिए प्रिंट स्टेटमेंट के आसपास कष्टप्रद सरणी कोष्ठक से छुटकारा मिलता है जो दिखाते हैं कि क्या आप बस itemsसीधे में गुजरते हैं Swift.print()

किसी के लिए अपेक्षाकृत नई स्विफ्ट के लिए आपको आश्चर्य हो सकता है कि बिल्ली क्या $0है। यह सिर्फ forEachब्लॉक में पारित पहले तर्क का प्रतिनिधित्व करता है । forEachबयान में यह भी इस तरह लिखा जा सकता है:

items.forEach { item in
    Swift.print(item, separator: separator, terminator: terminator)        
}

अंत में यदि आप रुचि रखते हैं, तो स्विफ्ट की घोषणा printइस तरह दिखाई देती है:

public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

ऊपर मेरा जवाब सटीक स्विफ्ट कार्यान्वयन को दर्शाता है - हालांकि मैं कभी भी एक से अधिक चीजों को नहीं छापता हूं या विभाजक / टर्मिनेटर नहीं बदलता हूं। लेकिन कौन जानता है, आप चाहते हो सकता है।


2
इस फ़ंक्शन को घोषित करने के लिए, क्या यह कुछ विस्तार या smth है? मैं इसे प्रत्येक फ़ाइल में घोषित नहीं करना चाहता)
Matrosov Alexander

1
@MatrosovAlexander आप अपने ऐप प्रोजेक्ट में कहीं भी एक स्विफ्ट फ़ाइल बना सकते हैं और इस कोड को डाल सकते हैं। कंपाइलर काफी स्मार्ट है जो इसे विश्व स्तर पर सुलभ बना सकता है।
ट्रेव

11

यहाँ एक फ़ंक्शन है जो मैं उपयोग करता हूं, जो स्विफ्ट 3 में पूरी तरह से काम करता है:

func gLog<T>( _ object: @autoclosure() -> T, _ file: String = #file, _ function: String = #function, _ line: Int = #line)
    {
    #if DEBUG
        let value = object()
        let stringRepresentation: String

        if let value = value as? CustomDebugStringConvertible
            {
            stringRepresentation = value.debugDescription
            }
        else if let value = value as? CustomStringConvertible
            {
            stringRepresentation = value.description
            }
        else
            {
            fatalError("gLog only works for values that conform to CustomDebugStringConvertible or CustomStringConvertible")
            }

        let fileURL = NSURL(string: file)?.lastPathComponent ?? "Unknown file"
        let queue = Thread.isMainThread ? "UI" : "BG"
    let gFormatter = DateFormatter()
    gFormatter.dateFormat = "HH:mm:ss:SSS"
        let timestamp = gFormatter.string(from: Date())

        print("✅ \(timestamp) {\(queue)} \(fileURL) > \(function)[\(line)]: " + stringRepresentation + "\n")
    #endif
    }

यहाँ आउटपुट का एक उदाहरण है जो इसे उत्पन्न करता है:

आउटपुट का स्क्रीनशॉट

स्पष्टीकरण:

  • हरे चेकमार्क का उपयोग आपको कंसोल में अपने प्रिंट (gLog) संदेशों को जल्दी से देखने में सक्षम करने के लिए किया जाता है, जहां वे कभी-कभी अन्य संदेशों के समुद्र में खो सकते हैं

  • समय / तारीख मोहर

  • यह जिस थ्रेड पर चलाया जा रहा है - मेरे मामले में यह या तो MainTread (जिसे मैं UI कहता हूं), या MainThread नहीं (जिसे मैं बीजी कहता हूं, बैकग्राउंड थ्रेड के लिए)

  • उस फ़ाइल का नाम, जिसमें gLog संदेश रहता है

  • gLog संदेश जिस फ़ाइल में रहता है, उसके भीतर फ़ंक्शन

  • gLog संदेश की पंक्ति संख्या

  • वास्तविक gLog संदेश जिसे आप प्रिंट करना चाहते हैं

आशा है कि यह किसी और के लिए उपयोगी है!


क्या इसे पूरे ऐप में उपयोग किए जाने के लिए एक अलग फ़ाइल में रखा जा सकता है? मैंने इसे एक अलग वर्ग फ़ाइल में डालने की कोशिश की, एक वर्ग विधि के रूप में। लेकिन यह libMobileGestalt MobileGestaltSupport.m के साथ क्रैश हो जाता है: 153: pid 2574 (डेमो) के पास frxQaeyWLUvLjejEKEKMhmg के लिए सैंडबॉक्स एक्सेस नहीं है और यह libMobileGestalt MobileGestalt.c: 550 के लिए उचित विनियोग नहीं है (देखें) ) डिबगर से संदेश: स्मृति समस्या के कारण समाप्त
omarojo

omarojo, मैं अपने पूरे ऐप में एक वैश्विक फ़ंक्शन के रूप में इसका उपयोग करता हूं। कोई वर्ग आवश्यक नहीं है। मेरे पास एक फ़ाइल है जिसका नाम utils.swift है, जिसमें मेरे सभी उपयोगिता कार्य शामिल हैं, जैसे कि। आपको सिर्फ फाउंडेशन आयात करने की ज़रूरत है - शायद यही वह कदम है जिसे आपने याद किया है? वैसे, कक्षाओं के भीतर अपने कार्यों को घोषित करने के बारे में अधिक जानकारी के लिए, कक्षाओं के भीतर स्थिर कार्यों के रूप में, या वैश्विक कार्यों के रूप में, इस SO प्रश्न और उत्तर देखें: stackoverflow.com/questions/30197548/…
जीन लोपार्को

हाँ, यह सिर्फ फंक्शन के साथ एक नई फ़ाइल बनाकर काम कर रहा है। क्लास फंक्शन के रूप में होने के कारण किसी भी स्पष्ट डिबग संदेश के साथ ऐप क्रैश होगा।
ओमारोजो

इस आदमी के लिए धन्यवाद, शर्म की बात है कि मैंने इसे पहले नहीं खोजा था। मुझे बहुत डिबगिंग सिरदर्द से बचाया।
बियोवुल्फ़

मेरी खुशी @beowulf!
जीन लोपार्को

9

स्विफ्ट 2.1 और Xcode 7.1.1 के साथ परीक्षण किया गया

रिलीज के संस्करणों से सभी प्रिंट स्टेटमेंट को बाहर करने का एक आसान तरीका है, एक बार जब आप जानते हैं कि स्विफ्ट कंपाइलर द्वारा खाली कार्यों को हटा दिया जाता है

साइड नोट: ऑब्जेक्टिव-सी के युग में, एक पूर्व-पार्सर था, जिसका उपयोग कंपाइलर के लात मारने से पहले NSLog स्टेटमेंट को हटाने के लिए किया जा सकता था, जैसे कि मेरे जवाब में यहाँ वर्णित है । लेकिन चूंकि स्विफ्ट के पास अब पूर्व-पार्सर नहीं है, इसलिए यह दृष्टिकोण अब मान्य नहीं है।

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

आप फ़ंक्शन को आवश्यकतानुसार मोड़ सकते हैं, इसे बेहतर बनाने के लिए किसी भी सुझाव का स्वागत है!

// Gobal log() function
//
// note that empty functions are removed by the Swift compiler -> use #if $endif to enclose all the code inside the log()
// these log() statements therefore do not need to be removed in the release build !
//
// to enable logging
//
// Project -> Build Settings -> Swift Compiler - Custom flags -> Other Swift flags -> Debug
// add one of these 3 possible combinations :
//
//      -D kLOG_ENABLE
//      -D kLOG_ENABLE -D kLOG_DETAILS
//      -D kLOG_ENABLE -D kLOG_DETAILS -D kLOG_THREADS
//
// you can just call log() anywhere in the code, or add a message like log("hello")
//
func log(message: String = "", filePath: String = #file, line: Int = #line, function: String = #function) {
            #if kLOG_ENABLE

            #if kLOG_DETAILS

            var threadName = ""
            #if kLOG_THREADS
                threadName = NSThread.currentThread().isMainThread ? "MAIN THREAD" : (NSThread.currentThread().name ?? "UNKNOWN THREAD")
                threadName = "[" + threadName + "] "
            #endif

            let fileName = NSURL(fileURLWithPath: filePath).URLByDeletingPathExtension?.lastPathComponent ?? "???"

            var msg = ""
            if message != "" {
                msg = " - \(message)"
            }

            NSLog("-- " + threadName + fileName + "(\(line))" + " -> " + function + msg)
        #else
            NSLog(message)
        #endif
    #endif
}

यहां आप कंपाइलर फ़्लैग सेट करते हैं:

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

इस तरह दिखता है सभी झंडे के साथ एक उदाहरण उत्पादन:

   2016-01-13 23:48:38.026 FoodTracker[48735:4147607] -- [MAIN THREAD] ViewController(19) -> viewDidLoad() - hello

लॉग के साथ कोड () इस तरह दिखता है:

    override func viewDidLoad() { log("hello")
    super.viewDidLoad()

   // Handle the text field's user input through delegate callbacks
   nameTextField.delegate = self
}

अच्छा है! मैंने इसे यहां से लिया और आखिरकार AELog और AEConsole बनाया ।
तदिजा

यह DEBUG मोड में ठीक काम कर रहा है। अब, मैं एडिट स्कीम से RELEASE मोड में बदल गया हूं। यह रिलीज़ मोड के लिए लॉग इन कंसोल विंडो को भी दिखाता है। ऐसा क्यों?
जयप्रकाश दुबे

Xcode 9 में स्विफ्ट 3.2 के लिए मुझे लॉग (संदेश: "हैलो") का उपयोग करके प्रिंट करने और कॉल करने के लिए NSLog बदलने की जरूरत थी, साथ ही मुझे उद्धरणों के साथ "-D" "kLOG_ENABLE" के रूप में झंडे लगाने थे। अन्य सभी स्विफ्ट संस्करण अपडेट को कंपाइलर द्वारा सुझाए गए फ़िक्सेस के साथ उठाया गया था।
iPyberPaul

1
यहां आप "स्विफ्ट कंपाइलर द्वारा खाली किए गए फ़ंक्शंस" को हटाते हैं, जहां डॉक्स में हमें वह मिलता है? आप कैसे जानते हैं कि मामला क्या है? @ रॉन-वियर्स
जुमज़ुम

7

डिबग बिल्ड सेटिंग्स के -D DEBUGलिए सुनिश्चित करने के बाद भी सरल, और भी OTHER_SWIFT_FLAGS:

#if !DEBUG
    func print(_ items: Any..., separator: String = " ", terminator: String = "\n") { }
#endif

मुझे संदेह है कि इसके लिए "जहां" की आवश्यकता हो सकती है क्योंकि प्रिंट करने योग्य ऑब्जेक्ट्स उन सिस्टम प्रोटोकॉलों में से एक के अनुरूप होते हैं जिन्हें आप wwdc के लिए vids में शायद ही कभी उल्लेख किया गया हो, और मुझे लगता है कि स्विफ्ट गाइड (s) 1.2 बनाम 2 के अंत में, अंतर भूल गया अगर वहाँ सिस्टम एक के साथ एक है
स्टीफन जे

अब तक यह स्विफ्ट 1.2 के साथ काम करता है। 2.0 की कोशिश नहीं की।
रिवेरा

6

XCode 8 ने कुछ नई बिल्ड सेटिंग्स पेश कीं ।
विशेष रूप से एक ने Active Compilation Conditionsउसी तरह से संदर्भित किया है जैसे अन्य फ्लैग सेटिंग्स ने किया था।

"सक्रिय संकलन शर्तें" स्विफ्ट कंपाइलर के लिए सशर्त संकलन झंडे को पारित करने के लिए एक नई बिल्ड सेटिंग है।

XCode 8 के अनुसार (8.3.2 में परीक्षण किया गया) आपको यह डिफ़ॉल्ट रूप से मिलेगा:

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

तो बिना किसी विन्यास के आप निम्नलिखित लिख सकते हैं:

#if DEBUG
    print("⚠️ Something weird happened")
#endif

मैं आपको दृढ़ता से सलाह देता हूं कि यदि आप इस दृष्टिकोण का उपयोग करते हैं तो बड़े पैमाने पर एक वर्ग / संरचना / फ़ंक्शन बनाएं जो इस लॉगिंग तर्क को लपेटता है। आप इसे और नीचे सड़क तक विस्तारित करना चाह सकते हैं।


4

वरुण नाहरिया के पास अब तक का बेहतर समाधान है। मैं उनके जवाब को रिवेरा के साथ जोड़ूंगा ...

  1. -D DEBUGकंपाइलर निर्देशों पर एक ध्वज बनाएँ , सेटिंग्स का निर्माण करें।
  2. फिर यह कोड जोड़ें:

    #if !DEBUG
     public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    }
    #endif
    

यह कोड printरिलीज के लिए हर चीज को कुछ नहीं में बदल देगा ।


3

स्विफ्ट 4 एक्सकोड 10.0

शायद आप इसका उपयोग कर सकते हैं

func dPrint(_ message: @autoclosure () -> Any) {
    #if DEBUG
    print(message())
    #endif
}

उपयोग करने का कारण यह @autoclosureहै कि यदि आप एक फ़ंक्शन को संदेश पैरामीटर के रूप में पास करते हैं, तो फ़ंक्शन को केवल डिबग मोड में कहा जाएगा, यह एक प्रदर्शन हिट का कारण होगा।

Swift.print(_ items: Any..., separator: String = default, terminator: String = default)फ़ंक्शन के विपरीत , मेरे समाधान में केवल एक पैरामीटर है, क्योंकि ज्यादातर मामलों में, हम कई मापदंडों को पास नहीं करते हैं क्योंकि प्रिंट फ़ंक्शन केवल कंसोल में जानकारी दिखाता है, हम मापदंडों को केवल स्ट्रिंग में बदल सकते हैं: "\(param1)"+"\(param2)"सही? आशा है कि मेरे समाधान की तरह


1

आप एक ब्रेकपॉइंट का उपयोग भी कर सकते हैं, इसे मूल्यांकन के बाद जारी रखने के लिए सेट करें, और ब्रेकपॉइंट में प्रिंट संदेश लिखें!

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


0

आप परिभाषित कर सकते debug_printlnहैं कि सामग्री किसकी होगी:

#if DEBUG
  println()
#endif

धन्यवाद, मैं इसे कहां परिभाषित कर सकता हूं? मैं एक छात्र हूं जो मैं डरता हूं और मैं मदद की बहुत सराहना करता हूं, लेकिन अधिक स्पष्ट संदर्भ की आवश्यकता है।
नैट बिरखोलज़

आप इसे एक हेडर फ़ाइल में घोषित करेंगे कि आप इसका उपयोग करने के लिए कहीं भी आयात करेंगे।
इयान मैकडोनाल्ड

0

मेरा समाधान कक्षा से पहले AppDelegate में इस कोड का उपयोग करता है

// Disable console log in live app
#if !arch(x86_64) && !arch(i386)
    public func debugPrint(items: Any..., separator: String = " ", terminator: String = "\n") {

    }
    public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {

    }
#endif

class AppDelegate: UIResponder, UIApplicationDelegate {
// App Delegate Code 

}

0

मेरे समाधान के लिए मैं इसे सरल बनाता हूं

import UIKit

class DLog: NSObject {

   init(title:String, log:Any) {
       #if DEBUG
           print(title, log)
       #endif

   }

}

तो इसे दिखाने के लिए बस कॉल करें

_ = DLog(title:"any title", log:Any)

0

मैंने इसका उपयोग करते हुए समाप्त किया:

#if DEBUG
func dLog(_ item: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
    print("\(Date()) [\((file as NSString).lastPathComponent):\(line) \(function)] \(item())")
}
#else
func dLog(_ item: @autoclosure () -> Any) {}
#endif

यह काफी कॉम्पैक्ट है, कुछ उपयोगी informations (टाइमस्टैम्प, स्विफ्ट फ़ाइल नाम, कोड लाइन, फंक्शन नेम) को प्रिंट करता है और कम से कम मेरे परीक्षणों में हेक्स एडिटोरियल में खोले जाने पर मुझे एप्लिकेशन बाइनरी फ़ाइल में कोई लॉग स्ट्रिंग नहीं मिली।


0

और भी सरल: इस तथ्य का लाभ उठाएं कि मुखर रिलीज बिल्ड से हटा दिए गए हैं और केवल वहां से प्रिंट को कॉल करें। यह सभी लॉग कॉल को निकालता है (हां, यहां तक ​​कि Log.da पर कॉल भी) क्योंकि वे रिलीज के लिए निर्माण करते समय खाली हैं।

लेकिन मैंने यह भी सुना है कि रिलीज़ बिल्ड के लिए प्रिंट निकाल दिए जाते हैं, लेकिन लिखित रूप में इसे खोजने में सक्षम नहीं हैं। तो अभी के लिए, मैं Logनीचे कुछ इस तरह का उपयोग कर रहा हूँ । मेरे पास GitHub पर emojis (पठनीयता के लिए) और लॉग विषयों (स्थिरता के लिए) के साथ एक अधिक भावपूर्ण संस्करण है:

https://github.com/Gatada/JBits/blob/master/Project/Utility/Log.swift

public enum Log {

    /// A date formatter used to create the timestamp in the log.
    ///
    /// This formatter is only created if it is actually used, reducing the
    /// overhead to zero.
    static var formatter: DateFormatter?

    // MARK: - API

    /// Call to print message in debug area.
    ///
    /// Asserts are removed in release builds, which make
    /// the function body empty, which caused all calls to
    /// be removed as well.
    ///
    /// Result is zero overhead for release builds.
    public static func da(_ message: String) {
        assert(debugAreaPrint(message))
    }

    // MARK: - Helpers

    /// The function that actually does the printing. It returns `true` to
    /// prevent the assert from kicking in on debug builds.
    private static func debugAreaPrint(_ message: String) -> Bool {
        print("\(timestamp) - \(message)")
        return true
    }

    /// Creates a timestamp used as part of the temporary logging in the debug area.
    static private var timestamp: String {

        if formatter == nil {
            formatter = DateFormatter()
            formatter!.dateFormat = "HH:mm:ss.SSS"
        }

        let date = Date()
        return formatter!.string(from: date)
    }
}

कोड में:

Log.da("This is only handled in a debug build.")

डिबग बिल्ड चलाते समय Xcode डीबग क्षेत्र में ही देखें :

13: 36: 15.047 - यह केवल डिबग बिल्ड में संभाला जाता है।


0

मेरा प्रोजेक्ट ऑब्जेक्टिव सी में विकसित किया गया था, लेकिन पिछले एक साल से मैंने स्विफ्ट में नए कोड को मर्ज करना शुरू कर दिया है, इसलिए स्विफ्ट नीचे दिए गए समाधान में मेरे लिए काम किया, मैंने अपने स्विफ्ट निरंतर फ़ाइल में उस कोड को जोड़ा है:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    items.forEach {
        Swift.print($0, separator: separator, terminator: terminator)
    }
    #endif
}

0

यह मेरे लिए काम करता है (इस परियोजना में एक वैश्विक समारोह के रूप में जोड़ें)

func print(_ items: Any...) {
    #if DEBUG
        Swift.print(items[0])
    #endif
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.