Читайте китайский язык: 中文集成指南
Инъекция кода позволяет вам обновлять реализацию функций и любого метода класса, структуры или перечисления постепенно в симуляторе iOS без необходимости выполнять полную перестройку или перезапустить ваше приложение. Это экономит разработчика значительное количество времени настройки кода или итерации по проекту. Эффективно он меняет Xcode от «редактора источников» на «редактор программы», где изменения источника сохраняются не только на диск, но и в вашу программу работает напрямую.
Настройка ваших проектов для использования впрыска теперь так же просто, как загрузка одного из выпусков GitHub приложения или в магазине приложений Mac и добавление кода ниже где -то в вашем приложении, которое будет выполнено при запуске (больше не нужно фактически запускать само приложение).
#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 Также важно добавить параметры -Xlinker и -interposable (без двойных кавычек и в отдельных строках) в «другие флаги линкера» целей в вашем проекте (только для конфигурации Debug ), чтобы включить «вмешательство» (см. Объяснение ниже).

После этого, когда вы запускаете свое приложение в симуляторе, вы должны увидеть сообщение, в котором говорится, что наблюдатель за файлом начал для вашего домашнего каталога, и всякий раз, когда вы сохраняете исходный файл в текущем проекте, он должен сообщить, что он был введен. Это означает, что все места, которые ранее называли старой реализации, будут обновлены, чтобы вызвать последнюю версию вашего кода.
Это не так просто, как сразу же увидеть результаты на экране, который должен был фактически вызвать новый код. Например, если вы вводите контроллер представления, он должен привести к тому, что Redisplay. Чтобы решить эту проблему, классы могут реализовать метод @objc func injected() , который будет вызван после того, как класс будет внедрен для выполнения любого обновления на дисплее. Одна техника, которую вы можете использовать, - это включить следующий код где -то в вашу программу:
#if DEBUG
extension UIViewController {
@ objc func injected ( ) {
viewDidLoad ( )
}
}
#endifЕще одним решением этой проблемы является «хостинг» с использованием пакета Inject Swift, представленного этим сообщением в блоге.
Вы не можете вводить изменения в то, как данные изложены в памяти, то есть вы не можете добавлять, удалять или переупорядочить свойства с хранением. Для нефинальных классов это также относится к добавлению или удалению методов, поскольку vtable используемая для отправки, сама является структурой данных, которая не должна изменяться в течение впрыска. Инъекция также не может понять, какие части кода необходимо повторно выполнить, чтобы обновить дисплей, как обсуждалось выше. Кроме того, не увлекайтесь контролем доступа. private свойства и методы не могут быть введены напрямую, особенно в расширениях, поскольку они не являются global взаимосвязанным символом. Как правило, они вводили косвенно, так как они могут быть только акцентами внутри вводится только файл, но это может вызвать путаницу. Наконец, инъекция плохо справляется с добавлением/переименованием исходных файлов во время инъекции. Возможно, вам понадобится создать и перезапустить свое приложение или даже закрыть и открыть свой проект, чтобы очистить старые журналы сборки XCODE.
Swiftui, во всяком случае, лучше подходит для инъекций, чем uikit, поскольку у него есть конкретные механизмы для обновления дисплея, но вам нужно внести пару изменений в каждую структуру View , которую вы хотите вводить. Чтобы принудительно перерисоваться простейшим способом - добавить свойство, которое наблюдает, когда произошла инъекция:
@ ObserveInjection var forceRedraw Эта обертка свойства доступна либо в пакете Hotswiftui, либо в пакете Swift. По сути, он содержит @Published integer, которые ваши взгляды наблюдают, что увеличивает каждую инъекцию. Вы можете использовать один из следующего, чтобы сделать один из этих пакетов доступными на протяжении всего проекта:
@ _exported import HotSwiftUI
or
@ _exported import Inject Второе изменение, которое вам необходимо сделать для надежного инъекции Swiftui, состоит в том, чтобы «стирать тип возврата» свойства тела, обернув его в AnyView , используя метод .enableInjection() расширяющий View в этих пакетах. Это связано с тем, что, когда вы добавляете или снимаете элементы Swiftui, это может изменить тип бетона возврата свойства тела, который составляет изменение макета памяти, которое может сбое. Таким образом, хвостовой конец каждого тела всегда должен выглядеть так:
var body : some View {
VStack or whatever {
// Your SwiftUI code...
}
. enableInjection ( )
}
@ ObserveInjection var redraw Вы можете оставить эти модификации в своем производственном коде, как для сборки Release , которую они оптимизируют в NO-OP.
Новое в XCode 16 - SWIFT_ENABLE_OPAQUE_TYPE_ERASURE . Эта настройка включается по умолчанию, и вам не нужно явно стереть тело. Вам все равно нужно @ObserveInjection , чтобы принудительно перерисоваться.
Для получения дополнительной информации см. Xcode 16.2 Примечания к выпуску.
Это может работать, но вам нужно будет запустить одну из выпусков GitHub 4.8.0+ Incectioniii.App, установить пользователь по умолчанию, чтобы забрать и перезапустить приложение.
$ defaults write com.johnholdsworth.InjectionIII deviceUnlock any
Затем вместо загрузки пучков впрыска запустите этот скрипт в «фазе сборки»: (вам также необходимо отключить настройку сборки проекта «Sandboxing Soundboxing»)
RESOURCES=/Applications/InjectionIII.app/Contents/Resources
if [ -f "$RESOURCES/copy_bundle.sh" ]; then
"$RESOURCES/copy_bundle.sh"
fi
И в вашем приложении выполните следующий код при запуске:
#if DEBUG
if let path = Bundle . main . path ( forResource :
" iOSInjection " , ofType : " bundle " ) ??
Bundle . main . path ( forResource :
" macOSInjection " , ofType : " bundle " ) {
Bundle ( path : path ) ! . load ( )
}
#endifПосле того, как вы переключитесь на эту конфигурацию, она также будет работать при использовании симулятора. Проконсультируйтесь с ReadMe проекта HotReLoAning для получения подробной информации о том, как отладить, если ваша программа подключается к IncectionIII.App через Wi-Fi. Вам также нужно будет выбрать каталог проектов для Watcher File вручную из меню «Поп -низ».
Он работает, но вам нужно временно отключить «Песочницу приложения» и «проверка библиотеки» в «Завершенном времени выполнения» во время разработки, чтобы он могла динамически загружать код. Чтобы избежать проблем с кодами, используйте новый сценарий copy_bundle.sh , как подробно описано в инструкциях для инъекции на реальных устройствах выше.
Инъекция работала различными способами за эти годы, начиная с использования API «Swizzling» для Objective-C, но в настоящее время в значительной степени построена вокруг функции линкера Apple, называемого «Interpasing», который обеспечивает решение для любого быстрого метода или вычисленного свойства любого типа.
Когда ваш код вызывает функцию в Swift, он, как правило, «статически отправляется», т.е. связан с использованием «искаженного символа» вызываемой функции. Всякий раз, когда вы связываете свое приложение с опцией «-interposable», однако, добавляется дополнительный уровень косвенности, когда он находит адрес всех функций, вызываемых через раздел записи, которую можно получить. Использование способности операционной системы загружать исполняемый код и библиотека Fishhook для «повторения», поэтому вызов, следовательно, можно «внедрить» новые реализации любой функции и эффективно сшить их в остальную часть вашей программы во время выполнения. С этого момента он будет работать так, как если бы новый код был встроен в программу.
Инъекция использует API FSEventSteam для наблюдения за тем, когда был изменен исходный файл, и сканирует последний журнал сборки XCODE, чтобы перекомпилировать его, и связывает динамическую библиотеку, которая может быть загружена в вашу программу. Поддержка времени выполнения инъекции затем загружает динамическую библиотеку и сканирует ее для определений функций, которые она содержит, которые затем «вводят» в остальную часть программы. Это не полная история, поскольку отправка нефинальных методов класса использует «VTable» (подумайте о виртуальных методах C ++), которая также должна быть обновлена, но проект заботится о этом вместе с любым унаследованным объективом C "Swizzling".
Если вам интересно узнать больше о том, как работает инъекция, лучший источник-это либо моя книга Swift Secrets, либо новую, начальную справочную реализацию в пакете Swift IncectionLite. Для получения дополнительной информации о «взаимодействии» проконсультируйтесь с этим сообщением в блоге или в прокате проекта Fishhook. Для получения дополнительной информации об организации самого приложения обратитесь к Roadmap.md.
Получение инъекции на работу имеет три компонента. FileWatcher, код для перекомпиляции любых измененных файлов и создания динамической библиотеки, которая может быть загружена, и сам код впрыска, который сшивает новые версии вашего кода в приложение во время работы. То, как эти три компонента объединяются, приводит к тому, что может использоваться количество способов, которыми может быть использовано.
«Инъекция классика» - это то, где вы загружаете один из бинарных выпусков от GitHub и запускаете incectioniii.app. Затем вы загружаете одну из пакетов внутри этого приложения в свою программу, как показано выше в симуляторе. В этой конфигурации в приложении выполняются перекомпилирование File и источник, а пакет подключается к приложению, используя розетку, чтобы узнать, когда новая динамическая библиотека будет загружена.
«Инъекция приложения магазина». Эта версия приложения предназначена для песочницы, и, хотя наблюдатель за файлом все еще работает внутри приложения, перекомпилирование и загрузка делегируется для выполнения внутри симулятора. Это может создавать проблемы с файлами заголовка C, так как симулятор использует чувствительную к корпусу файловую систему, которая является верным моделированием реального устройства.
«HotReLoading Indection» - это то, где вы запускаете свое приложение на устройстве, и потому что вы не можете загрузить пакет с файловой системы вашего Mac на настоящий телефон, который вы добавляете пакет Swift HotReling в свой проект (только во время разработки!), Который содержит весь код, который обычно будет в пакете, чтобы выполнить динамическую загрузку. Это требует, чтобы вы использовали один из бинарных выпусков без санкботок. Он также был заменен сценарием copy_bundle.sh , описанного выше.
«Автономная инъекция». Это была самая последняя эволюция проекта, где вы больше не запускаете саму приложение, а просто загружаете одну из пучков для инъекций, а наблюдатель файла, повторный компиляция и инъекция выполняются в симуляторе. По умолчанию эти часы для изменений в любом файле Swift в вашем домашнем каталоге, хотя вы можете изменить это, используя переменную среды INJECTION_DIRECTORIES .
IncectionLite-это начальная минимальная реализация автономной инъекции для справки. Просто добавьте этот пакет Swift, и вы сможете вводить в симулятор.
IncectionNext - это экспериментальная версия инъекции в настоящее время, которая должна быть быстрее и надежнее для крупных проектов. Он интегрируется в флаг отладки Xcode, чтобы выяснить, как перекомпилировать файлы, чтобы избежать анализа журналов сборки и повторно использования клиентской реализации инъекции от InjectionLite . Для использования с внешними редакторами, такими как Cursor , IncectionNext также может использовать наблюдатель за файлом для обнаружения редакций и возвращения, чтобы создать код анализа журнала.
Все эти вариации требуют, чтобы вы добавили флаги-линкеры «-xlinker -interposble» для сборки отладки, или вы сможете внедрять нефинальные методы классов, и все можно использовать в сочетании с любым из инъекций более высокого уровня или Hotswiftui.
Проконсультируйтесь с старым Readme, который, если что -то содержало просто «слишком много информации», включая различные переменные среды, которые вы можете использовать для настройки. Несколько примеров:
| Среда вар. | Цель |
|---|---|
| Incection_detail | Пловесная вывода всех выполненных действий |
| Incection_trace | Вызовы журналов в инъекционные функции (v4.6.6+) |
| Incection_host | IP-адрес MAC для инъекции на устройстве |
С переменной среды incection_trace , инъекция любого файла добавит ведение журнала всех вызовов к функциям и методам в файле вместе с их значениями аргумента в качестве помощи для отладки.
Неизвестная особенность IncectionIII заключается в том, что при условии, что вы запустили тесты для вашего приложения в какой -то момент, вы можете ввести отдельный класс XCTEST и иметь немедленно, если он запускается, - отчетность, если оно не удалось каждый раз, когда вы его изменяете.
Этот проект включает в себя код от Rentzsch/Mach_inject, Erwanb/MachinjectSample, Davedelong/ddhotkey и ACJ/TimeLapseBuilder-Swift под их соответствующими лицензиями.
В функциональности трассировки приложения используется реализация батутного батута Oliverletterer/Imp_ImplementingToselector с помощью проекта SwiftTrace по лицензии MIT.
Swifttrace использует очень удобный https://github.com/facebook/fishhook. См. Файл источника проекта и заголовок, включенный в пакет приложений для получения подробной информации.
Этот релиз включает в себя очень немного измененную версию отличной библиотеки Canviz для рендеринга «точечных» файлов на холсте HTML, которая подлежит лицензии MIT. Изменения должны пройти через идентификатор узла к метке метки узла (строка 212), чтобы отменить рендеринг узлов и линии, связывающие их (строка 406) и хранить края пути, чтобы их можно было окрасить (строка 66 и 303) в «Canviz-0.1/Canviz.js».
Он также включает в себя редактор Codemirror JavaScript для оценки кода с использованием инъекции по лицензии MIT.
Сказочный иконка приложения благодаря Katya of Pixel-mixer.com.