중국어 readme : m
Code Injection을 사용하면 IOS 시뮬레이터에서 기능의 구현 및 클래스 구조, 구조물 또는 열거 방법을 완전히 재건 또는 다시 시작하지 않아도 업데이트 할 수 있습니다. 이로 인해 개발자는 코드를 조정하거나 디자인을 반복하는 상당한 시간을 절약 할 수 있습니다. 효과적으로 Xcode를 "소스 편집기"에서 "프로그램 편집기" 로 변경하여 소스 변경이 디스크에 저장 될뿐만 아니라 실행 프로그램에 직접 저장됩니다.
주입을 사용하기 위해 프로젝트를 설정하는 것은 앱의 GitHub 릴리스 중 하나 또는 Mac App Store에서 다운로드하고 시작시에 실행될 앱 어딘가에 아래 코드를 추가하는 것만 큼 간단합니다 (실제로 앱 자체를 실행할 필요는 없습니다).
#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 이 속성 래퍼는 핫스웨어 투이 또는 Swift 패키지로 제공됩니다. 본질적으로 @Published Integer가 포함되어 있습니다. 뷰는 각 주입마다 증가하는 것을 관찰합니다. 다음 중 하나를 사용하여 프로젝트 전반에 걸쳐 이러한 패키지 중 하나를 사용할 수 있습니다.
@ _exported import HotSwiftUI
or
@ _exported import Inject 신뢰할 수있는 Swiftui 주입을 위해 두 번째로 변경 해야하는 것은이 패키지에서 .enableInjection() 메소드를 확장하여 AnyView 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+ 릴리스의 릴리스 중 하나를 실행하고 사용자 기본값을 옵트 인으로 설정하고 앱을 다시 시작해야합니다.
$ defaults write com.johnholdsworth.InjectionIII deviceUnlock any
그런 다음 주입 묶음을로드하는 대신이 스크립트를 "빌드 단계"에서 실행합니다.
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이 구성으로 전환하면 시뮬레이터를 사용할 때도 작동합니다. 프로그램을 디버깅하는 방법에 대한 자세한 내용은 Wi-Fi를 통해 Injectioniii.App에 연결하는 방법에 대한 자세한 내용은 HotReloading 프로젝트의 README에 문의하십시오. 또한 팝 다운 메뉴에서 수동으로 파일 감시자의 프로젝트 디렉토리를 선택해야합니다.
작동하지만 개발 중에 "경화 된 런타임"에서 "앱 샌드 박스"및 "라이브러리 검증"을 일시적으로 끄려면 코드를 동적으로로드 할 수 있습니다. 코드 디자인 문제를 피하려면 위의 실제 장치에 대한 주입 지침에 자세히 설명 된 새로운 copy_bundle.sh 스크립트를 사용하십시오.
주입은 Objective-C의 "스위블 링"API를 사용하여 수년에 걸쳐 다양한 방식으로 작동했지만 이제는 신속한 방법 또는 계산 된 속성에 대한 솔루션을 제공하는 Apple 링커의 "Interposing"이라는 기능을 중심으로 구축되었습니다.
코드가 Swift에서 함수를 호출하면 일반적으로 "통계적으로 발송"됩니다. 즉, 호출되는 함수의 "Mangled Symbol"을 사용하여 연결됩니다. 그러나 애플리케이션을 "-인터페이스 가능"옵션과 연결할 때마다 추가 수준의 간접 수준이 추가되어 모든 기능의 주소가 쓰기 가능한 메모리 섹션을 통해 호출되는 것을 찾습니다. 운영 체제의 실행 클로르와 Fishhook 라이브러리를로드하는 기능을 사용하여 호출을 "반창"하여 호출을 "반창"할 수 있습니다. 따라서 모든 기능의 새로운 구현을 "개입"하고 런타임에 나머지 프로그램에 효과적으로 스티칭 할 수 있습니다. 이 시점부터 새 코드가 프로그램에 내장 된 것처럼 수행됩니다.
주입은 FSEventSteam API를 사용하여 소스 파일이 변경되었을 때 시청하고 마지막 Xcode 빌드 로그를 스캔하고 프로그램에 다시 컴파일하는 방법을 스캔하고 프로그램에로드 할 수있는 동적 라이브러리를 연결합니다. 주입에 대한 런타임 지원 그런 다음 동적 라이브러리를로드하고 포함하는 기능 정의에 대해 스캔 한 다음 프로그램의 나머지 부분에 "중재"합니다. 비 결절 클래스 방법의 파견이 "vtable"(C ++ 가상 메소드 생각)을 사용하여 업데이트되어야하지만 프로젝트는 레거시 목표 C "스위 즈 링"과 함께이를보고 있기 때문에 전체 이야기가 아닙니다.
주입 방법에 대해 더 많이 알고 있다면 가장 좋은 소스는 내 책 Swift Secrets 또는 IncectionLite Swift 패키지의 새로운 신생 기준 참조 구현입니다. "중재"에 대한 자세한 내용은이 블로그 게시물 또는 Fishhook 프로젝트의 README를 참조하십시오. 앱 자체의 구성에 대한 자세한 내용은 Roadmap.md를 참조하십시오.
작업에 주입하는 것은 세 가지 구성 요소가 있습니다. Filewatcher, 변경된 파일을 다시 컴파일하고로드 할 수있는 동적 라이브러리를 구축하는 코드와 실행 중에 새 버전의 코드를 앱에 스팅하는 주입 코드 자체를 작성합니다. 이 세 가지 구성 요소를 결합하는 방법은 주입을 사용할 수있는 방법을 발생시킵니다.
"Injection Classic"은 Github에서 이진 릴리스 중 하나를 다운로드하고 주입 IIII.App을 실행하는 곳입니다. 그런 다음 시뮬레이터와 같이 위에 표시된대로 해당 앱 내부의 번들 중 하나를 프로그램에로드합니다. 이 구성에서는 파일 감시자 및 소스 리 컴파일이 앱 내부에서 수행되며 번들은 소켓을 사용하여 앱에 연결하여 새 동적 라이브러리를로드 할 준비가 된시기를 알 수 있습니다.
"App Store Injection"이 앱 버전은 샌드 박스가 있으며 파일 감시자가 여전히 앱 내부에서 실행되는 동안 리 컴파일 및로드는 시뮬레이터 내부에서 수행되도록 위임됩니다. 시뮬레이터는 CASE 민감한 파일 시스템을 사용하여 실제 장치의 충실한 시뮬레이션이므로 C 헤더 파일에 문제가 발생할 수 있습니다.
"HotReloading Injection"은 장치에서 앱을 실행하는 곳이었으며 실제 전화기에 Mac 파일 시스템에서 번들을로드 할 수 없기 때문에 hotreloading swift 패키지를 프로젝트에 추가하여 (개발 중에 전용!) 동적로드를 수행하기 위해 일반적으로 번들에있는 모든 코드를 포함합니다. 이를 위해서는 샌드 샌드 박스 바이너리 릴리스 중 하나를 사용해야합니다. 또한 위에서 설명한 copy_bundle.sh 스크립트로 대체되었습니다.
"독립형 주입". 이것은 더 이상 앱 자체를 실행하지 않고 주입 묶음 중 하나를로드하는 프로젝트의 가장 최근의 진화였습니다. 파일 감시자, 재 컴파일 및 주입은 모두 시뮬레이터 내부에서 수행됩니다. 기본적 으로이 홈 디렉토리 내부의 신속한 파일 변경 사항은 환경 변수 INJECTION_DIRECTORIES 사용하여 변경할 수 있습니다.
주입자는 참조를위한 독립형 주입의 시작 초과 최소 구현입니다. 이 Swift 패키지를 추가하면 시뮬레이터에 주입 할 수 있어야합니다.
InjectionNext는 현재 실험적인 주입 버전으로 대규모 프로젝트에 더 빠르고 신뢰할 수 있어야합니다. Xcode의 디버깅 플래그에 통합되어 파일을 다시 컴파일하는 방법을 찾기 위해 구문 분석 로그를 피하고 InjectionLite 에서 주입의 클라이언트 구현을 재사용합니다. Cursor 와 같은 외부 편집기와 함께 사용하려면 InjectionNext는 파일 감시자를 사용하여 편집을 감지하고 로그 구문 분석 코드를 구축하기 위해 돌아갈 수도 있습니다.
이러한 모든 변형은 디버그 빌드를 위해 "-xlinker-interposble"링커 플래그를 추가해야합니다. 그렇지 않으면 클래스의 비 결합 메소드 만 주입 할 수 있으며 모든 수준의 주사 또는 핫스턴 투기와 함께 사용할 수 있습니다.
사용자 정의에 사용할 수있는 다양한 환경 변수를 포함하여 단순히 "너무 많은 정보"가 포함 된 경우 이전 readme에 문의하십시오. 몇 가지 예 :
| 환경 var. | 목적 |
|---|---|
| 주사 _detail | 수행 된 모든 작업의 장점 출력 |
| 주사 _trace | 주입 된 함수에 대한 통화 (v4.6.6+) |
| 주사 _host | 기기 주입을위한 Mac의 IP 주소 |
injection_trace 환경 변수를 사용하면 파일을 주입하면 디버깅의 도움으로 인수 값과 함께 파일의 함수 및 메소드에 모든 호출을 로깅을 추가합니다.
Injectioniii의 약간 알려진 기능은 어느 시점에서 앱 테스트를 실행했다면 개별 XCTest 클래스를 주입하고 즉시 실행할 경우 즉시 실행할 수 있다는 것입니다.
이 프로젝트에는 Rentzsch/mach_inject, erwanb/machinjectsample, davedelong/ddhotkey 및 acj/timelapsebuilder-swift의 각 라이센스에 따라 코드가 포함됩니다.
앱 추적 기능은 MIT 라이센스 하의 SwiftTrace 프로젝트를 통해 Oliverletterer/Imp_implementationForwardingToselector Trampoline 구현을 사용합니다.
SwiftTrace는 매우 편리한 https://github.com/facebook/fishhook을 사용합니다. 라이센스 세부 정보는 앱 번들에 포함 된 프로젝트 소스 및 헤더 파일을 참조하십시오.
이 릴리스에는 우수 캔 디즈 라이브러리의 매우 약간 수정 된 버전이 포함되어있어 MIT 라이센스가 적용되는 HTML 캔버스에서 "DOT"파일을 렌더링합니다. 변경 사항은 노드의 ID를 통과하여 노드 레이블 태그 (라인 212)로 전달하여 노드의 렌더링과 링크를 연결하는 선 (406 행)을 반전시키고 에지 경로를 저장하여 "Canviz-0.1/Canviz.js"에서 색상을 채색 할 수 있습니다 (라인 66 및 303).
또한 MIT 라이센스에 따라 주입을 사용하여 평가 될 코드를 위해 Codemirror JavaScript 편집기도 포함되어 있습니다.
멋진 앱 아이콘은 Pixel-mixer.com의 Katya에게 감사합니다.