원본 코드 를 통 해 iOS 의 깊 은 복사 와 얕 은 복사 분석

머리말
iOS 에서 대상 의 깊 은 복사 와 얕 은 복사 에 관 한 글 은 많 지만 대부분 메모리 주 소 를 인쇄 하여 결 과 를 유도 합 니 다.이 글 은 원본 코드 의 측면 에서 깊 은 복사 와 얕 은 복사 를 분석 합 니 다.
딥 카피 와 얕 은 카피 의 개념
복사 방식 은 두 가지 가 있 는데 그것 이 바로 깊 은 복사 와 얕 은 복사 이다.
  • 얕 은 복사 본 은 포인터 복사 라 고도 합 니 다.예 를 들 어 지침 이 있 습 니 다.이 지침 은 문자열 을 가리 키 고 있 습 니 다.즉,이 지침 변수의 값 은 이 문자열 의 주소 입 니 다.이때 이 문자열 을 포인터 복사 한 다 는 뜻 은 포인터 변 수 를 만 들 었 습 니 다.이 지침 변수의 값 은 이 문자열 의 주소 입 니 다.이 문자열 의 인용 계수+1 입 니 다.
  • 딥 복사 란 내용 복사 라 고도 합 니 다.예 를 들 어 지침 이 있 습 니 다.이 지침 은 문자열 을 가리 키 고 있 습 니 다.즉,이 지침 변수의 값 은 이 문자열 의 주소 값 입 니 다.그러면 이 문자열 을 내용 복사 하면 새로운 지침 을 만 들 고 새로운 주소 영역 에 문자열 을 만 듭 니 다.이 문자열 의 값 은 원래 문자열 의 값 과 같 습 니 다.새 지침 은 새로 만 든 문자열 을 가리 키 고 있 습 니 다.이 때 원래 문자열 의 인용 수 는+1 이 없습니다.
  • 얕 은 복사 란 복사 한 후에 실제 복 제 를 하지 않 고 복사 한 대상 과 원래 대상 이 모두 같은 주 소 를 가리 키 는 것 이다.
    딥 복사 본 은 실제 복사 본 으로 복사 대상 이 새로운 주 소 를 가리 키 고 있 습 니 다.

    위의 그림 에서 알 수 있 듯 이 A 포인터 가 가리 키 는 내용 을 바 꾸 었 고 B 포인터 도 수 정 된 내용 을 가리 키 고 있다.B 지침 을 사용 하 는 곳 이 있 으 면 A 가 가리 키 는 내용 에 도 변 화 를 원 하지 않 을 경우 딥 카피 가 필요 하 다.
    얕 은 복사 본 은 당신 의 그림자 와 같 습 니 다.당신 이 죽 으 면 그림자 도 사라 집 니 다.깊 은 복사 본 은 복제 인간 과 같다.네가 죽 었 는데,그것 은 아직 있다.
    대상 의 copy 와 mutableCopy 방법
    집합 대상 이 든 비 집합 대상 이 든 copy 와 mutableCopy 메 시 지 를 받 을 때 다음 과 같은 준칙 을 따른다.
  • copy immutable 대상 되 돌려 주기
  • mutableCopy mutable 대상 되 돌려 주기
  • 다음은 비 집합 대상 과 집합 대상 의 copy 와 mutableCopy 방법 에 대해 구체 적 으로 논술 한다.
    1.집합 대상 이 아 닌 copy 와 mutableCopy 방법
    비 집합 클래스 대상 은 NSString,NSNumber...이런 종 류 를 가리킨다.다음 예 는 NSString 클래스 를 예 로 들 수 있 습 니 다.
    우선 immutable 대상 복사 예 를 살 펴 보 겠 습 니 다.
    
     NSString *string = @"test";
     NSString *copyString = [string copy];
     NSMutableString *mutableCopyString = [string mutableCopy];
     
     NSLog(@"%p 
    %p
    %p
    ", string, copyString, mutableCopyString);
    인쇄 결과:
    0x101545068
    0x101545068
    0x60000024e940
    인쇄 결 과 를 통 해 알 수 있 듯 이 copyString 은 string 의 주소 값 과 같 고 mutableCopyString 과 string 의 주소 값 이 다 릅 니 다.이것 은 imutable 대상 의 copy 방법 이 얕 은 복사,mutableCopy 방법 이 깊 은 복사 되 었 음 을 설명 합 니 다.
    mutable 대상 복사 예 를 살 펴 보 겠 습 니 다.
    
     NSMutableString *string = [[NSMutableString alloc] initWithString:@"test"];
     NSString *copyString = [string copy];
     NSMutableString *mutableCopyString = [string mutableCopy];
     
     NSLog(@"%p 
    %p
    %p
    ", string, copyString, mutableCopyString);
    인쇄 결과:
    0x600000240e40
    0xa000000747365744
    0x6000002411a0
    인쇄 결 과 를 통 해 알 수 있 듯 이 copyString 과 string 의 메모리 주소 가 다 르 고 mutableCopyString 과 string 의 메모리 주소 도 다르다.이 는 mutable 대상 의 copy 방법 과 mutable Copy 방법 이 모두 딥 복사 되 었 음 을 나타 낸다.
    총괄 적 으로 말 하면:
    immutable 대상 의 copy 방법 을 얕 게 복사 하 였 습 니 다.
    immutable 대상 의 mutableCopy 방법 을 깊이 복사 하 였 습 니 다.
    mutable 대상 의 copy 방법 을 깊이 복사 하 였 습 니 다.
    mutable 대상 의 mutable Copy 방법 을 깊이 복사 하 였 습 니 다.
    코드 로 표시 하면:
    
     [immutableObject copy];//   
     [immutableObject mutableCopy];//   
     [mutableObject copy];//   
     [mutableObject mutableCopy];//   
    이상 은 메모리 주 소 를 인쇄 하여 얻 은 결론 입 니 다.다음은 소스 코드 를 통 해 우리 의 결론 을 확인 하 겠 습 니 다.
    opensource.apple.com 의 git 창고 에 있 는 runtime 소스 코드 에는 NSObject.mm 라 는 파일 이 있 습 니 다.이 파일 에는 copy 와 mutableCopy 방법 이 실 현 됩 니 다.
    
    - (id)copy {
     return [(id)self copyWithZone:nil];
    }
    
    - (id)mutableCopy {
     return [(id)self mutableCopyWithZone:nil];
    }
    우 리 는 copy 와 mutableCopy 방법 이 copy WithZone:과 mutableCopy WithZone:두 가지 방법 만 간단하게 호출 된 것 을 발견 했다.그리고 나 서 나 는searchcode.com에서 NSString 과 NSMutableString 의 Source Code 를 찾 았 다.
    NSString.m에서 copy 에 관 한 방법 을 찾 았 습 니 다.
    
    - (id)copyWithZone:(NSZone *)zone {
     if (NSStringClass == Nil)
     NSStringClass = [NSString class];
     return RETAIN(self);
    }
    
    - (id)mutableCopyWithZone:(NSZone*)zone {
     return [[NSMutableString allocWithZone:zone] initWithString:self];
    }
    이 소스 코드 를 통 해 알 수 있 듯 이 NSString 대상 에 대해 copy 방법 을 호출 하 는 것 은 copy WithZone:방법 을 호출 하 는 것 입 니 다.한편,copy With Zone:방법 은 새로운 대상 을 만 들 지 않 고 포인터 로 하여 금 원래 의 NSString 대상 을 가지 게 하기 때문에 NSString 의 copy 방법 은 얕 은 복사 입 니 다.
    mutableCopy 를 호출 하 는 방법 은 mutableCopyWithZone:방법 을 호출 하 는 것 입 니 다.mutableCopyWithZone:의 실현 을 통 해 알 수 있 듯 이 이 방법 은 새로운 가 변 적 인 문자열 대상 을 만 드 는 것 입 니 다.따라서 NSString 의 mutableCopy 방법 은 딥 카피 입 니 다.
    NSMutableString.m에서 copy 와 copy WithZone:방법 만 찾 았 을 뿐 mutable Copy WithZone:방법 은 찾 지 못 했 습 니 다.
    
    -(id)copy {
     return [[NSString alloc] initWithString:self];
    }
    
    -(id)copyWithZone:(NSZone*)zone {
     return [[NSString allocWithZone:zone] initWithString:self];
    }
    NSMutablestring 대상 에 copy 방법 을 호출 하면 이 곳 의 copy With Zone:방법 이 실 현 됩 니 다.새로운 가 변 적 이지 않 은 문자열 을 만 드 는 것 을 볼 수 있 습 니 다.그래서 NSMutablestring 대상 에 대한 copy 방법 은 딥 복사 입 니 다.
    NSMutablestring 에서 mutableCopyWithZone:방법 이 구현 되 지 않 았 기 때문에 부모 클래스 의 mutableCopyWithZone:방법,즉 NSString 류 의 mutableCopyWithZone:방법 을 호출 합 니 다.NSString 류 의 mutableCopyWithZone:방법 은 새로운 가 변 문자열 을 만 들 수 있 습 니 다.그래서 NSMutablestring 대상 에 게 mutableCopy 를 실행 하 는 방법 은 딥 복사 입 니 다.
    2.집합 대상 의 copy 와 mutableCopy
    집합 대상 은 NSArray,NSDictionary,NSSet 등 과 같은 대상 을 가리킨다.다음은 NSArray 를 예 로 들 어 immutable 대상 이 copy 와 mutableCopy 를 사용 하 는 예 를 살 펴 보 겠 습 니 다.
    
     NSArray *array = @[@"1", @"2", @"3"];
     NSArray *copyArray = [array copy];
     NSMutableArray *mutableCopyArray = [array mutableCopy];
     
     NSLog(@"%p
    %p
    %p", array, copyArray, mutableCopyArray);
    인쇄 결과:
    0x60400025bed0
    0x60400025bed0
    0x60400025c2f0
    인쇄 결 과 를 통 해 알 수 있 듯 이 copy Array 의 주소 와 array 의 주 소 는 같 으 며,array 에 대해 copy 를 하 는 것 은 얕 은 복사 임 을 나타 낸다.그리고
    mutableCopyArray 의 주소 와 array 의 주 소 는 다 릅 니 다.array 에 대해 mutableCopy 를 하 는 것 은 깊이 복사 한 것 을 의미 합 니 다.
    mutable 대상 이 copy 와 mutableCopy 를 실행 하 는 예 를 살 펴 보 겠 습 니 다.
    
     NSMutableArray *array = [[NSMutableArray alloc] initWithArray:@[@"1", @"2", @"3"]];
     NSArray *copyArray = [array copy];
     NSMutableArray *mutableCopyArray = [array mutableCopy];
     
     NSLog(@"%p
    %p
    %p", array, copyArray, mutableCopyArray);
    인쇄 결과:
    0x604000447440
    0x604000447050
    0x604000447080
    인쇄 결 과 를 통 해 알 수 있 듯 이 copy Array 와 mutableCopyArray 의 주 소 는 모두 array 의 주소 와 다 릅 니 다.이 는 가 변 배열 에 대해 copy 와 mutableCopy 작업 을 모두 깊이 복사 한 것 을 의미 합 니 다.
    그래서 결론 을 내 렸 다.
    집합 클래스 대상 에서 immutable 대상 에 대해 copy 작업 을 하 는 것 은 얕 은 복사 이 고 mutableCopy 작업 을 하 는 것 은 깊 은 복사 입 니 다.mutable 대상 에 대해 copy 작업 을 하 는 것 은 깊 은 복사 이 고 mutable Copy 작업 을 하 는 것 은 깊 은 복사 입 니 다.
    코드 로 표시 하면:
    
     [immutableObject copy];//   
     [immutableObject mutableCopy];//   
     [mutableObject copy];//   
     [mutableObject mutableCopy];//   
    이상 은 메모리 주 소 를 인쇄 하여 얻 은 결론 입 니 다.다음은 소스 코드 를 통 해 우리 의 결론 을 검증 하 겠 습 니 다.
    NSArray.m에서 나 는 copy WithZone:mutable Copy WithZone:방법 을 찾 았 다.
    
    - (id)copyWithZone:(NSZone *)zone
    {
     return RETAIN(self);
    }
    
    - (id)mutableCopyWithZone:(NSZone*)zone
    {
     if (NSMutableArrayClass == Nil)
     NSMutableArrayClass = [NSMutableArray class];
     return [[NSMutableArrayClass alloc] initWithArray:self];
    }
    copy 방법 을 호출 할 때 실제 적 으로 이곳 의 copy With Zone:방법 을 실 행 했 습 니 다.이 방법 에 서 는 새로운 대상 을 만 들 지 않 고 오래된 대상 만 가지 고 있 기 때문에 가 변 적 이지 않 은 배열 대상 에 대해 copy 작업 을 수행 하 는 것 은 얕 은 복사 입 니 다.
    mutableCopy 방법 을 호출 할 때 실제 적 으로 이곳 의 mutableCopy With Zone:방법 을 실 행 했 습 니 다.이 방법 에서 원래 의 배열 대상 을 이용 하여 새로운 가 변 배열 대상 을 만 들 었 기 때문에 가 변 적 이지 않 은 배열 대상 에 대해 서 는 mutableCopy 작업 을 깊이 복사 합 니 다.
    NSArray.m이 파일 의 825 줄 은 NSMutable Array 의 실현 입 니 다.875 줄 에서 copy With Zone:의 실현 을 찾 았 습 니 다.mutable Copy With Zone:의 실현 을 찾 지 못 했 습 니 다.
    
    - (id)copyWithZone:(NSZone*)zone
    {
     if (NSArrayClass == Nil)
     NSArrayClass = [NSArray class];
     return [[NSArrayClass alloc] initWithArray:self copyItems:YES];
    }
    copy 방법 을 호출 할 때 실제 적 으로 여기 있 는 copy With Zone:방법 을 호출 했 습 니 다.이 방법의 실현 에 있어 서 원래 의 가 변 배열 을 이용 하여 새로운 가 변 배열 을 만 들 었 기 때문에 가 변 배열 에 대해 copy 작업 을 수행 하 는 것 은 깊 은 복사 입 니 다.
    mutableCopy 를 호출 할 때 NSMutableArray 자체 가 mutableCopyWithZone:방법 을 실현 하지 못 했 기 때문에 부모 클래스,즉 NSArray 류 의 실현 을 호출 합 니 다.위 를 통 해 NSArray 의 실현 을 볼 수 있 습 니 다.원 배열 을 이용 하여 새로운 가 변 배열 을 만 들 었 기 때문에 가 변 배열 에 대해 mutableCopy 작업 을 하 는 것 은 깊 은 복사 입 니 다.
    고전 면접 문 제 를 풀다.
    면접 문제:왜 NSString 유형의 멤버 변수의 수식 속성 은 strong 이 아 닌 copy 를 사용 합 니까?
    우선 NSString 유형의 멤버 변 수 를 copy 로 수식 하 는 것 과 strong 으로 수식 하 는 것 의 차 이 를 알 아야 합 니 다.copy 수식 자 를 사용 하면 구성원 변수 에 값 을 부여 할 때 할당 대상 을 copy 작업 한 다음 구성원 변수 에 값 을 부여 합 니 다.strong 수정자 를 사용 하면 copy 작업 을 수행 하지 않 고 할당 되 는 변 수 를 구성원 변수 에 직접 할당 합 니 다.
    NSString 형식의 구성원 변수 string 이 있다 고 가정 하고 값 을 부여 합 니 다.
    
     NSString *testString = @"test";
     self.string = testString;
    만약 이 구성원 변수 가 copy 로 수식 된다 면 다음 과 같 습 니 다.
    
    self.string = [testString copy];
    strong 으로 꾸 몄 다 면 copy 작업 이 없습니다.
    
    self.string = testString;
    copy 와 strong 의 차 이 를 알 게 된 후,우 리 는 왜 copy 수식 자 를 사용 해 야 하 는 지 다시 분석 합 니 다.코드 먼저 보기:
    
     NSMutableString *mutableString = [[NSMutableString alloc] initWithString:@"test"];
     self.string = mutableString;
     NSLog(@"%@", self.string);
     [mutableString appendString:@"addstring"];
     NSLog(@"%@", self.string);
    이 멤버 변수 string 이 strong 으로 수식 되 어 있다 면 인쇄 결 과 는 다음 과 같 습 니 다.
    2018-09-04 10:50:16.909998+0800 copytest[2856:78171] test
    2018-09-04 10:50:16.910128+0800 copytest[2856:78171] testaddstring
    mutablestring 의 값 이 바 뀌 면 string 의 값 도 달라 집 니 다.self.string=mutablestring 때 문 입 니 다.이 코드 는 실제로 포인터 복사 가 실행 되 었 다.string 의 값 은 mutablestring 의 값 에 따라 달라 집 니 다.이것 은 분명히 우리 가 원 하 는 결과 가 아 닙 니 다.
    만약 구성원 변수 string 이 copy 로 수식 된다 면 인쇄 결 과 는 다음 과 같 습 니 다.
    2018-09-04 10:58:07.705373+0800 copytest[3024:84066] test
    2018-09-04 10:58:07.705496+0800 copytest[3024:84066] test
    이것 은 copy 수식 자 를 사용 한 후 self.string=mutablestring;self.string=[mutablestring copy];즉,한 번 깊이 복사 되 었 기 때문에 mutablestring 의 값 이 다시 변 하면 string 의 값 에 영향 을 주지 않 습 니 다.
    면접 문제 에 대답 하 다.
    NSString 형식의 구성원 변 수 는 strong 수식 이 아 닌 copy 수식 을 사용 합 니 다.가끔 이 구성원 에 게 주어진 변 수 는 NSMutableString 형식 이기 때 문 입 니 다.이때 수정자 가 strong 이면 구성원 변수의 값 은 할당 대상 의 값 에 따라 달라 집 니 다.copy 로 수식 하면 NSMutablestring 형식의 값 을 한 번 깊이 복사 하면 구성원 변수의 값 은 할당 대상 의 값 에 따라 바 뀌 지 않 습 니 다.
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기