Ios 메시지 전송 메커니즘

5899 단어 Runtime
원본 링크:http://www.jianshu.com/p/fa29c920409d
이 블 로그 의 선행 지식 포 인 트 는 OC 의 소식 전달 체제 입 니 다. 만약 에 이것 에 대해 잘 모 르 면 먼저 배우 고 이 글 을 보 세 요.이 블 로 그 는 PPT 를 말 하 는 것 처럼 이 지식 을 알려 드 리 려 고 합 니 다.
대상 이 읽 을 수 없 는 소식 을 들 었 을 때 무슨 일이 일어 날 지 생각해 보 자.예 를 들 어, 우 리 는 viewcontroller 를 실현 합 니 다. 그 중 에 'setText:' 라 는 구성원 방법 이 없습니다. 이 문 구 를 작성 할 때
[self setText:@"  "];

예시
OC 는 동적 언어 이기 때문에 컴 파일 기간 에 하나의 warning 만 표시 할 뿐 실행 을 막 는 error 가 아 닙 니 다.warning 실행 을 무시 하면 프로그램 이 crash 되 고 콘 솔 에 유사 한 것 을 표시 합 니 다.
unrecognized selector sent to instance 0x7f931a4180d0

라 는 오류 메 시 지 를 보 냈 다.
unrecognized selector
메 시 지 는 처리 할 수 없 는 대상 에 게 보 내 졌 다.우리 가 iOS 의 메시지 퍼 가기 체 제 를 배 우 는 것 은 고의로 이러한 crash 놀 이 를 만 들 기 위해 서가 아니다. 위의 이 예 를 들 어 우리 가 메시지 퍼 가기 체 제 를 통 해 어떤 일 을 하지 않 으 면 시스템 은 결국 crash 로 끝 날 것 이라는 것 을 설명 하기 위해 서 이다.잠시 만 요. 방금 OC 는 동적 언어 라 고 했 는데 운영 기간 에 crash 가 일어나 지 않도록 뭔 가 를 할 수 있 을까요?
메시지 전송 메커니즘 은 바로 이 일 을 하 러 온 것 이다. 운행 기간 에 3 개의 '접 판 협' 방법 을 통 해 대상 과 메시지 에 더 많은 기 회 를 주어 성공 적 인 호출 을 완성 하 는 것 이지 직접 crash 가 아니다.
1 번 접 반 협
첫 번 째 접 판 협 은 동적 방법 해석 단 계 를 대표 합 니 다. 해당 하 는 구체 적 인 방법 은 + (BOOL) resolve InstanceMethod: (SEL) sel 과 + (BOOL) resolve ClassMethod: (SEL) sel 입 니 다. 방법 이 인 스 턴 스 방법 일 때 전 자 를 호출 하고 방법 이 클래스 방법 일 때 후 자 를 호출 합 니 다.이 방법 은 클래스 에 class 를 이용 하기 위해 설계 되 었 습 니 다.addMethod 추가 방법의 기회.
다음 예 시 를 보면 MyTestObject 류 는 첫 번 째 접 판 협 방법 을 다시 썼 습 니 다. 이 방법 이 selector 에 들 어가 BOOL 형식 으로 돌아 가 는 것 을 볼 수 있 습 니 다.들 어 오 는 selector 는 처리 되 지 않 은 방법 입 니 다. 1 번 접 판 협 방법 에서 방법 명 이 XXX 라면 같은 이름 을 추가 하 는 방법 으로 방법의 실현 을 XXX 이름과 일치 하지 않 는 AAA 로 가리 키 고 YES 로 되 돌려 줍 니 다.selector 이름 이 XXX 가 아니라면 부모 클래스 로 돌아 갑 니 다.
resolveInstanceMethod
이 예 를 통 해 알 수 있 듯 이 우 리 는 1 번 접 판 협 방법 을 통 해 방법 명 과 방법 을 운행 기간 에 임 의적 으로 조합 할 수 있다.
다시 한 번 말씀 드 리 지만 이 반환 값 은 사실 시험 해 볼 수 있 습 니 다. YES 로 돌아 가든 NO 로 돌아 가든 시스템 은 SEL 로 IMP 를 찾 으 려 고 시도 합 니 다. 함수 가 실현 되면 실행 하기 때문에 YES 로 돌아 가든 \ NO 는 2 번 접 판 협 방법 에 들 어 갑 니 다.
2 번 접 반 협
두 번 째 단 계 는 지원 수신 자 단계 입 니 다. 대상 의 구체 적 인 방법 은 - (id) forwardingTargetForSelector: (SEL) aSelector 입 니 다. 이때 실행 할 때 다른 수신 자 에 게 메 시 지 를 전달 할 수 있 는 지 물 었 습 니 다. 즉, 이때 시스템 은 이 SEL 을 다른 대상 에 게 전달 할 기 회 를 주 었 습 니 다.우 리 는 계속해서 매개 변수 와 반환 값 을 연구 합 니 다. 매개 변 수 는 1 번 접 판 협 과 마찬가지 로 모두 selector 입 니 다. 반환 값 은 id 형식 입 니 다. 비 self \ 비 nil 로 돌아 갈 때 메 시 지 는 새로운 대상 에 게 전 달 됩 니 다.
forwardingTargetForSelector
3 번 접 반 협
세 번 째 단 계 는 전체 메시지 전송 단계 입 니 다. 대응 방법 - (void) forward Invocation: (NSInvocation *) anInvocation 입 니 다. 이것 은 메시지 전송 절차 의 마지막 부분 입 니 다.인자 anInvocation 에는 처리 되 지 않 은 메시지 의 각종 정보 가 포함 되 어 있 습 니 다 (selector \ target \ 매개 변수...).이 방법 에서 anInvocation 을 여러 대상 에 게 전달 할 수 있 고 2 번 접 판 협 과 달리 2 번 은 한 대상 에 게 만 전달 할 수 있다.
forwardInvocation
이 메 시 지 를 처리 하 는 세 가지 방법 이 없 으 면 NSObject 의 - (void) does NotRecognizeSelector: (SEL) aSelector 방법 에 들 어가 이상 을 던 집 니 다.잠시 만 요. 왜 우 리 는 NSObject 에 category 를 만들어 서 이 방법 을 다시 쓸 수 없 습 니까? 여기 서 메시지 가 처리 되 지 않 은 상황 을 처리 할 수 있 습 니까?애플 의 공식 문서 에 서 는 "이 함수 가 이대로 끝나 지 않도록 이상 을 던 져 야 한다" 고 명확 하 게 언급 했다.공식 문 서 를 듣 는 것 외 에 분류 에서 이 방법 을 다시 써 서 각종 정보 가 처리 되 지 않 은 상황 을 처리 하면 이 분류 방법 이 특히 길 고 유지 에 불리 하 다.그리고 분명 한 방법 은 'selector 를 식별 할 수 없다' 는 것 인 데 그 중에서 도 이 상황 을 처리 하 는 코드 가 많 고 이상 하 다.
doesNotRecognizeSelector
총결산
전체 메시지 전달 절 차 를 정리 합 니 다.
메시지 전달 절차
3 개의 접 반 협 방법 을 다시 써 서 그 중 중단 점 에서 집행 순 서 를 검증 할 수 있다.
정지점 검증 순서
요약: 한 함수 에서 찾 을 수 없습니다. OC 는 세 가지 방식 으로 보완 할 수 있 습 니 다. 1. resolve InstanceMethod 를 호출 하여 클래스 에 이 함 수 를 추가 할 수 있 는 기 회 를 주 었 습 니 다.
모두 맞지 않 으 면 does NotRecognizeSelector 를 호출 하여 이상 을 던 집 니 다.
의문
Q1: 그럼 우 리 는 마지막 접 판 맨 방법 만 쓰 면 얼마나 좋 을 까? 왜 앞의 두 개가 더 필요 하지?사실은 이 세 가지 방법의 용도 와 다르다. 운행 기 추가 방법 은 1 로 한다.다른 대상 에 게 전달 하고 방법 을 바 꿀 때 2;여러 대상 에 게 전달 해 야 할 때 3;
그리고 절차 가 뒤로 갈수 록 메 시 지 를 처리 하 는 대가 가 커 져 마지막 단계 에 이 르 렀 을 때 NSInvocation 대상 을 만 들 었 다.
Q2: 메시지 전달 에는 어떤 응용 장면 이 있 습 니까?운영 기간 에 어떤 방법 을 추가 할 수 있 습 니 다. 예 를 들 어 Teacher 류 에 teach 방법 이 있 습 니 다. Drug Dealer 류 에 lets Cook 방법 이 있 습 니 다. 1 번 접 판 협 방법 을 통 해 우 리 는 운영 기간 에 saleDrug 를 teacher 의 방법 목록 에 몰래 추가 하여 teacher 에 게 마 약 판매 기능 을 갖 추 게 할 수 있 습 니 다.절명 독사 야.
방법 을 다른 대상 에 게 넘 겨 처리 하고 예 를 들 어 Teacher 류 (블 로 거들 이 선생님 과 원한 이 있 습 니까?), [teacher lets Cook] 는 대상 을 운행 기간 에 drug Dealer 로 바 꿀 수 있 습 니 다.쿡 류 하나 더, 레 츠 쿡 방법 도 있 지만, 이번 방법 은 쿡 마 약이 아니 라 쿡 요리 다.따라서 [teacher lets Cook] 을 통 해 [drug Dealer lets Cook] 을 실현 할 수도 있 고 [cook lets Cook] 을 실현 할 수도 있다.OC 가 다 중 상속 을 이 룬 셈 이다. 부적 절 하지만...
주의 하 다.
respons ToSelector 는 대상 이 어떤 방법 을 실 현 했 는 지 확인 하 는 데 더 이상 익숙 하지 않 습 니 다.이 함 수 는 보통 다시 불 러 올 필요 가 없 지만 동적 으로 검색 과정 을 실현 한 후에 이 함 수 를 다시 불 러 와 서 대외 인터페이스 에서 동적 실현 함 수 를 찾 을 때 YES 로 돌아 가 대외 인터페이스의 행위 통일 을 확보 해 야 합 니 다.
respondsToSelector
마지막 으로 워 닝 얘 기 좀 하 자.컴 파일 러 가 친절 한 신문 의 그 warning 은 어떻게 해 야 합 니까? 그 작은 노란색 줄 이 깔끔 한 프로그래머 의 스타일 이 아니 더 라 도 우 리 는 그것 을 없 앨 방법 을 생각해 야 합 니 다.두 가지 방법 이 있 습 니 다. 첫 번 째 는 폭력 적 입 니 다. 설정 파일 에서 Complier Flag 을 - w 로 추가 하여 모든 warning 을 제거 합 니 다.
모든 경고 제거
두 번 째 는 추천 하 는 방법 입 니 다. xcode 의 error 패 널 에서 warning 오른쪽 단 추 를 누 르 십시오. - Leveal in Log 에 작은 bug 가 있 습 니 다. 이 옵션 을 선택 할 수 없다 면 다시 build 해 야 합 니 다.
작은 버그
오른쪽 에 있 습 니 다. 이 warning 의 이름 을 볼 수 있 습 니 다.
warning 이름 을 어떻게 봅 니까?
그래서 이 매크로 로 warning 이 나타 난 코드 를 둘러싸 면 컴 파일 러 가 더 이상 오 류 를 보고 하지 않 을 수 있 습 니 다.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-method-access"
    [self setText:@"  "];
#pragma clang diagnostic pop

좋은 웹페이지 즐겨찾기