Debug Lanjutan

Debug Area adalah fitur yang berguna dalam karya pengembang iOS di Xcode. Segera setelah kami mulai menguasai pengembangan untuk iOS, dan mencoba untuk menjauh dari metode cetak yang akrab dan dicintai, dan menemukan metode yang lebih cepat dan lebih nyaman untuk memahami keadaan sistem dalam periode tertentu, kami mulai mempelajari Area Debug.

Kemungkinan besar, di Debug panel mata Anda akan jatuh sebelum Anda memahami apa yang sebenarnya terjadi di sana. Ketika aplikasi mogok untuk pertama kalinya, menu yang lebih rendah terbuka secara otomatis, awalnya dapat membantu untuk memahami masalah (ingat kesalahan lama "Fatal: Indeks di luar jangkauan"), pada dasarnya di awal Anda tidak akan mengerti apa yang diinginkan Xcode dari kami dan google itu kesalahan, tetapi dalam perjalanan pertumbuhan semakin banyak informasi akan menjadi jelas.

Sejak awal, programmer mencoba mengoptimalkan karyanya. Untuk melakukan ini, kami berusaha memahami pada titik mana program kami masuk ke kondisi yang salah. Dan di sini, tergantung pada titik di mana evolusi programmer berada, metodenya dapat bervariasi. Pertama, bagaimana Debug dilakukan dengan benar dengan metode "print ()", kemudian Breakpoints ditempatkan dan metode "po" dipanggil, kemudian dibiasakan dengan Debug Variable Input (area di sebelah konsol dalam Xcode), dan kemudian muncul pemahaman tentang bagaimana mengkompilasi kode saat berhenti. Metode breakpoint - "ekspresi" (Setidaknya itulah evolusi yang saya miliki).

Mari kita coba berbagai cara yang akan membantu kita memahami dan mengubah keadaan aplikasi kita. Yang paling sederhana seperti "print ()", dan "po" tidak akan dipertimbangkan, saya pikir Anda sudah memahami esensi mereka dan tahu bagaimana menerapkannya.

Mari kita buat aplikasi sederhana dengan satu layar di mana kita hanya akan memiliki satu jenis sel (TableViewcell) dengan dua elemen di dalamnya: UIImageView dan UILabel. Dalam sel kita akan menulis nomor seri, dan menempatkan image1 atau image2 di dalam gambar.

Metode tableViewCellForRowAtIndexPath akan membuat sel untuk kita, meletakkan data dan kembali:

gambar

Metode ini akan menghasilkan tabel berikut:

gambar

Breakpoint


Mari kita hentikan program kami dan menambahkan beberapa teks ke Label kami.

1. Atur Breakpoint:

gambar

2. Program menghentikan eksekusi pada baris 55, segera setelah teks diberikan. Karena kita berada pada garis yang terletak di bidang tampilan sel, kita dapat berinteraksi dengan sel kita.

3. Kami menulis di konsol perintah untuk mengubah teks sel:

gambar

4. Kami menghapus Breakpoint kami dan menekan tombol "melanjutkan eksekusi program."

5. Pada layar ponsel kita, kita melihat bahwa semuanya ternyata berhasil:

gambar

ekspresi mengeksekusi ekspresi dan mengembalikan nilai pada utas saat ini.

Breakpoint yang diedit


Tetapi, bagaimana jika kita perlu mengubah teks dalam jumlah besar sel? Atau sudahkah kita menyadari dalam proses pelaksanaan program yang perlu kita ubah?

Kami dapat mengoptimalkan pelaksanaan operasi ini dan mempercepat pekerjaan sedikit, membuat teks berubah menjadi sel ketika mencapai Breakpoint dan terus menjalankan program, ini akan menghemat banyak waktu dan memungkinkan kami untuk tidak mencetak hal yang sama untuk setiap sel.

Untuk melakukan ini, kita perlu sedikit memodifikasi Breakpoint kita, menambahkan kode tambahan di sana, yang akan mengubah teksnya di zona visibilitas sel kita dan melanjutkan program.

  1. Buat breakpoint.
  2. Klik kiri pada panah breakpoint.
  3. Klik Edit Breakpoint.
  4. Kondisi - kondisi di mana Breakpoint akan bekerja, sekarang kita tidak membutuhkannya.
  5. Abaikan - berapa kali untuk melewati Breakpoint sebelum berfungsi (juga bukan itu).
  6. Tapi Aksi adalah yang kita butuhkan, pilih jenis tindakan Perintah Debugger.
  7. Kami menulis ekspresi yang perlu kami eksekusi:
  8. ekspresi cell.desriptionTextOutlet.text = "\ (indexPath.item) misi selesai".
  9. Beri tanda centang - Lanjutkan eksekusi setelah perintah berhasil diselesaikan.

gambar

9. Kami berusaha.

gambar

Ini sukses, ternyata mengubah teks untuk setiap sel selama pembentukan tabel, dan kami tidak harus mengorbankan waktu dan meresepkan operasi untuk masing-masing.

Fungsi breakpoint


Selalu ada saat-saat ketika sesuatu terjadi dalam aplikasi kita yang tidak dapat kami jelaskan, teksnya tidak berubah atau berubah lebih dari yang diperlukan, sepertinya Breakpoint dalam kasus ini tidak memiliki tempat untuk meletakkannya. Tapi ini tidak sepenuhnya benar, jika Anda tahu Obj-C, dan Anda tahu metode mana yang dijalankan kompiler yang ingin Anda lacak, Anda bisa meletakkan Breakpoint di atasnya dan saat metode berikutnya dipanggil, aplikasi berhenti dalam proses menjalankan kode Assembler.

1. Di navigator Breakpoint, pilih Symbolic Breakpoint.

gambar

2. Kami ingin melacak metode pengaturan teks di sel, tulis - [UILabel setText:].

gambar

3. Argumen nol tidak ada, dan penghitungan dimulai dari yang pertama. Metode pertama yang ditangkap bukan yang kita butuhkan (kita atur waktu saat ini ke status bar), tetapi yang kedua hanya milik kita:

4. Di bawah "$ arg1" deskripsi objek disimpan.

5. Di bawah "$ arg2" fungsi pemilih disimpan.

6. Di bawah "$ arg3" teks yang diperoleh dengan metode ini disimpan.

Ok, ini sepertinya sudah jelas. Tetapi kadang-kadang ada situasi ketika tidak terbatas pada pengaturan satu teks di bilah status, dan Anda perlu melacak eksekusi metode pada pengontrol tertentu, apa yang harus dilakukan? Anda dapat mengaktifkan Breakpoint mirip dengan yang kami instal sebelumnya, tetapi mengatur posisinya dalam kode. Apa artinya ini? Kami tahu pasti bahwa tampilan kami akan muncul ketika kami menginstal teks dalam sel, jadi masalahnya adalah untuk meletakkannya di viewDidLoad atau setelah membuat sel.

Untuk membuat breakpoint, kami mengaturnya di baris, dan dalam aksi kami menulis kode berikut:

breakpoint set --one-shot true --name "-[UILabel setText:]” 

breakpoint set β€”one-shot true - buat breakpoint
β€”name adalah nama dari breakpoint karakter
β€œ-[UILabel setText:]” disebut metode

Inilah yang terjadi:

gambar

Lewati garis



Tetapi bagaimana jika kita mencurigai bahwa beberapa baris kode merusak seluruh program kita? Selama eksekusi kode, Anda dapat menghindari mengeksekusi baris kode tertentu seperti ini:

  1. Kami menempatkan breakpoint pada garis yang tidak ingin kami jalankan.
  2. Saat eksekusi berhenti, seret ke baris yang ingin kami lanjutkan eksekusi program (lucu, tetapi tidak selalu berhasil, opsi tanpa menyeret lebih rendah).

Ada juga opsi lain yang akan mengoptimalkan lompatan garis - ini adalah resep dari perintah yang sesuai di "edit breakpoint". Tim ini berisiko, karena esensi lompatan tersebut adalah untuk menyelamatkan kami dari pembangunan kembali, tetapi jika Anda melewatkan inisialisasi objek dan mencoba untuk menghubunginya, program akan macet.

gambar

Mari kita hentikan program kita untuk menginisialisasi gambar, dan kita tidak akan menetapkan gambar sama sekali untuk sel, untuk ini kita perlu melewati lima baris kode dan mengembalikan sel tanpa gambar, untuk ini kita melewatkan eksekusi dari lima baris kode berikut pada utas saat ini, dan melanjutkan program:

gambar

Kedengarannya bagus, tapi saya masih ingin memberikan gambar, mari kita tambahkan metode penugasan ke breakpoint:

gambar

Kombinasi yang baik, sekarang kami hanya memiliki satu jenis gambar di setiap sel.

Titik Pantau


Fungsi lain yang mudah digunakan dalam debugger adalah melacak nilai-nilai dalam program, titik pantauan. Watchpoint agak mirip dengan KVO, kami menetapkan breakpoint untuk mengubah keadaan suatu objek, dan setiap kali ia mengubah keadaannya, proses eksekusi program berhenti, dan kami dapat melihat nilai dan tempat-tempat dari mana dan oleh siapa nilai tersebut diubah. Sebagai contoh, saya meletakkan titik pengawas pada sel untuk mencari tahu apa yang terjadi ketika sebuah tabel di-paging dan sebuah sel baru diinisialisasi. Daftar perintah ternyata sangat besar, jadi saya tidak akan memberikannya untuk menyebutkan beberapa: pelaksanaan tampilan tata letak yang terletak di dalam sel dan pengaturan kendala, animasi, pengaturan keadaan untuk sel dan banyak lagi.

Untuk mengatur titik tontonan ke nilai, Anda harus menghentikan program breakpoint dalam lingkup properti yang ingin Anda monitor, pilih properti di panel "variabel debug" dan pilih arloji "<parameter>".

gambar

Untuk menghapus titik tontonan dengan variabel, Anda perlu melihat ke navigator breakpoint, di sana bersama dengan sisa breakpoint akan menjadi titik tontonan kami.

Breakpoint UI Change


Terkadang kita perlu belajar lebih banyak tentang objek yang ingin kita tolak. Pilihan termudah adalah menggunakan "po" untuk menampilkan informasi tentang objek, dan melihat lokasi objek dalam memori di tempat yang sama. Tapi itu terjadi bahwa kita tidak memiliki tautan langsung ke objek, itu tidak diwakili dalam tampilan API, di mana terletak atau mungkin disembunyikan oleh perpustakaan. Salah satu opsi adalah menggunakan Hierarki Tampilan, tetapi ini tidak selalu nyaman dan tidak selalu sulit untuk memahami bahwa Anda telah menemukan tampilan yang diinginkan. Anda dapat mencoba menggunakan perintah:

 expression self.view.recursiveDescription() 

Itu ada di Obj-C, tetapi dihapus di Swift karena kekhasan bahasanya, kita tidak bisa melakukannya, tetapi karena Debuger bekerja dengan Obj-C, secara teori dia bisa memberi makan perintah ini dan dia akan mengerti apa yang Anda inginkan darinya . Untuk menjalankan kode Obj-C di konsol, Anda harus memasukkan perintah:

 expression -l objc -O - - [`self.view` recursiveDescription] 

Apa yang kamu lihat di sini? Saya melihat konstruksi yang agak tidak nyaman yang bisa digunakan seiring waktu, tetapi sebaiknya kita tidak melakukannya, tetapi gunakan typealias untuk menyederhanakan perintah:

 command alias poc expression -l objc -O β€” 

Sekarang tim kami menyusut dan menyederhanakan, tetapi terus melakukan pekerjaan:

 poc [`self.view` recursiveDescription] 

Apakah akan berfungsi setelah menutup Xcode atau di proyek lain? Sayangnya, tidak. Tapi itu bisa diperbaiki! Dengan membuat file .lldbinit dan memasukkan alias kita di sana. Jika Anda tidak tahu caranya, berikut adalah petunjuknya:

1. Buat file .lldbinit (Anda dapat menggunakan .gitignore sebagai prototipe, itu milik jenis teks yang tidak terlihat).

2. Tulis persis perintah berikut dalam file ini:

  command alias poc expression -l objc -O - - 

3. Tempatkan file di folder dengan alamat "MacintoshHD / Users / <Ini adalah nama pengguna Anda>".

Jadi kami mendapat deskripsi dari semua tampilan yang disajikan di layar. Mari kita coba melihat apa yang bisa kita lakukan dengan alamat objek di memori. Untuk Swift, ada metode dengan kelemahan, Anda harus selalu melemparkan tipe objek ke memori ke nilai tertentu:

 po unsafeBitCast(0x105508410, to: UIImageView.self) 

Sekarang kita dapat melihat posisi gambar kita di dalam sel, mari kita gerakkan sehingga itu berpusat pada sel dan memiliki indentasi pada sisi 20 px.

gambar

Terkadang perubahan tidak segera terlihat, tetapi perlu untuk menghapus aplikasi dari debug untuk melihat perubahan tersebut.

Tetapi jika kita ingin melihat sesuatu yang serupa di setiap sel, kita perlu mempercepat eksekusi perintah, kita dapat menulis beberapa skrip dengan Python yang akan bekerja untuk kita (Anda dapat melihat cara menambahkan skrip di sini www.raywenderlich.com/612-custom-lldb-commands-in- berlatih ), dan jika Anda tahu cara menangani Python dan ingin menulis untuk lldb maka Anda akan berguna.

Saya memutuskan untuk menulis ekstensi untuk kelas UIView, yang hanya akan memindahkan pandangan ke arah yang benar, bagi saya tampaknya akan ada sedikit masalah menghubungkan skrip baru ke LLDB dan tidak sulit untuk setiap programmer iOS (jika tidak, Anda perlu belajar Python untuk LLDB).

Saya tidak mencari tempat objek dalam memori dan membawanya ke kelas yang diinginkan, sehingga saya akan mengambil bingkai nanti, juga akan memakan waktu terlalu banyak. Pertanyaannya dipecahkan dengan menulis fungsi dalam ekstensi UIView:

gambar

Sayangnya, itu tidak bekerja dengan baik dengan sel, kemungkinan besar karena fakta bahwa pada saat perintah flush dieksekusi, tidak semua posisi sel dihitung dan tidak muncul di layar (kami belum mengembalikan tableViewCell). Dengan elemen statis lainnya, ini berfungsi dengan baik.

Mengetahui posisi tampilan dalam hierarki, kita dapat mengaksesnya dan mengubah posisinya.

Dan sekarang situasi sebaliknya adalah ketika kita dapat mengakses ViewHierarchy dan ingin mendapatkan data tampilan dari sana. Dalam Xcode, dimungkinkan untuk melihat hierarki tampilan selama pelaksanaan suatu program, Anda juga dapat melihat warna, tata letak, jenis dan ikatan ke objek lain, termasuk itu. Mari kita coba mengakses batasan dari UIImageView kami.

Untuk mendapatkan data kendala:

1. Klik pada Hierarki Tampilan Debug.
2. Aktifkan Konten yang Dipotong di panel di bagian bawah layar yang muncul.
3. Aktifkan Kendala di panel yang sama.
4. Pilih Contraint.
5. Di menu, klik Edit -> Copy (Command + C).
6. Pengikatan jenis ini disalin: ((NSLayoutConstraint *) 0x2838a39d0).
7. Dan sekarang, sama seperti kita mengubahnya melalui kode, Anda juga dapat mengubahnya di lldb:
expression [((NSLayoutConstraint *)0x2838a39d0) setConstant: 60]
8. Setelah mengklik tombol lanjut, item akan memperbarui posisinya di layar.

Anda dapat mengubah warna, teks, dan lainnya dengan cara yang sama:

 expression [(UILabel *)0x102d0a260] setTextColor: UIColor.whiteColor] 

Proyek demo ternyata terlalu sederhana (60 baris kode di ViewController), sebagian besar kode yang saya tulis disajikan dalam artikel, sehingga tidak akan ada kesulitan dalam mereproduksi proyek uji.

PS: Jika ada pertanyaan atau komentar, tulis. Lihatlah WWDC dan Debat sebagai Pro.

Saya juga menyarankan Anda untuk membiasakan diri dengan materi:

Terinspirasi oleh Advanced Debugger WWDC 18 Session
Perintah Debugger
Menambahkan skrip Python ke LLDB Xcode

Source: https://habr.com/ru/post/id460779/


All Articles