iOS 개발에서 "자동 해제"적용

오늘 여러분과'자방출'사상이 iOS 개발에서의 응용에 대해 이야기해 봅시다.'자방출'이 무엇입니까?간단하게 보면 대상이 생명주기가 끝난 후에 그와 관련된 모든 자원이나 링크를 자동으로 정리하고 회수하는 것으로 이해할 수 있다. 이 정리는 대상 메모리의 회수뿐만 아니라 대상의 결합과 부속 사건의 정리 등도 포함한다. 예를 들어 타이머의 자기 정지, KVO 이미지의 감청 제거 등이다.

개체 메모리 재확보


개발 과정에서 대상 관리의 기본 원칙인 누가 창설하고 누가 석방하는가.그러나 비 ARC 프로젝트에서 우리는 autorelease로 대상을 표시하고 편집기에 이 대상은 내가 방출을 책임지지 않는다고 알려준다. 이때 이 대상은'자방출'대상이 되고 더 이상 필요하지 않을 때 시스템은 자동으로 메모리를 회수한다.ARC 프로젝트에서 모든 대상은 우리에게 자방출 대상입니다. 기쁩니다. 우리는 메모리 유출 문제에 대해 더 이상 주의를 기울일 필요가 없고 업무 논리에 더 많은 정력을 기울일 수 있습니다. 그러나 이것은 메모리 유출이 없다는 것을 의미하지 않습니다. 이 도구인 HJNSObjectRelease를 사용해 보세요. 아마도 예상치 못한 수확을 얻을 수 있을 것입니다.

타이머의 자동 방출


타이머는 일반 대상과 달리 타이머를 만든 후에 스스로 풀리지 않기 때문에 적당한 시간에 invalidate가 필요합니다.실제 개발에서, 아마도 너는 자주 이렇게 타이머를 만들 것이다
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(onTimerCount) userInfo:nil repeats:YES];

그리고 dealloc 함수에서 타이머 invalidate를 지정합니다.유감스럽지만, 프로그램은 dealloc 함수를 영원히 실행하지 않을 것입니다. 왜냐하면 NSTimer가 target 대상을 강제로 인용하기 때문에, 순환 인용의 출현은 반드시 메모리 유출을 초래하기 때문입니다.이때, 당신은 틀림없이 weak target의 타이머를 매우 원할 것입니다. 매우 기쁩니다. MSWeak Timer가 당신의 요구를 잘 만족시켰습니다.그러나, Timer는 여전히 자신을 방출하지 않습니다. dealloc에서 invalidate를 사용해야 합니다.그러면 어떻게 해야만 invalidate를 쓰지 않을 수 있습니까?타이머는 스스로 방출할 수 있습니까?우리 먼저 이 문제를 한쪽에 놓고 이어서 아래를 보자

KVO의 석방


iOS 개발 중에는 메시지 알림 및 KVO를 자주 사용하는데 아마도 당신은 이렇게 코드를 쓸 것이다
- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNotice) name:@"NoticeIdentifier" object:nil];
    [self addObserver:target forKeyPath:@"keyPath" options:NSKeyValueObservingOptionNew context:nil];
}
 
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NoticeIdentifier" object:nil];
    [self removeObserver:target forKeyPath:@"keyPath"];
}

시간이 지날수록 이런 쓰기에 익숙해질 뿐만 아니라 사과도 이렇게 추천한다.하지만 천천히 모든 대상의 Dealloc 함수가 이 일만 하고 있다는 것을 알게 될 것이다. 이 일을 하지 않을 수 있겠는가?FBKVOcontroller는 좋은 선택일지도 몰라요. 데모는 이렇게 쓸 수 있어요.
[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {
    clockView.date = change[NSKeyValueChangeNewKey];
}];
FBKVOcontroller의 실현 원리는 이 글을 볼 수 있다. 자체 방출의 실현을 통해 프로그램원들은remove감청에 더 이상 관심을 가지지 않는다.그러나 그 대상은 자신의 속성을 감청할 수 없다. 만약 당신의 코드가 이렇다면
[self.KVOController observe:self keyPath:@"date" options:NSKeyValueObservingOptionNew block:^(NSDictionary *change) {
    // to do
}];

유감스럽게도 순환 인용 문제가 또 발생했습니다. FBKVOcontroller의 NSMapTable 대상은retain 키 대상이기 때문입니다. 구체적인 코드는 다음과 같습니다.
[_objectInfosMap setObject:infos forKey:object];

그렇다면 FBKVOcontroller는 어떻게 스스로 풀었을까?동적 속성이라는 네 글자로 요약할 수 있습니다.관찰자 귀속 동적 속성self.KVOcontroller, 동적 귀속된 KVOcontroller는 관찰자의 방출에 따라 방출된다. KVOcontroller는 자신의 dealloc 함수에서 KVO 감청을 제거하고 관찰자의 Remove를 동적 속성의 dealloc 함수로 교묘하게 옮긴다.
그런데 이게 무슨 소용이야?대상은 여전히 자신의 속성을 감청할 수 없습니다. set 함수를 다시 써야 합니다.HTBKVObservation은 당신의 생각을 바꿀 수 있습니다. FBKVOcontroller와 같은 사람입니다. 코드는 이렇게 쓸 수 있습니다.
self.anObservation = [HTBKVObservation observe:anObjectToObserve keyPath:@"observeMe" options:0 callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {
   // to do
}];

HTBKVObservation은 동적 속성을 사용하지 않고 속성으로 자동 방출을 실현한다.객체의 등록 정보를 모니터링할 수 있지만 등록 정보 HTBKVObservation을 만들어야 합니다.여기에 나는 그것에 대해 약간의 확장을 하였는데, 사용하기 편리하고, 코드는 이렇게 쓸 수 있다
[self observe:self keyPath:@"KVOPath" options:NSKeyValueObservingOptionNew callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {
   // to do
}];

FBKVOcontroller와 HTBKVObservation은 속성이나 동적 속성을 통해 교묘하게 KVO의remove를 제3자에게 옮기고 KVO 사건의 결합을 실현하여 자방출의 실현에 참고 방향을 제공했다.

NSNotification의 자동 해제


KVO에 대해 이야기하고 NSNotification에 대해 다시 이야기합시다.Notification에 대해 ReactiveCocoa는 잘 봉인되어 있으며, 인터넷에는 어떻게 사용하는지 소개하는 글이 많아서 더 이상 설명하지 않겠습니다.코드 직접 보기
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] subscribeNext:^(id x) {
        // to do
    }
];

간단명료하다. 관찰자 dealloc에서 유감스럽게도 NSNotification은 제거할 필요가 없다. 왜냐하면 대상은 스스로 방출할 필요가 없기 때문이다. 정확한 코드는 이렇게 해야 한다.
[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
        // to do
    }
];

타이머, KVO, NSNotification을 제외하고 봉인된 특정한 기능 대상, 예를 들어 HttpRequest, 데이터베이스ListSql 등을 포함하여 자방출을 합리적으로 이용하면 사용자에게 더 많은 편의를 줄 수 있고crash가 발생할 확률도 줄일 수 있다.자동 방출을 실현하는 방법은 다음과 같은 세 가지 방식으로 요약할 수 있다. Reactive Cocoa 자동 방출의 원리는 FBKVOcontroller와 달리 속성이나 동적 속성을 통해 실현되는 것이 아니라 swizzling을 통해 대상을 관찰하는 dealloc 함수를 통해 사용자 정의 dealloc 함수를 실제적으로 청소하지만 기본적으로 청소하는 것이 아니다. willDeallocSignal에 알려줄 때 모든 청소 작업을 완성해야 한다.
동적 속성의 자동 방출@property의 자동 방출 swizzling dealloc의 자동 방출전재:http://www.olinone.com/?p=232

좋은 웹페이지 즐겨찾기