iOS 런타임 이해

런타임

개요: 런타임이라고도 하는 런타임은 기본 C 언어 API 세트이며 iOS 시스템의 핵심 중 하나입니다. 개발자는 코딩 프로세스 중에 모든 개체에 메시지를 보낼 수 있습니다. 수신자가 메시지에 응답하고 처리하는 방법은 런타임에 따라 달라집니다.< /p>

? C 언어에서는 컴파일러가 호출할 함수를 결정하는 반면, OC 함수는 동적 호출 프로세스에 속합니다. 컴파일러는 실제로 호출할 함수를 결정할 수 없으며 실제 런타임 중에만 해당 함수를 찾을 수 있습니다. 함수를 호출하고 호출하세요. OC는 동적 언어입니다. 즉, 클래스와 객체를 동적으로 생성하고 메시지를 전달하고 전송하려면 컴파일러뿐만 아니라 런타임 시스템도 필요합니다.

1. 메시지 전달

< p> 런타임의 주요 기능은 메시지 전달입니다. 개체에서 메시지를 찾을 수 없으면 전달됩니다. Objective-C는 동적 언어입니다. 즉, 클래스와 개체, 메시지 전달 및 전달을 동적으로 생성하려면 컴파일러뿐만 아니라 런타임 시스템도 필요합니다. 런타임의 핵심은 메시지 전달입니다.

(1) 메시지 전달 과정

객체 메소드 [obj test]의 경우 컴파일러는 이를 메시지로 변환하여 objc_msgSend(obj, test)로 보냅니다. 프로세스는 다음과 같습니다

a. 먼저 obj의 isa 포인터를 통해 해당 클래스를 찾습니다.

b. 클래스의 메서드 목록에서 test를 찾습니다.

c. 클래스에서 발견되면 해당 슈퍼클래스에서 계속 검색합니다.

d. 테스트 함수를 찾으면 해당 IMP를 실행합니다.

효율성 문제로 인해 objc_method_list를 한 번 순회하는 것은 비합리적입니다. 따라서 함수 쿼리의 효율성을 높이기 위해 자주 호출되는 함수를 캐시해야 합니다. 이것이 objc_class의 또 다른 중요한 구성원인 objc_cache가 수행하는 작업입니다. 테스트를 찾은 후 테스트의 method_name을 키로, method_imp를 값으로 사용합니다. 테스트 메시지가 다시 수신되면 캐시에서 직접 검색할 수 있습니다.

클래스 객체(objc_class)

Objective-C 클래스는 실제로 objc_class 구조에 대한 포인터인 Class 유형으로 표시됩니다. struct objc_class 구조에는 많은 변수가 정의되어 있습니다. 구조체에는 상위 클래스에 대한 포인터, 클래스 이름(name), 버전, 인스턴스 변수 목록(ivars), 메서드 목록(methodLists), 캐시(cache), 준수할 프로토콜 목록(protocols)이 저장됩니다. 여기서 알 수 있듯이 클래스 객체는 struct objc_class 구조이고 이 구조에 저장된 데이터는 메타데이터입니다.

런타임을 이해한다는 것은 데이터 저장소와 클래스, 인스턴스, 클래스 객체 및 iOS가 실행 중일 때의 메타클래스.

(2) 메시지 전달 메커니즘

최종 분석에서 Objective-C의 모든 메소드 호출의 본질은 객체에 메시지를 보내는 것입니다

1. 클래스에 메소드 생성 -(void)test

2. iOS 시스템은 이 메소드에 대한 번호인 SEL(test)를 생성하고 이를 메소드 목록에 추가합니다.

3. 이 경우 메소드가 호출되면 시스템은 메소드 목록에서 이 메소드를 검색하고 발견되면 실행합니다.

따라서 메소드를 호출하면 메시지가 한 번 전송됩니다. 즉, 이 클래스의 메소드 목록에서 검색됩니다. 클래스에서 찾을 수 없으면 이 클래스의 상위 클래스에서 검색으로 이동하고, 상위 클래스를 찾을 수 없으면 상속 트리의 루트까지 검색하거나 메시지 전달을 수행합니다. 실패하면 인식할 수 없는 선택기 오류가 보고됩니다.

1. 동적 메서드 해결

Objective-C 런타임은 resolveInstanceMethod를 호출합니다. 아니면, resolveClassMethod: 함수를 추가하고 YES를 반환하는 경우 함수 구현을 제공할 수 있습니다. , 그러면 런타임이 메시지 전송 프로세스를 다시 시작합니다. 다음과 같습니다.

foo:에 대한 구현 함수는 없지만 class_addMethod()를 통해 fooMethod 함수를 동적으로 추가하고 이 함수가 성공적으로 실행되어 인쇄됩니다. reslove가 NO를 반환하면 런타임은 다음 단계인forwardingTargetSelector로 이동합니다.

2. 직접 메시지 전달

대상 개체가 전달 대상 선택기를 구현하는 경우 런타임은 이때 이 메서드를 호출하여 다음을 수행합니다. 이 메시지를 다른 객체에 전달할 수 있는 기회를 주십시오

그림에서 볼 수 있듯이 현재 클래스의 메소드를 전달타겟ForSelector 메소드를 통해 Father 클래스에 구현했으며 인쇄에 성공했습니다.

3. 메시지 전달 완료

이전 단계에서 알 수 없는 메시지를 처리할 수 없는 경우 수행할 수 있는 유일한 작업은 메시지 전달 메커니즘을 시작하는 것입니다. 먼저 함수의 매개변수와 반환 값 유형을 얻기 위해 methodSignatureForSelector 메시지를 보냅니다. methodSignatureForSelector가 nil을 반환하면 런타임은 doesNotRecognizeSelector를 발행합니다. 서명된 함수가 반환되면 런타임은 NSInvocation 개체를 생성하고 대상 개체에 전달 Invocation 메시지를 보냅니다.

런타임의 실제 적용

1. 런타임 교환 방식 사용

2. 동적 추가 방식(현재로서는 잘 이해되지 않음)

3. 카테고리에 속성 추가

4. 버그 해결을 위한 메시지 전달(핫 업데이트)(JSPatch)