Usuń println () w wydaniu wersji iOS Swift

84

Chciałbym globalnie zignorować wszystkie println()wywołania w moim kodzie Swift, jeśli nie jestem w kompilacji debugowania. Nie mogę znaleźć żadnych szczegółowych instrukcji krok po kroku i byłbym wdzięczny za wskazówki. czy jest jakiś sposób, aby to zrobić globalnie, albo muszę otaczać każdy println()ze #IF DEBUG/#ENDIFstwierdzeniami?

Nate Birkholz
źródło
6
print nie wyświetla już wyników w konsoli urządzenia, ale działa w konsoli debugera. Dlatego nie ma potrzeby usuwania w celu wydania wersji.
Anish Parajuli 웃
1
Od Xcode 8 i Swift 3 nie widzę wydruków w konsoli w trybie wydania.
CiNN

Odpowiedzi:

101

Najprostszym sposobem jest umieszczenie własnej funkcji globalnej przed Swift println:

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

Kiedy nadejdzie czas, aby zakończyć rejestrowanie, po prostu zakomentuj treść tej funkcji:

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

Lub możesz zrobić to automatycznie, używając warunku:

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

EDYCJA W Swift 2.0 printlnzostaje zmieniona na print. Niestety ma teraz zmienny pierwszy parametr; to jest fajne, ale oznacza to, że nie można go łatwo zastąpić, ponieważ Swift nie ma operatora „splat”, więc nie można przekazać kodu wariadycznego (można go utworzyć tylko dosłownie). Ale możesz stworzyć zredukowaną wersję, która działa, jeśli, jak to zwykle bywa, drukujesz tylko jedną wartość:

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

W Swift 3 musisz pominąć zewnętrzną etykietę pierwszego parametru:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}
matowe
źródło
3
Niezłe rozwiązanie, dzięki. Powiedziano mi, że w iOS (ale nie OS X) println()nie jest wykonywany w trybie wydania.
Nate Birkholz
13
@NateBirkholz Nie, to bzdury. (Powiedział, po testach, aby się upewnić!)
Matt
W Swift 2, ze zmienioną nazwą funkcji na print, czy po prostu zaryzykowałbyś dopasowanie funkcji? Jak by to zdefiniować globalnie? Próbowałem umieścić go poza moją klasą w AppDelegate i po prostu nigdy nie jest wywoływany, mimo że mam milion wywołań funkcji print (). Oto, czego próbowałem: func print (object: Any) {Swift.print (object)}
Charlie,
@Charlie Tak, nadal go używam ze printlnzmienioną na print. Powodem, dla którego to nie działa, jest to, że Twoja printdefinicja nie pasuje do języka Swift, więc jej nie zastępujesz. Występuje niewielki problem, ponieważ, jak wielokrotnie zauważano, Swift nie ma operatora splat, więc nie możesz przejść wariadyki. Ale działa dobrze w przypadku jednego elementu, który możesz przekazać jako items[0].
mat.
2
Jedno zastrzeżenie, jeśli wstawiasz te instrukcje dziennika do sekcji kodu o wysokiej wydajności: Swift nadal będzie spędzał czas na wykonywaniu interpolacji ciągów i renderowaniu parametrów w celu przekazania do funkcji, nawet jeśli nie będą one używane. Jedynym sposobem, w jaki widzę, aby naprawdę warunkowo usunąć instrukcje, jest orzeczenie ich na fladze. np. if (log) {print (..)} w każdym miejscu, w którym są używane.
Pat Niemeyer
46

Zaktualizowano dla Swift 4.x:

Ponieważ Swift 2.0 / 3.0 i Xcode 7/8 są teraz poza wersją beta, nastąpiły pewne zmiany w sposobie wyłączania funkcji drukowania w kompilacjach wydań.

Jest kilka ważnych punktów wymienionych powyżej przez @matt i @Nate Birkholz, które są nadal aktualne.

  1. println()Funkcja została zastąpiona przezprint()

  2. Aby użyć #if DEBUG makra, musisz zdefiniować "Swift Compiler - Custom Flags-Other Flags", aby zawierał wartość-D DEBUG

  3. Zalecałbym przesłonięcie Swift.print()funkcji w zakresie globalnym, aby można było używać print()funkcji w normalny sposób w kodzie, ale spowoduje to usunięcie danych wyjściowych dla kompilacji bez debugowania. Oto podpis funkcji, który możesz dodać w zakresie globalnym, aby zrobić to w Swift 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
    }
    

Uwaga: Domyślnym separatorem jest tutaj spacja, a domyślnym terminatorem jest znak nowej linii. Jeśli chcesz, możesz skonfigurować to inaczej w swoim projekcie.

Mam nadzieję że to pomoże.

Aktualizacja:

Zwykle lepiej jest umieścić tę funkcję w zakresie globalnym, tak aby znajdowała się przed printfunkcją Swift . Uważam, że najlepszym sposobem na zorganizowanie tego jest dodanie pliku narzędziowego do projektu (takiego jak DebugOptions.Swift), w którym można umieścić tę funkcję w zakresie globalnym.

Od wersji Swift 3 ++operator zostanie wycofany. Zaktualizowałem powyższy fragment, aby odzwierciedlić tę zmianę.

Glavid
źródło
1
Przepraszam, ale gdzie umieścić funkcję?
DàChún
@ User9527 Prawdopodobnie chcesz umieścić to gdzieś w zakresie globalnym, aby było dostępne w całym projekcie. W moich projektach dodaję plik Swift narzędzia (DebugOptions.swift lub coś podobnego) i umieszczam tę funkcję w zakresie globalnym (tj. Nie w zamkniętej klasie).
Glavid
Czy możesz potwierdzić, że od aktualnej wersji Swift-Xcode instrukcja print nie będzie już wyświetlana na konsoli urządzenia bez konieczności ustawiania opcji -D Debug na płasko? Przynajmniej to dzisiaj przetestowałem.
user523234
1
Od wersji Swift 3 można uzyskać nieco większą zwięzłość, dodając podkreślenie na początku listy argumentów: „print (_ items…”
Jonathan Zhan
7
Poszukałem więc odniesienia do wydruku (używanego w didFinishLaunching ...) i wskazało mi oryginalną funkcję drukowania Swift. Łącząc to i komentarz @ JonathanZhan, dostosowałem funkcję tak, aby wyglądała następująco i voila, działa:public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Jonny
38

Problem z wszystkimi tymi podejściami, w tym moim, polega na tym, że nie usuwają one narzutu związanego z oceną printargumentów. Bez względu na to, którego z nich używasz, będzie to drogie:

print(myExpensiveFunction())

Jedynym przyzwoitym rozwiązaniem jest zawinięcie rzeczywistego wywołania print w kompilację warunkową (załóżmy, że DEBUGjest to zdefiniowane tylko dla kompilacji debugowania):

#if DEBUG
print(myExpensiveFunction())
#endif

To i tylko to zapobiega myExpensiveFunctionwywoływaniu w kompilacji wydania.

Możesz jednak cofnąć ocenę o jeden poziom, używając funkcji automatycznego zamykania . W ten sposób możesz przepisać moje rozwiązanie (to jest Swift 3) w ten sposób:

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

To rozwiązuje problem tylko w przypadku, gdy drukujesz tylko jedną rzecz, co zwykle jest prawdą. Dzieje się tak, ponieważ item()nie jest wywoływana w trybie wydania. print(myExpensiveFunction())w ten sposób przestaje być drogie, ponieważ wywołanie jest zapakowane w zamknięcie bez oceny, aw trybie zwolnienia w ogóle nie będzie oceniane.

matowe
źródło
Jaki pożytek @autoclosure?
kelin
@matt w swojej książce wspominasz „Ważną cechą druku jest to, że jest on skutecznie tłumiony, gdy aplikacja jest uruchamiana niezależnie od Xcode”, czy to oznacza, że ​​możemy obecnie pozostawić nasze oświadczenia drukowane w naszych przesłanych aplikacjach, czy też nie rozumiem coś?
ukryta nazwa użytkownika
@ hidden-username Tak, zwykle zostawiam swoje printoświadczenia w kodzie wysyłki, ale różni się to od tego, czego dotyczy moja odpowiedź. Dane printwyjściowe instrukcji nie są wysyłane do konsoli w kompilacji wydania niezależnego od Xcode, ale nadal są oceniane , więc warto wiedzieć, jak zablokować tę ocenę na wypadek, gdyby była kosztowna lub ma niepożądane skutki uboczne.
mat.
@matt oh ok ... Tak, źle to zrozumiałem. Skomentuję je. Dzięki
ukryta nazwa użytkownika
Czy to podejście usunie wydrukowany ciąg z pliku binarnego? Na przykład, jeśli użyję tej metody i gdzieś w mojej aplikacji wstawię „print („ użytkownik zalogował się ”)”, a jeśli ktoś spróbuje odtworzyć moją aplikację, czy znajdzie gdzieś ten ciąg, czy w ogóle go nie będzie?
Leszek Szary
18

Jak już wspomniałem, jestem studentem i potrzebuję trochę jaśniejszego zdefiniowania rzeczy, aby dalej postępować. Po wielu badaniach sekwencja, którą musiałem śledzić, to:

Kliknij nazwę projektu u góry Nawigatora plików po lewej stronie okna projektu Xcode. To jest wiersz zawierający nazwę projektu, liczbę celów kompilacji i wersję zestawu SDK systemu iOS.

Wybierz kartę Ustawienia kompilacji i przewiń w dół do sekcji „ Swift Compiler - Flagi niestandardowe ” u dołu. Kliknij strzałkę w dół obok pozycji Inne flagi, aby rozwinąć sekcję.

Kliknij wiersz Debug , aby go zaznaczyć. Umieść kursor myszy po prawej stronie linii i kliknij dwukrotnie. Pojawi się lista. Kliknij przycisk + w lewym dolnym rogu widoku listy, aby dodać wartość. Pole tekstowe stanie się aktywne.

W polu tekstowym wprowadź tekst -D DEBUGi naciśnij klawisz Return, aby zatwierdzić wiersz.

Dodaj nowy plik Swift do swojego projektu. Będziesz chciał utworzyć niestandardową klasę dla pliku, więc wprowadź tekst w następujących wierszach:

class Log {

  var intFor : Int

  init() {
    intFor = 42
   }

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

Miałem dziś problem z zaakceptowaniem klasy przez Xcode, więc init może być nieco cięższy niż to konieczne.

Teraz będziesz musiał odwołać się do swojej niestandardowej klasy w dowolnej klasie, w której zamierzasz użyć nowej funkcji niestandardowej zamiast println()Dodaj to jako właściwość w każdej odpowiedniej klasie:

   let logFor = Log()

Teraz można zastąpić wszystkie wystąpienia println()z logFor.DLog(). Dane wyjściowe zawierają również nazwę funkcji, w której wywołano wiersz.

Zauważ, że wewnątrz funkcji klasowych nie mogłem wywołać funkcji, chyba że utworzyłem kopię funkcji jako funkcja klasy w tej klasie, a println()także jest nieco bardziej elastyczny z danymi wejściowymi, więc nie mogłem tego użyć w każdym przypadku w mój kod.

Nate Birkholz
źródło
8
Nie ma potrzeby tworzenia niestandardowej klasy dla dziennika debugowania. Korzystanie z funkcji globalnej jest łatwiejsze i bardziej praktyczne.
Vojtech Vrbka,
Jaki jest pożytek z intFor = 42?
Ted
15

Szybki 5

Po prostu utwórz nowy plik w swoim projekcie i wklej ten kod w:

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

Ta sygnatura funkcji jest zgodna z domyślną sygnaturą Swift, więc „zastępuje” funkcję w projekcie. W razie potrzeby nadal możesz uzyskać dostęp do oryginału za pomocą Swift.print().

Po dodaniu powyższego kodu używaj print()dalej jak zwykle, a będzie on drukowany tylko w kompilacjach debugowania.

Uwaga: Wykonanie polecenia, forEachaby wydrukować każdy element, usuwa irytujące nawiasy tablicowe wokół instrukcji print, które pojawiają się, jeśli przejdziesz itemsbezpośrednio do Swift.print().

Dla każdego stosunkowo nowego w Swifcie możesz się zastanawiać, co to $0jest do cholery . Po prostu reprezentuje pierwszy argument przekazany do forEachbloku. forEachOświadczenie można także zapisać w ten sposób:

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

Na koniec, jeśli jesteś zainteresowany, deklaracja Swift printwygląda następująco:

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

Moja odpowiedź powyżej odzwierciedla dokładną implementację Swift - chociaż nigdy nie drukuję więcej niż jednej rzeczy ani nie zmieniam separatora / terminatorów. Ale kto wie, może chcesz.

Trev14
źródło
2
gdzie zadeklarować tę funkcję, czy to jest jakieś rozszerzenie czy coś takiego? Po prostu nie chcę tego deklarować w każdym pliku)
Matrosov Alexander
1
@MatrosovAlexander Możesz po prostu utworzyć plik Swift w dowolnym miejscu projektu aplikacji i umieścić ten kod. Kompilator jest wystarczająco inteligentny, aby był dostępny globalnie.
Trev14
11

Oto funkcja, której używam, która działa doskonale w Swift 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
    }

Oto przykład generowanego wyniku:

zrzut ekranu wyjścia

Wyjaśnienie:

  • zielony znacznik wyboru służy do szybkiego przeglądania wiadomości drukowanych (gLog) w konsoli, gdzie czasami mogą one zgubić się w morzu innych wiadomości

  • znacznik czasu / daty

  • wątek, na którym jest uruchamiany - w moim przypadku jest to albo MainThread (który nazywam UI), albo nie MainThread (który nazywam BG, dla wątku w tle)

  • nazwa pliku, w którym znajduje się wiadomość gLog

  • funkcja w pliku, w którym znajduje się wiadomość gLog

  • numer wiersza komunikatu gLog

  • aktualna wiadomość gLog, którą chcesz wydrukować

Mam nadzieję, że przyda się to komuś innemu!

Gene Loparco
źródło
czy można to umieścić w osobnym pliku i używać go w całej aplikacji? Próbowałem umieścić go w oddzielnym pliku klasy, jako metodę klasową. Ale zawiesza się z libMobileGestalt MobileGestaltSupport.m: 153: pid 2574 (Demo) nie ma dostępu do piaskownicy dla frZQaeyWLUvLjeuEK43hmg i NIE MA odpowiedniego tytułu libMobileGestalt MobileGestalt.c: 550: brak dostępu do InverseDeviceID (patrz <rdar: // problem / 11744455 ) Wiadomość od debuggera:
zakończona z
omarojo, używam tego jako funkcji globalnej w całej mojej aplikacji. Żadne zajęcia nie są potrzebne. Mam plik o nazwie utils.swift, który zawiera wszystkie moje funkcje narzędziowe, takie jak ten. Musisz tylko upewnić się, że importujesz Foundation - być może to jest krok, który przegapiłeś? Przy okazji, aby uzyskać więcej informacji na temat deklarowania funkcji w klasach, jako funkcji statycznych w klasach lub jako funkcji globalnych, zobacz to pytanie i odpowiedzi SO: stackoverflow.com/questions/30197548/ ...
Gene Loparco
Tak, działało, po prostu tworząc nowy plik z funkcją w środku. Z jakiegoś powodu posiadanie jej jako funkcji klasy spowodowałoby awarię aplikacji bez wyraźnego komunikatu debugowania.
omarojo
Dzięki za tego człowieka, szkoda, że ​​wcześniej tego nie odkryłem. Oszczędziło mi wielu problemów związanych z debugowaniem.
beowulf
Moja przyjemność @beowulf!
Gene Loparco
9

Przetestowano za pomocą Swift 2.1 i Xcode 7.1.1

Istnieje łatwy sposób na wykluczenie wszystkich instrukcji print z wydanych wersji, gdy wiesz, że puste funkcje są usuwane przez kompilator Swift .

Uwaga dodatkowa: w erze Objective-C istniał wstępny parser, którego można było użyć do usunięcia instrukcji NSLog przed uruchomieniem kompilatora, jak opisano w mojej odpowiedzi tutaj . Ale ponieważ Swift nie ma już pre-parsera, to podejście nie jest już aktualne.

Oto, czego używam dzisiaj jako zaawansowanej i łatwo konfigurowalnej funkcji dziennika, bez martwienia się o jej usunięcie w kompilacjach wydań. Ponadto, ustawiając różne flagi kompilatora, możesz dostosować informacje, które są rejestrowane w razie potrzeby.

W razie potrzeby możesz dostosować tę funkcję, wszelkie sugestie dotyczące jej ulepszenia są mile widziane!

// 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
}

Oto miejsce, w którym ustawiasz flagi kompilatora:

wprowadź opis obrazu tutaj

Przykładowe wyjście ze wszystkimi flagami wygląda następująco:

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

Kod z log () wygląda następująco:

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

   // Handle the text field's user input through delegate callbacks
   nameTextField.delegate = self
}
Ronny Webers
źródło
Niezłe! Wziąłem to stąd i ostatecznie stworzyłem AELog i AEConsole .
tadija
To działa dobrze w trybie DEBUG. Teraz zmieniłem na tryb RELEASE z Edit Scheme. Pokazuje również okno logowania konsoli dla trybu wydania. Dlaczego tak?
Jayprakash Dubey
Dla Swift 3.2 w Xcode 9 musiałem zmienić NSLog na drukowanie i wywoływanie za pomocą logu (komunikat: "hello"), także musiałem wstawić flagi jako "-D" "kLOG_ENABLE", z cudzysłowami. Wszystkie inne aktualizacje szybkich wersji zostały pobrane przez kompilator z sugerowanymi poprawkami.
iCyberPaul,
1
Tutaj stwierdzasz, że „puste funkcje są usuwane przez kompilator Swift”, gdzie w dokumentacji to znajdujemy? Skąd wiesz, że tak jest? @ ronny-webers
zumzum
7

Jeszcze prostsze, po upewnieniu się, że -D DEBUGsą ustawione dla OTHER_SWIFT_FLAGSustawień kompilacji debugowania:

#if !DEBUG
    func print(_ items: Any..., separator: String = " ", terminator: String = "\n") { }
#endif
Rivera
źródło
Podejrzewam, że może to wymagać "gdzie", ponieważ obiekty do druku są zgodne z jednym z tych protokołów systemowych, o których rzadko wspomina się w filmach dla wwdc i myślę, że na końcu szybkiego przewodnika (ów) 1.2 vs 2 zapomniałem o różnicy, jeśli tam jest jeden z systemem jeden
Stephen J
Jak dotąd działa to ze Swift 1.2. Nie próbowałem 2.0.
Rivera
6

XCode 8 wprowadził kilka nowych ustawień kompilacji .
W szczególności jeden, o którym mowa, Active Compilation Conditionsdziała w podobny sposób, co ustawienia innych flag .

„Aktywne warunki kompilacji” to nowe ustawienie kompilacji służące do przekazywania flag kompilacji warunkowej do kompilatora Swift.

Zgodnie z XCode 8 (testowane w 8.3.2) otrzymasz to domyślnie:

wprowadź opis obrazu tutaj

Więc bez żadnej konfiguracji możesz napisać:

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

Zdecydowanie zalecam, aby w przypadku intensywnego stosowania tego podejścia utworzyć klasę / strukturę / funkcję, która otacza tę logikę rejestrowania. Możesz chcieć przedłużyć to dalej w dół drogi.

Javier Cadiz
źródło
4

Jak dotąd Varun Naharia ma lepsze rozwiązanie. Połączyłbym jego odpowiedź z odpowiedzią Rivery ...

  1. utwórz -D DEBUGflagę na dyrektywach kompilatora, ustawienia kompilacji.
  2. następnie dodaj ten kod:

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

Ten kod zamieni wszystko printw nic do wydania.

kaczka
źródło
3

Swift 4 Xcode 10.0.0

może mógłbyś tego użyć

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

Powodem użycia @autoclosurejest to, że jeśli przekażesz funkcję jako parametr wiadomości, funkcja zostanie wywołana tylko w trybie debugowania, spowoduje to spadek wydajności.

w przeciwieństwie do Swift.print(_ items: Any..., separator: String = default, terminator: String = default)funkcji, moje rozwiązanie ma tylko jeden parametr, ponieważ w większości przypadków nie przekazujemy wielu parametrów, ponieważ funkcja print wyświetla informacje tylko w konsoli, możemy po prostu przekonwertować parametry na String:, "\(param1)"+"\(param2)"prawda? mam nadzieję, że podoba ci się moje rozwiązanie

Jiangshi Fresh
źródło
1

Możesz także użyć punktu przerwania, ustawić go tak, aby był kontynuowany po ocenie i napisać komunikat drukowania w punkcie przerwania!

wprowadź opis obrazu tutaj

7RedBits.com
źródło
0

Możesz określić, debug_printlnczyja zawartość byłaby z grubsza:

#if DEBUG
  println()
#endif
Ian MacDonald
źródło
Dzięki, gdzie mogę to najlepiej zdefiniować? Jestem studentem, boję się i bardzo doceniam pomoc, ale wymagam bardziej wyraźnego kontekstu.
Nate Birkholz
Zadeklarowałbyś to w pliku nagłówkowym, który zaimportowałbyś do dowolnego miejsca, w którym chciałbyś go użyć.
Ian MacDonald
0

Moje rozwiązanie używa tego kodu w AppDelegate przed klasą

// 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 

}
Varun Naharia
źródło
0

dla mojego rozwiązania upraszczam

import UIKit

class DLog: NSObject {

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

   }

}

następnie, aby to pokazać, po prostu zadzwoń

_ = DLog(title:"any title", log:Any)
Wibowo Raditya Trilaksmono
źródło
0

Skończyło się na tym:

#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

Jest dość kompaktowy, wyświetla przydatne informacje (znacznik czasu, szybka nazwa pliku, linia kodu, nazwa funkcji) i przynajmniej w moich testach nie mogłem znaleźć żadnych zarejestrowanych ciągów w pliku binarnym aplikacji po otwarciu w edytorze szesnastkowym.

Leszek Szary
źródło
0

Jeszcze prostsze: wykorzystaj fakt, że potwierdzenia są usuwane z kompilacji wydania i dopiero stamtąd wywołują print. Spowoduje to usunięcie wszystkich wywołań dziennika (tak, nawet wywołań Log.da), ponieważ są one puste podczas budowania do wydania.

Słyszałem też, że wydruki są usuwane z kompilacji wydania, ale nie mogłem znaleźć tego na piśmie. Na razie używam czegoś takiego Logponiżej. Mam bardziej mięsistą wersję na GitHub z emoji (dla czytelności) i tematami dziennika (dla spójności):

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)
    }
}

W kodzie:

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

Widziane w obszarze debugowania Xcode tylko podczas uruchamiania kompilacji debugowania:

13: 36: 15.047 - jest to obsługiwane tylko w kompilacji do debugowania.

Johan
źródło
0

Mój projekt został opracowany w Objective C, ale od zeszłego roku zacząłem scalać nowy kod w Swift, więc w Swift poniższe rozwiązanie zadziałało, dodałem ten kod w pliku stałym My Swift:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    items.forEach {
        Swift.print($0, separator: separator, terminator: terminator)
    }
    #endif
}
PoojaArora
źródło
0

To działa dla mnie (dodaj to jako funkcję globalną w projekcie)

func print(_ items: Any...) {
    #if DEBUG
        Swift.print(items[0])
    #endif
}
harryngh
źródło