OC runtime 학습 노트 관련 대상

머리말
Objective-C 는 대상 에 속성 을 동적 으로 추가 할 수 없습니다.다른 원생 들 이 지원 하 는 언어 와 다 릅 니 다.그래서 앞으로 늘 어 날 변 수 를 위해 공간 을 마련 하려 고 노력 해 야 했다.맥 OS X 10.6 에서 오 브 젝 티 브-C 의 런 타임 은 이미 이 기능 을 원생 으로 지원 했다.
OC runtime 에서 관련 대상 의 방법 은 모두 가 사용 한 적 이 있다 고 믿 지만 그 원리 와 내부 실현 은 많은 사람들 이 모른다.이 글 은 OC runtime 의 관련 대상 을 설명 하고 바로 본론 으로 들 어 갑 니 다.
runtime 관련 대상 원리
runtime 에서 제공 하 는 API 는 다음 과 같 습 니 다.

///       
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
 OBJC_ASSOCIATION_ASSIGN = 0,  /**<         */
 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**<          .     . */
 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**<           .     . */
 OBJC_ASSOCIATION_RETAIN = 01401, /**<          .   . */
 OBJC_ASSOCIATION_COPY = 01403  /**<           .   . */
};

/** 
 *      key       policy      object       
 */
void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy);

/** 
 *       object   key        
 */
id objc_getAssociatedObject(id object, const void * key);

/** 
 *      object        
 */
void objc_removeAssociatedObjects(id object);
runtime 의 API 는 매우 간단 합 니 다.실제로 작업 중 runtime 의 관련 대상 을 사용 하 는 것 도 편리 합 니 다.다음 과 같 습 니 다.

static const void * _Nonnull titleKey = @"titleKey";

- (void)setTitle:(NSString *)title
{
 objc_setAssociatedObject(self, titleKey, key, OBJC_ASSOCIATION_RETAIN);
}

- (NSString *)title
{
 return objc_getAssociatedObject(self, titleKey);
}
이렇게 간단 하고 강력 한 기능 은 시스템 의 실현 을 관찰 하려 면 관련 대상 의 소스 코드 를 찾 을 수 있 습 니 다.우 리 는 obsc 소스 코드 에서 얻 을 수 있 습 니 다.
원본 코드 에서 상기 세 개의 API 의 실현 은 다음 과 같다.

obbc 로setAssociated Object 방법 을 예 로 들 면 방법 내부 에서 호출 된 내부 방법 은 매개 변수 가 같 고 내부 로 들 어 가 는 방법 이다

///            。
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
 
 //         ,           
 ObjcAssociation old_association(0, nil);
 //     
 id new_value = value ? acquireValue(value, policy) : nil;
 {
 //          .         AssociationsHashMap
 AssociationsManager manager;
 //          Map
 AssociationsHashMap &associations(manager.associations());
 //       。     object   
 disguised_ptr_t disguised_object = DISGUISE(object);
 if (new_value) {
  //            
  AssociationsHashMap::iterator i = associations.find(disguised_object); //       key  AssociationsHashMap objc       Map
  if (i != associations.end()) {
  //   Map  。    map: ObjectAssociationMap
  ObjectAssociationMap *refs = i->second;
  //         ObjectAssociationMap      
  ObjectAssociationMap::iterator j = refs->find(key); //   key  ObjectAssociationMap   ObjcAssociation
  if (j != refs->end()) {
   //      ObjcAssociation   ,    old_association
   old_association = j->second;
   j->second = ObjcAssociation(policy, new_value);
  } else {
   //     ->       
   (*refs)[key] = ObjcAssociation(policy, new_value);
  }
  } else {
  //      Map        
  ObjectAssociationMap *refs = new ObjectAssociationMap;
  associations[disguised_object] = refs;
  (*refs)[key] = ObjcAssociation(policy, new_value);
  object->setHasAssociatedObjects();
  }
 } else {
  //    value ,         nil。         
  AssociationsHashMap::iterator i = associations.find(disguised_object);
  if (i != associations.end()) {
  ObjectAssociationMap *refs = i->second;
  ObjectAssociationMap::iterator j = refs->find(key);
  if (j != refs->end()) {
   old_association = j->second;
   refs->erase(j);
  }
  }
 }
 }
 //    old value.
 if (old_association.hasValue()) ReleaseValue()(old_association);
}
원본 코드 에서 볼 수 있 듯 이 유지보수 대상 과 관련 된 대상 은 주로 네 개 입 니 다.
AssociationsManager  // 관련 관 계 를 유지 하 는 전역 관리자--->Associations HashMap 저장
AssociationsHashMap  // 관련 관 계 를 저장 하 는 HashMap--->대상 에 대응 하 는 관련 관 계 를 저장 하 는 Map
Object Association Map//대상 관련 관계 맵,2 급 맵
ObjcAssociation      // 연관 관계
그들의 관 계 는 그림 으로 다음 과 같이 표시 합 니 다.
runtime
우리 의 대상 외부 에서 대상 관련 체 제 를 재 구축 하고 관리 하 며 이중 hashMap 을 통 해 대상 간 의 관련 관 계 를 유지 하 는 것 과 같다.그 중에서 Associations HashMap(외층 Map)은 Associations Manager 에 저 장 된 전역 정적 맵 입 니 다.대상 의 메모리 주소 처 리 를 통 해 대상 과 유일 하 게 연 결 된 key 를 map 에 저장 하고 대상 과 관련 된 Object Association Map 을 저장 합 니 다.이 map 는 Objc Association(관련 정책 과 값)을 유지 합 니 다.
이상 obj csetAssociated Object 를 예 로 들 어 관련 대상 의 원 리 를 설명 하 였 습 니 다.obbcgetAssociated Object 와 obbcremove Associated Objects 원리 도 마찬가지다.
사유 확장
runtime 에서 대상 과 관련 된 원 리 는 위 와 같이 애플 소스 코드 의 사상 을 배 웠 다.업무 중 에 비슷 한 데이터 저장 이 마침 참고 할 수 있다 는 것 을 알 수 있다.
마침 오후 에 runtime 대상 의 관련 원 리 를 연구 할 때 친구 가 나 에 게 다 중 사용자 시스템 의 실현 논 리 를 물 었 다.
대 의 는:
4.567917.사용 자 는 핸드폰 번호 로 로그 인 한 후에 메모리 에 사용자 정보 표를 생 성 합 니 다.표 에 사용자 의 예 를 들 어 개인 기본 정보,연락처 정보,지갑 정 보 를 저장 할 수 있 습 니 다.4.567918.
  • 사용자 가 로그 인 을 종료 하면 정 보 를 잃 어 버 리 지 않 습 니 다.
  • 다른 사용자 가 로그 인 한 후에 도 해당 하 는 사용자 정보 표를 만 들 고 저장 합 니 다
  • 이전 사용자 가 로그 인 한 후에 도 자신의 사용자 정 보 를 볼 수 있 습 니 다
  • 이 문 제 를 보고 나 는 runtime 에서 대상 과 관련 된 실현 이 바로 이 문제 의 좋 은 실현 이 라 고 직접 느 꼈 다.
    사용자 로그 인 id 를 통 해 key 에 사용자 정보 맵 을 만 듭 니 다.모든 사용자 id 가 유일한 사용자 정보 표 에 대응 하 는 지 확인 하고 사용자 정보 표 에 어떤 정 보 를 저장 하고 싶 은 지 사용자 정의 합 니 다.
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기