Apakah saya perlu menonaktifkan NSLog sebelum merilis Aplikasi?

117

Saat merilis aplikasi untuk iPhone, jika saya menonaktifkan, apakah NSLog();kinerjanya akan lebih baik?

RAGOpoR
sumber
1
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:

#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... ) 
#endif

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.

Ramin
sumber
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
   #define NSLog(...);
#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.

#define NSLog(...);

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.

Ronny Webers
sumber
1
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.

Referensi dari sini .

Andrew
sumber
23

Favorit pribadi saya adalah menggunakan makro variadic.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
Eytan
sumber
1
Di mana Anda meletakkan ini?
pengguna6631314
20

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 .

Nicolas Miari
sumber
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

Pengaturan Default Proyek

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 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif
AechoLiu
sumber
5

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... ;-)

Ben Gotow
sumber
5

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 :

#define NSLog(...)

( 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

#undef NSLog

Misalnya, Anda dapat mencegah panggilan ke NSLog di sekitar grup metode tertentu dengan melakukan sesuatu seperti

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
tidak tersinkronisasi
sumber
3

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".

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
papahabla
sumber
2

dalam file pch tuliskan ini sebelum #endif

#define NSLog() //
Sandeep Saurabh
sumber
0

bagaimana dengan ini?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    
roberto.buratti
sumber
1
ini menonaktifkan keluaran, tetapi tidak menghemat waktu pemrosesan, yaitu NSLog masih dipanggil dan argumennya diurai
dwery
0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

Ini akan menerima argumen tambahan juga .. Cukup nilai parameter showDebugLogs ke true atau false, sesuai kebutuhan Anda

Zahur
sumber
Ini bagus, tetapi masih memiliki masalah semua overhead panggilan dan overhead (dan potensi efek samping) dari komputasi argumen yang diteruskan ke Dlogfungsi.
Todd Lehman