Dalam proyek saya saat ini, saya menggunakan UALogger . Itu tidak masuk produksi , jika Anda tidak memintanya secara eksplisit. Dan memiliki manfaat lain dibandingkan NSLog biasa seperti tingkat keparahan (dengan DEBUG , INFO , dll) di luar kotak. Kerja bagus!
Anton Gaenko
1
Untuk menjawab pertanyaan Anda tentang "apakah akan bekerja lebih baik?" Ya, tetapi hasil yang Anda peroleh bergantung pada berapa banyak yang NSLog()Anda miliki di seluruh aplikasi Anda. NSLog()membutuhkan waktu untuk mengeksekusi dan menambahkan overhead tambahan ke runtime aplikasi Anda. Bagaimanapun, jika itu membantu dalam kinerja dengan makro preprocessor DEBUG sederhana, maka kita harus menonaktifkannya.
Scott
Saya juga menyarankan jika Anda memiliki banyak pernyataan NSLog / print dalam kode Anda, ini mungkin menyarankan Anda untuk meluangkan waktu mempelajari lebih lanjut tentang debugger. Saya secara teratur menetapkan breakpoint yang mencetak informasi yang saya minati, dan melanjutkan secara otomatis. Ya, ini bisa sedikit memperlambat lari, tetapi dalam banyak kasus tidak berlebihan. Juga, jeda bersyarat sehingga Anda dapat menyelidiki ketika sesuatu yang tidak terduga terjadi.
bshirley
Jawaban:
127
Salah satu cara untuk melakukannya adalah dengan masuk ke pengaturan Build Anda dan di bawah konfigurasi Debug tambahkan nilai ke nilai "Makro Preprocessor" seperti:
DEBUG_MODE=1
Pastikan Anda hanya melakukan ini untuk konfigurasi Debug dan bukan untuk versi Beta atau Rilis. Kemudian di file header umum Anda dapat melakukan sesuatu seperti:
Sekarang bukannya NSLog digunakan di DLogmana-mana. Saat menguji dan men-debug, Anda akan mendapatkan pesan debug. Saat Anda siap untuk merilis beta atau rilis final, semua DLogbaris itu secara otomatis menjadi kosong dan tidak ada yang dipancarkan. Dengan cara ini tidak ada pengaturan manual variabel atau komentar yang NSLogsdiperlukan. Memilih target build Anda akan menanganinya.
Di Xcode 4.5 memberikan peringatan yang mengatakan: "Deklarasi implisit dari fungsi 'DLog' tidak valid di C99" jadi hal ini tidak berfungsi.
Sergey Grischyov
2
@SergiusGee: Anda mendapatkan peringatan deklarasi implisit jika deklarasi untuk fungsi tersebut tidak dapat ditemukan, dalam hal ini ia mengira Anda mencoba mendeklarasikannya. Pastikan kelas Anda memiliki akses ke file header tempat ini dideklarasikan.
sudo rm -rf
1
Saya tidak akan melakukan logout karena merampas kemampuan Anda untuk menerima laporan kesalahan yang lebih baik dari pengguna. gunakan async logging dan logLevels untuk membatasi kinerja yang dicapai hampir nol! (lihat penebang kakao atau java's log4j
Daij-Djan
2
Saya akan memilih #if daripada #ifdef, karena DEBUG_MODE 0 masih akan melalui jalur yang benar
Grady Player
1
ini tidak menjawab pertanyaan
Martin Mlostek
117
Pembaruan untuk Xcode 5 & iOS 7
catatan: untuk solusi Xcode 7 / Swift 2.1 untuk menghapus pernyataan print () dalam rilis build, temukan jawaban saya di sini .
Ya, Anda harus menghapus pernyataan NSLog apa pun dalam kode rilis Anda, karena itu hanya memperlambat kode Anda, dan tidak ada gunanya dalam versi rilis. Untungnya, di Xcode 5 (iOS 7), sangat mudah untuk menghapus semua pernyataan NSLog Anda 'secara otomatis' dalam build rilis. Jadi mengapa tidak melakukannya.
Pertama, 3 langkah yang harus diambil, lalu beberapa penjelasan
1) di proyek Xcode Anda, cari file 'yourProjectName-prefix.pch' (biasanya Anda akan menemukannya di bawah grup 'file pendukung', di mana file main.m Anda berada
2) tambahkan 3 baris ini di akhir file '.pch':
#ifndef DEBUG
#defineNSLog(...);#endif
3) uji perbedaan antara versi 'debug' dan 'rilis' Anda. Salah satu cara untuk melakukannya adalah melalui 'edit skema' -> 'jalankan nama aplikasi' -> di bawah tab 'info' pilih menggunakan kotak drop-down antara debug & rilis. Dalam versi rilis, Anda tidak akan melihat keluaran NSLog di konsol debug!
bagaimana ini semua bekerja?
Pertama-tama, kita harus tahu bahwa preprocessor relatif 'dumb', dan hanya bertindak sebagai 'text replacer' sebelum compiler dipanggil. Ini menggantikan apa pun yang Anda '#definikan' dengan apa yang mengikuti #definepernyataan tersebut.
#defineNSLog(...);
The (...)singkatan dari 'sesuatu' antara kurung (). Pikiran juga ;di akhir. Ini tidak benar-benar diperlukan karena kompiler akan mengoptimalkannya, tetapi saya ingin meletakkannya di sana, karena ini lebih 'benar'. Setelah kita #definetidak ada 'nothing', maka preprocessor akan menggantinya dengan 'nothing', dan itu hanya akan membuang baris lengkapnya, mulai dari NSLog...sampai dan termasuk ;.
mendefinisikan pernyataan dapat dibuat bersyarat menggunakan #ifdef(jika ditentukan) atau #ifndef(jika tidak ditentukan)
di sini kami menulis #ifndef DEBUG, yang artinya 'jika simbol DEBUG tidak ditentukan'. The #ifdefatau #ifndefkebutuhan untuk menjadi 'tertutup' dengan#endif
Xcode 5 secara default mendefinisikan simbol 'DEBUG' untuk kita ketika mode de build adalah 'DEBUG'. Dalam 'rilis' ini tidak ditentukan. Anda dapat memverifikasi ini di bawah pengaturan proyek Anda, tab 'Build settings' -> gulir ke bawah ke bagian 'Apple LLVM 5.0 - Preprocessing' -> makro preprocessor. Anda akan melihat bahwa simbol 'DEBUG' tidak ditentukan untuk rilis build!
akhirnya, file .pch dibuat oleh Xcode secara otomatis, dan secara otomatis disertakan dalam setiap file sumber selama waktu kompilasi. Jadi seolah-olah Anda akan memasukkan #definesemuanya ke dalam setiap file sumber Anda.
Terima kasih @Whasssaaahhh, ini berfungsi dengan baik. Berhati-hatilah untuk menghindari memasukkan kode dalam pernyataan log! Praprosesor akan menghapus seluruh NSLogpernyataan tanpa menghiraukan apa yang ada di dalamnya.
Eric Platon
1
Jika ini adalah proyek lama yang tidak memiliki tanda debug di makro preprocesssor, penting untuk menambahkan "debug = 1" untuk proyek dan bukan target
Priebe
1
Juga, jangan menggunakan NSLogsebagai pernyataan apa-apa do, misalnya if(AllCool) NSLog(@"Cool!Do Nothing!"); else...bukan pop NSLogdalam beberapa kurung keritingif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
Arcady bob
33
Hampir semua jawaban di atas menyarankan solusi tetapi tidak menjelaskan masalahnya. Saya melakukan pencarian di google, dan menemukan alasannya. Inilah jawaban saya:
Ya, jika Anda mengomentari NSLog dalam versi rilis Anda, kinerja akan menjadi lebih baik. Karena NSLog cukup lambat. Mengapa? NSLog akan melakukan dua hal 1) menulis pesan log ke Apple System Logging (ASL), 2) jika aplikasi berjalan di xcode, ia juga menulis ke stderr.
Masalah utamanya terletak pada yang pertama. Untuk mencapai thread safe, setiap kali NSLog dipanggil, NSLog membuka koneksi ke fasilitas ASL , mengirim pesan, dan menutup koneksi. Operasi koneksi sangat mahal. Alasan lainnya adalah NSLog meluangkan waktu untuk mendapatkan stempel waktu untuk masuk.
Selain semua orang yang dengan bijak berkomentar bahwa tidak menelepon NSLog()sama sekali dalam produksi berjalan sedikit lebih cepat, saya akan menambahkan bahwa:
Semua NSLog()string output tersebut dapat dilihat oleh siapa saja yang mengunduh aplikasi Anda dari store dan menjalankannya dengan perangkat yang dicolokkan ke mac yang menjalankan Xcode (melalui jendela Organizer).
Bergantung pada informasi apa yang Anda catat (dan terutama jika aplikasi Anda menghubungi server, melakukan otentikasi, dll.), Ini bisa menjadi masalah keamanan yang serius .
terima kasih atas infonya - apakah ini di dokumen di suatu tempat, atau baru saja Anda temukan sendiri? Apakah masih benar untuk pencetakan di Swift?
Ronny Webers
Saya tidak ingat membaca dokumentasi apa pun. Saya baru saja menginstal build yang diarsipkan (biner yang sama dengan yang saya kirimkan ke toko) di perangkat saya dan menghubungkannya ke Xcode. Saya tidak tahu apakah itu sama untuk Swift print(), tetapi kemungkinan besar begitu.
Nicolas Miari
@NicolasMiari Apa yang Anda maksud dengan dicolokkan ke Xcode? Bagaimana kita bisa memasukkan biner kita ke Xcode, sebenarnya saya ingin mencoba hal yang sama. Jadi tolong sarankan. Terima kasih.
iDevAmit
@iDeveloper Maksud saya unduh aplikasi Anda dari AppStore ke perangkat (mis., iPhone), colokkan perangkat itu ke Xcode melalui USB, luncurkan aplikasi Anda dan perhatikan log di jendela "Perangkat" Xcode.
Nicolas Miari
3
@Whasssaaahhh print tidak keluar di konsol perangkat..saya baru saja mengujinya
Anish Parajuli 웃
13
Di dalam pengaturan default proyek saat ini di Xcode, NS_BLOCK_ASSERTIONSmakro akan disetel ke 1 dalam versi rilis, dan DEBUG=1dalam versi Debug.
Jadi, saya lebih suka metode berikut.
// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.#ifndef NS_BLOCK_ASSERTIONS
#define _DEBUG
#endif#ifdef _DEBUG
// for debug mode #defineDLog(fmt,...)NSLog(@"%s " fmt, __FUNCTION,##__VA_ARGS__) .../// something extra#else// for release mode#defineDLog(fmt,...)/* throw it away */.../// something extra#endif
Ya, Anda harus menonaktifkannya. Terutama jika Anda mencoba memaksimalkan kecepatan kode Anda. NSLogging hal-hal kiri dan kanan mencemari log sistem yang mungkin coba digali oleh pengembang lain dan itu dapat berdampak besar pada kode kritis-kecepatan (di dalam loop, dll ..) Saya secara tidak sengaja meninggalkan beberapa pesan log dalam fungsi rekursif sekali dan harus merilis pembaruan dengan "peningkatan kecepatan 30%!" beberapa minggu kemudian... ;-)
Semua jawaban bagus, namun inilah trik kecil lain yang dapat Anda pertimbangkan untuk digunakan, terutama dalam fase pengembangan / pengujian aplikasi Anda.
Ini juga bisa berguna untuk kode rilis aplikasi, jika Anda hanya ingin mengubah kode debug ANDA, dan bukan pesan yang mungkin menunjukkan masalah di luar kontrol langsung kode Anda.
Trik-nya:
Anda dapat mematikan NSLog per file .m hanya dengan memasukkan baris berikut di bagian atas file .m :
#defineNSLog(...)
( CATATAN: JANGAN taruh ini file .h, hanya file .m! )
Ini hanya membuat compiler mengevaluasi NSLog()dengan memperluas makro preprocessor Anda. Makro tidak melakukan apa pun selain menghapus argumen.
jika Anda ingin menyalakannya kembali, Anda selalu dapat menggunakan
#undefNSLog
Misalnya, Anda dapat mencegah panggilan ke NSLog di sekitar grup metode tertentu dengan melakukan sesuatu seperti
NSLog lambat dan sebaiknya tidak digunakan untuk build rilis. Makro sederhana seperti di bawah ini akan menonaktifkannya bersama dengan pernyataan apa pun yang mungkin Anda miliki yang juga harus dinonaktifkan. Dalam kasus yang kurang umum saat Anda menginginkan NSLog dalam rilis build, panggil saja secara langsung. Jangan lupa untuk menambahkan "-DNDEBUG" ke pengaturan build "flag c lainnya".
Ini bagus, tetapi masih memiliki masalah semua overhead panggilan dan overhead (dan potensi efek samping) dari komputasi argumen yang diteruskan ke Dlogfungsi.
NSLog()
Anda miliki di seluruh aplikasi Anda.NSLog()
membutuhkan waktu untuk mengeksekusi dan menambahkan overhead tambahan ke runtime aplikasi Anda. Bagaimanapun, jika itu membantu dalam kinerja dengan makro preprocessor DEBUG sederhana, maka kita harus menonaktifkannya.Jawaban:
Salah satu cara untuk melakukannya adalah dengan masuk ke pengaturan Build Anda dan di bawah konfigurasi Debug tambahkan nilai ke nilai "Makro Preprocessor" seperti:
Pastikan Anda hanya melakukan ini untuk konfigurasi Debug dan bukan untuk versi Beta atau Rilis. Kemudian di file header umum Anda dapat melakukan sesuatu seperti:
Sekarang bukannya
NSLog
digunakan diDLog
mana-mana. Saat menguji dan men-debug, Anda akan mendapatkan pesan debug. Saat Anda siap untuk merilis beta atau rilis final, semuaDLog
baris itu secara otomatis menjadi kosong dan tidak ada yang dipancarkan. Dengan cara ini tidak ada pengaturan manual variabel atau komentar yangNSLogs
diperlukan. Memilih target build Anda akan menanganinya.sumber
Pembaruan untuk Xcode 5 & iOS 7
catatan: untuk solusi Xcode 7 / Swift 2.1 untuk menghapus pernyataan print () dalam rilis build, temukan jawaban saya di sini .
Ya, Anda harus menghapus pernyataan NSLog apa pun dalam kode rilis Anda, karena itu hanya memperlambat kode Anda, dan tidak ada gunanya dalam versi rilis. Untungnya, di Xcode 5 (iOS 7), sangat mudah untuk menghapus semua pernyataan NSLog Anda 'secara otomatis' dalam build rilis. Jadi mengapa tidak melakukannya.
Pertama, 3 langkah yang harus diambil, lalu beberapa penjelasan
1) di proyek Xcode Anda, cari file 'yourProjectName-prefix.pch' (biasanya Anda akan menemukannya di bawah grup 'file pendukung', di mana file main.m Anda berada
2) tambahkan 3 baris ini di akhir file '.pch':
3) uji perbedaan antara versi 'debug' dan 'rilis' Anda. Salah satu cara untuk melakukannya adalah melalui 'edit skema' -> 'jalankan nama aplikasi' -> di bawah tab 'info' pilih menggunakan kotak drop-down antara debug & rilis. Dalam versi rilis, Anda tidak akan melihat keluaran NSLog di konsol debug!
bagaimana ini semua bekerja?
Pertama-tama, kita harus tahu bahwa preprocessor relatif 'dumb', dan hanya bertindak sebagai 'text replacer' sebelum compiler dipanggil. Ini menggantikan apa pun yang Anda '#definikan' dengan apa yang mengikuti
#define
pernyataan tersebut.The
(...)
singkatan dari 'sesuatu' antara kurung (). Pikiran juga;
di akhir. Ini tidak benar-benar diperlukan karena kompiler akan mengoptimalkannya, tetapi saya ingin meletakkannya di sana, karena ini lebih 'benar'. Setelah kita#define
tidak ada 'nothing', maka preprocessor akan menggantinya dengan 'nothing', dan itu hanya akan membuang baris lengkapnya, mulai dariNSLog...
sampai dan termasuk;
.mendefinisikan pernyataan dapat dibuat bersyarat menggunakan
#ifdef
(jika ditentukan) atau#ifndef
(jika tidak ditentukan)di sini kami menulis
#ifndef DEBUG
, yang artinya 'jika simbol DEBUG tidak ditentukan'. The#ifdef
atau#ifndef
kebutuhan untuk menjadi 'tertutup' dengan#endif
Xcode 5 secara default mendefinisikan simbol 'DEBUG' untuk kita ketika mode de build adalah 'DEBUG'. Dalam 'rilis' ini tidak ditentukan. Anda dapat memverifikasi ini di bawah pengaturan proyek Anda, tab 'Build settings' -> gulir ke bawah ke bagian 'Apple LLVM 5.0 - Preprocessing' -> makro preprocessor. Anda akan melihat bahwa simbol 'DEBUG' tidak ditentukan untuk rilis build!
akhirnya, file .pch dibuat oleh Xcode secara otomatis, dan secara otomatis disertakan dalam setiap file sumber selama waktu kompilasi. Jadi seolah-olah Anda akan memasukkan
#define
semuanya ke dalam setiap file sumber Anda.sumber
NSLog
pernyataan tanpa menghiraukan apa yang ada di dalamnya.NSLog
sebagai pernyataan apa-apa do, misalnyaif(AllCool) NSLog(@"Cool!Do Nothing!"); else...
bukan popNSLog
dalam beberapa kurung keritingif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
Hampir semua jawaban di atas menyarankan solusi tetapi tidak menjelaskan masalahnya. Saya melakukan pencarian di google, dan menemukan alasannya. Inilah jawaban saya:
Ya, jika Anda mengomentari NSLog dalam versi rilis Anda, kinerja akan menjadi lebih baik. Karena NSLog cukup lambat. Mengapa? NSLog akan melakukan dua hal 1) menulis pesan log ke Apple System Logging (ASL), 2) jika aplikasi berjalan di xcode, ia juga menulis ke stderr.
Masalah utamanya terletak pada yang pertama. Untuk mencapai thread safe, setiap kali NSLog dipanggil, NSLog membuka koneksi ke fasilitas ASL , mengirim pesan, dan menutup koneksi. Operasi koneksi sangat mahal. Alasan lainnya adalah NSLog meluangkan waktu untuk mendapatkan stempel waktu untuk masuk.
Referensi dari sini .
sumber
Favorit pribadi saya adalah menggunakan makro variadic.
sumber
Selain semua orang yang dengan bijak berkomentar bahwa tidak menelepon
NSLog()
sama sekali dalam produksi berjalan sedikit lebih cepat, saya akan menambahkan bahwa:Semua
NSLog()
string output tersebut dapat dilihat oleh siapa saja yang mengunduh aplikasi Anda dari store dan menjalankannya dengan perangkat yang dicolokkan ke mac yang menjalankan Xcode (melalui jendela Organizer).Bergantung pada informasi apa yang Anda catat (dan terutama jika aplikasi Anda menghubungi server, melakukan otentikasi, dll.), Ini bisa menjadi masalah keamanan yang serius .
sumber
print()
, tetapi kemungkinan besar begitu.Di dalam pengaturan default proyek saat ini di Xcode,
NS_BLOCK_ASSERTIONS
makro akan disetel ke 1 dalam versi rilis, danDEBUG=1
dalam versi Debug.Jadi, saya lebih suka metode berikut.
sumber
Ya, Anda harus menonaktifkannya. Terutama jika Anda mencoba memaksimalkan kecepatan kode Anda. NSLogging hal-hal kiri dan kanan mencemari log sistem yang mungkin coba digali oleh pengembang lain dan itu dapat berdampak besar pada kode kritis-kecepatan (di dalam loop, dll ..) Saya secara tidak sengaja meninggalkan beberapa pesan log dalam fungsi rekursif sekali dan harus merilis pembaruan dengan "peningkatan kecepatan 30%!" beberapa minggu kemudian... ;-)
sumber
Semua jawaban bagus, namun inilah trik kecil lain yang dapat Anda pertimbangkan untuk digunakan, terutama dalam fase pengembangan / pengujian aplikasi Anda.
Ini juga bisa berguna untuk kode rilis aplikasi, jika Anda hanya ingin mengubah kode debug ANDA, dan bukan pesan yang mungkin menunjukkan masalah di luar kontrol langsung kode Anda.
Trik-nya:
Anda dapat mematikan NSLog per file .m hanya dengan memasukkan baris berikut di bagian atas file .m :
( CATATAN: JANGAN taruh ini file .h, hanya file .m! )
Ini hanya membuat compiler mengevaluasi
NSLog()
dengan memperluas makro preprocessor Anda. Makro tidak melakukan apa pun selain menghapus argumen.jika Anda ingin menyalakannya kembali, Anda selalu dapat menggunakan
Misalnya, Anda dapat mencegah panggilan ke NSLog di sekitar grup metode tertentu dengan melakukan sesuatu seperti
sumber
NSLog lambat dan sebaiknya tidak digunakan untuk build rilis. Makro sederhana seperti di bawah ini akan menonaktifkannya bersama dengan pernyataan apa pun yang mungkin Anda miliki yang juga harus dinonaktifkan. Dalam kasus yang kurang umum saat Anda menginginkan NSLog dalam rilis build, panggil saja secara langsung. Jangan lupa untuk menambahkan "-DNDEBUG" ke pengaturan build "flag c lainnya".
sumber
dalam file pch tuliskan ini sebelum #endif
sumber
bagaimana dengan ini?
sumber
Ini akan menerima argumen tambahan juga .. Cukup nilai parameter showDebugLogs ke true atau false, sesuai kebutuhan Anda
sumber
Dlog
fungsi.