Bahasa Cina Readme: 中文集成指南
Injeksi kode memungkinkan Anda untuk memperbarui implementasi fungsi dan metode apa pun dari kelas, struct atau enum secara bertahap di simulator iOS tanpa harus melakukan pembangunan kembali penuh atau memulai kembali aplikasi Anda. Ini menghemat sejumlah besar kode waktu tweaker atau iterasi atas desain. Secara efektif mengubah Xcode dari menjadi "editor sumber" menjadi "editor program" di mana perubahan sumber tidak hanya disimpan ke disk tetapi juga ke program berjalan Anda secara langsung.
Menyiapkan proyek Anda untuk menggunakan injeksi sekarang sesederhana mengunduh salah satu rilis GitHub dari aplikasi atau dari Mac App Store dan menambahkan kode di bawah di suatu tempat di aplikasi Anda untuk dieksekusi pada startup (tidak perlu lagi benar -benar menjalankan aplikasi itu sendiri).
#if DEBUG
Bundle ( path : " /Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle " ) ? . load ( )
//for tvOS:
Bundle ( path : " /Applications/InjectionIII.app/Contents/Resources/tvOSInjection.bundle " ) ? . load ( )
//Or for macOS:
Bundle ( path : " /Applications/InjectionIII.app/Contents/Resources/macOSInjection.bundle " ) ? . load ( )
#endif Penting juga untuk menambahkan opsi -Xlinker dan -interposable (tanpa kutipan ganda dan pada baris terpisah) ke "bendera penghubung lainnya" dari target dalam proyek Anda (hanya untuk konfigurasi Debug ) untuk mengaktifkan "interposing" (lihat penjelasan di bawah).

Setelah itu, ketika Anda menjalankan aplikasi Anda di simulator, Anda akan melihat pesan yang mengatakan seorang pengamat file telah memulai untuk direktori rumah Anda dan, setiap kali Anda menyimpan file sumber dalam proyek saat ini, ia harus melaporkan telah disuntikkan. Ini berarti semua tempat yang sebelumnya disebut implementasi lama akan diperbarui untuk memanggil versi terbaru dari kode Anda.
Tidak sesederhana itu untuk melihat hasil di layar segera, kode baru harus benar -benar dipanggil. Misalnya, jika Anda menyuntikkan pengontrol tampilan, ia perlu memaksa redisplay. Untuk menyelesaikan masalah ini, kelas dapat mengimplementasikan metode @objc func injected() yang akan dipanggil setelah kelas disuntikkan untuk melakukan pembaruan apa pun ke tampilan. Salah satu teknik yang dapat Anda gunakan adalah memasukkan kode berikut di suatu tempat dalam program Anda:
#if DEBUG
extension UIViewController {
@ objc func injected ( ) {
viewDidLoad ( )
}
}
#endifSolusi lain untuk masalah ini adalah "hosting" menggunakan paket suntikan Swift yang diperkenalkan oleh posting blog ini.
Anda tidak dapat menyuntikkan perubahan pada bagaimana data diletakkan di memori yaitu Anda tidak dapat menambahkan, menghapus atau memesan ulang properti dengan penyimpanan. Untuk kelas non-final, ini juga berlaku untuk menambahkan atau menghapus metode karena vtable yang digunakan untuk pengiriman itu sendiri merupakan struktur data yang tidak boleh berubah lebih dari injeksi. Injeksi juga tidak dapat mengetahui potongan kode apa yang perlu dieksekusi ulang untuk memperbarui tampilan seperti yang dibahas di atas. Juga, jangan terbawa dengan kontrol akses. Properti dan metode private tidak dapat disuntikkan secara langsung, terutama dalam ekstensi karena mereka bukan simbol interposable global . Mereka umumnya menyuntikkan secara tidak langsung karena mereka hanya dapat diakses di dalam file yang disuntikkan tetapi ini dapat menyebabkan kebingungan. Akhirnya, injeksi tidak teratas dengan file sumber yang ditambahkan/diganti namanya/dihapus selama injeksi. Anda mungkin perlu membangun dan meluncurkan kembali aplikasi Anda atau bahkan menutup dan membuka kembali proyek Anda untuk menghapus log XCode Build lama.
SwiftUi, jika ada, lebih cocok untuk injeksi daripada Uikit karena memiliki mekanisme spesifik untuk memperbarui tampilan tetapi Anda perlu membuat beberapa perubahan pada setiap struct View yang ingin Anda suntikkan. Untuk memaksa menggambar ulang cara paling sederhana adalah dengan menambahkan properti yang mengamati ketika injeksi telah terjadi:
@ ObserveInjection var forceRedraw Pembungkus properti ini tersedia di Paket HotswiftUi atau menyuntikkan SWIFT. Ini pada dasarnya berisi @Published Integer pandangan Anda mengamati peningkatan itu dengan setiap suntikan. Anda dapat menggunakan salah satu dari berikut ini untuk membuat salah satu paket ini tersedia di seluruh proyek Anda:
@ _exported import HotSwiftUI
or
@ _exported import Inject Perubahan kedua yang perlu Anda lakukan untuk injeksi SwiftUi yang andal adalah untuk "menghapus tipe pengembalian" dari properti tubuh dengan membungkusnya di AnyView menggunakan metode .enableInjection() yang memperluas View dalam paket ini. Ini karena, saat Anda menambahkan atau menghapus elemen SwiftUi, ia dapat mengubah jenis pengembalian beton dari properti tubuh yang berjumlah tata letak memori yang mungkin macet. Singkatnya, ujung ekor masing -masing tubuh harus selalu terlihat seperti ini:
var body : some View {
VStack or whatever {
// Your SwiftUI code...
}
. enableInjection ( )
}
@ ObserveInjection var redraw Anda dapat meninggalkan modifikasi ini dalam kode produksi Anda sebagai, untuk pembangunan Release yang mereka optimalkan ke no-op.
Baru di Xcode 16 adalah pengaturan build SWIFT_ENABLE_OPAQUE_TYPE_ERASURE . Pengaturan ini dihidupkan secara default dan Anda tidak perlu menghapus tubuh tampilan secara eksplisit. Anda masih harus @ObserveInjection untuk memaksa menggambar ulang.
Untuk info lebih lanjut, lihat catatan rilis XCODE 16.2.
Ini dapat berhasil tetapi Anda harus benar-benar menjalankan salah satu rilis GitHub 4.8.0+ dari injectioniii.app, atur default pengguna untuk ikut serta dan restart aplikasi.
$ defaults write com.johnholdsworth.InjectionIII deviceUnlock any
Kemudian, alih -alih memuat bundel injeksi, jalankan skrip ini dalam "fase build": (Anda juga perlu mematikan pengaturan proyek pembuatan "skrip pengguna sandboxing"))
RESOURCES=/Applications/InjectionIII.app/Contents/Resources
if [ -f "$RESOURCES/copy_bundle.sh" ]; then
"$RESOURCES/copy_bundle.sh"
fi
Dan, di aplikasi Anda, jalankan kode berikut saat startup:
#if DEBUG
if let path = Bundle . main . path ( forResource :
" iOSInjection " , ofType : " bundle " ) ??
Bundle . main . path ( forResource :
" macOSInjection " , ofType : " bundle " ) {
Bundle ( path : path ) ! . load ( )
}
#endifSetelah Anda beralih ke konfigurasi ini juga akan berfungsi saat menggunakan simulator. Konsultasikan dengan readme proyek hotreloading untuk perincian tentang cara men-debug program Anda terhubung ke injectioniii.app melalui wi-fi. Anda juga perlu memilih direktori proyek untuk pengamat file secara manual dari menu pop-down.
Ini berfungsi tetapi Anda perlu untuk sementara mematikan "App Sandbox" dan "Validasi Perpustakaan" di bawah "runtime yang dikeraskan" selama pengembangan sehingga dapat secara dinamis memuat kode. Untuk menghindari masalah penandatanganan kode, gunakan skrip copy_bundle.sh baru sebagaimana dirinci dalam instruksi untuk injeksi pada perangkat nyata di atas.
Injeksi telah bekerja dengan berbagai cara selama bertahun-tahun, mulai menggunakan API "Swizzling" untuk Objective-C tetapi sekarang sebagian besar dibangun di sekitar fitur Linker Apple yang disebut "Interposing" yang memberikan solusi untuk setiap metode Swift atau properti yang dihitung dari jenis apa pun.
Ketika kode Anda menyebut fungsi di Swift, umumnya "dikirim secara statis", IE terhubung menggunakan "simbol hancur" dari fungsi yang disebut. Namun, setiap kali Anda menautkan aplikasi dengan opsi "-Interposable", tingkat tidak langsung tambahan ditambahkan di mana ia menemukan alamat semua fungsi yang dipanggil melalui bagian memori yang dapat ditulis. Menggunakan kemampuan sistem operasi untuk memuat kode yang dapat dieksekusi dan Perpustakaan Fishhook untuk "memulihkan" panggilan itu dimungkinkan untuk "menginterposkan" implementasi baru dari fungsi apa pun dan secara efektif menjahitnya ke sisa program Anda saat runtime. Sejak saat itu ia akan berkinerja seolah -olah kode baru telah dibangun ke dalam program.
Injeksi menggunakan API FSEventSteam untuk menonton ketika file sumber telah diubah dan memindai log Build XCode terakhir untuk cara mengkompilasi ulang dan menautkan pustaka dinamis yang dapat dimuat ke dalam program Anda. Dukungan runtime untuk injeksi kemudian memuat pustaka dinamis dan memindai untuk definisi fungsi yang dikandungnya kemudian "menyela" ke sisa program. Ini bukan cerita lengkap karena pengiriman metode kelas non-final menggunakan "vtable" (pikirkan metode virtual C ++) yang juga harus diperbarui tetapi proyek tersebut menjaga setelah itu bersama dengan obyektif warisan-C "swizzling".
Jika Anda tertarik mengetahui lebih banyak tentang bagaimana injeksi bekerja, sumber terbaik adalah buku saya SWIFT Secrets atau implementasi referensi baru yang start-over dalam paket InjectionLite Swift. Untuk informasi lebih lanjut tentang "interposing", hubungi posting blog ini atau Readme of the Fishhook Project. Untuk informasi lebih lanjut tentang organisasi aplikasi itu sendiri, konsultasikan Roadmap.md.
Mendapatkan suntikan untuk bekerja memiliki tiga komponen. Seorang fileWatcher, kode untuk mengkompilasi ulang file yang diubah dan membangun pustaka dinamis yang dapat dimuat dan kode injeksi itu sendiri yang menjahit versi baru kode Anda ke dalam aplikasi saat sedang berjalan. Bagaimana ketiga komponen ini digabungkan menimbulkan jumlah cara injeksi dapat digunakan.
"Injection Classic" adalah tempat Anda mengunduh salah satu rilis biner dari GitHub dan menjalankan injectioniii.app. Anda kemudian memuat salah satu bundel di dalam aplikasi itu ke dalam program Anda seperti yang ditunjukkan di atas dalam simulator. Dalam konfigurasi ini, pengamat file dan sumber ulang sumber dilakukan di dalam aplikasi dan bundel terhubung ke aplikasi menggunakan soket untuk mengetahui kapan perpustakaan dinamis baru siap untuk dimuat.
"App Store Injection" versi aplikasi ini adalah kotak pasir dan sementara pengamat file masih berjalan di dalam aplikasi, kompilasi dan pemuatan yang didelegasikan untuk dilakukan di dalam simulator. Ini dapat menciptakan masalah dengan file header C karena simulator menggunakan sistem file sensitif case untuk menjadi simulasi yang setia dari perangkat nyata.
"Hotreloading Injection" adalah tempat Anda menjalankan aplikasi pada perangkat dan karena Anda tidak dapat memuat bundel dari sistem file Mac Anda pada ponsel nyata Anda menambahkan paket swift hotreloading ke proyek Anda (hanya selama pengembangan!) Yang berisi semua kode yang biasanya ada di bundel untuk melakukan pemuatan dinamis. Ini mengharuskan Anda menggunakan salah satu rilis biner yang tidak diandbox. Itu juga telah digantikan oleh skrip copy_bundle.sh yang dijelaskan di atas.
"Suntikan mandiri". Ini adalah evolusi terbaru dari proyek di mana Anda tidak menjalankan aplikasi itu sendiri tetapi cukup memuat salah satu bundel injeksi dan pengamat file, kompilasi ulang dan injeksi semuanya dilakukan di dalam simulator. Secara default ini menonton untuk perubahan pada file Swift di dalam direktori home Anda meskipun Anda dapat mengubah ini menggunakan variabel lingkungan INJECTION_DIRECTORIES .
Injectionlite adalah implementasi minimal minimal dari injeksi mandiri untuk referensi. Cukup tambahkan paket Swift ini dan Anda harus dapat menyuntikkan di simulator.
InjectionNext adalah versi injeksi yang saat ini eksperimental yang harus lebih cepat dan lebih dapat diandalkan untuk proyek besar. Ini diintegrasikan ke dalam bendera debugging Xcode untuk mengetahui cara mengkompilasi ulang file untuk menghindari penguraian log build dan menggunakan kembali implementasi klien injeksi dari InjectionLite . Untuk digunakan dengan editor eksternal seperti Cursor , InjectionNext juga dapat menggunakan pengamat file untuk mendeteksi pengeditan dan kembali untuk membangun kode parsing log.
Semua variasi ini mengharuskan Anda untuk menambahkan bendera linker "-xlinker -Intposble" untuk build deBug atau Anda hanya akan dapat menyuntikkan metode kelas non-final dan semua dapat digunakan bersama dengan salah satu dari suntikan level yang lebih tinggi atau hotswiftui.
Konsultasikan dengan ReadMe lama yang jika ada yang mengandung "terlalu banyak informasi" termasuk berbagai variabel lingkungan yang dapat Anda gunakan untuk kustomisasi. Beberapa contoh:
| Lingkungan var. | Tujuan |
|---|---|
| Injection_detail | Output verbose dari semua tindakan yang dilakukan |
| Injection_trace | Panggilan log ke fungsi yang disuntikkan (v4.6.6+) |
| Injection_host | Alamat IP Mac untuk injeksi di perangkat |
Dengan variabel lingkungan injection_trace , menyuntikkan file apa pun akan menambah pencatatan semua panggilan ke fungsi dan metode dalam file bersama dengan nilai argumen mereka sebagai bantuan untuk debugging.
Sedikit fitur injectioniii yang sedikit diketahui adalah asalkan Anda telah menjalankan tes untuk aplikasi Anda di beberapa titik, Anda dapat menyuntikkan kelas XCTEST individual dan telah segera dijalankan - melaporkan jika gagal setiap kali Anda memodifikasinya.
Proyek ini mencakup kode dari Rentzsch/Mach_inject, Erwanb/MachinjectSample, Davedelong/Ddhotkey dan ACJ/Timelapsebuilder-Swift di bawah lisensi masing-masing.
Fungsi penelusuran aplikasi menggunakan OliverleTterer/Imp_ImplementationForwardingToselector Trampoline Implementasi melalui proyek Swifttrace di bawah lisensi MIT.
Swifttrace menggunakan https://github.com/facebook/fishhook yang sangat berguna. Lihat sumber proyek dan file header yang termasuk dalam bundel aplikasi untuk detail lisensi.
Rilis ini mencakup versi yang sangat sedikit dimodifikasi dari perpustakaan Canviz yang sangat baik untuk membuat file "DOT" dalam kanvas HTML yang tunduk pada lisensi MIT. Perubahan adalah untuk melewati ID node ke tag label node (baris 212), untuk membalikkan rendering node dan garis yang menghubungkannya (baris 406) dan untuk menyimpan jalur tepi sehingga mereka dapat diwarnai (baris 66 dan 303) di "Canviz-0.1/canviz.js".
Ini juga termasuk editor Codemirror JavaScript untuk kode yang akan dievaluasi menggunakan injeksi di bawah lisensi MIT.
Ikon aplikasi yang luar biasa adalah berkat Katya dari pixel-mixer.com.