Objective-C 사이드북 - 12:Cocoa 메모리 관리
26644 단어 Objective-C
1. 대상의 생명주기 대상의 생명주기는 탄생(alloc 또는 new 방법으로 실현), 생존(메시지 수신과 실행 조작), 친구(방법의 조합과 파라미터를 빌려), 방출(그들의 생명이 끝날 때 최종적으로 죽는다)을 포함한다.객체의 라이프 사이클이 끝나면 객체의 원자재(메모리)가 새 객체에 사용되도록 재확보됩니다.
인용 계수 (reference counting): 모든 대상은 인용 계수기나 보존 계수기라고 불리는 정수를 가지고 있습니다.한 단락의 코드가 대상에 접근해야 할 때, 이 코드는 이 대상의 보존 계수기 값을 1로 더해서, "내가 이 대상에 접근할 것"을 표시한다.이 코드가 대상의 접근을 끝낼 때, 대상의 보류 계수기 값을 1로 줄여서, 대상이 더 이상 접근하지 않는다는 것을 표시합니다.보류 계수기 값이 0일 때, 이 대상에 더 이상 코드가 접근하지 않기 때문에, 대상은 삭제되고, 다시 사용하기 위해 사용된 메모리는 시스템에서 회수됩니다.
alloc, new,copy (수신 대상의 복사본 생성) 를 사용하여 대상을 만들 때, 대상의 보존 계수기 값이 1로 설정됩니다.대상의 보존 계수기 값을 늘리려면 대상에게retain 메시지를 보낼 수 있고, 대상의 보존 계수기 값을 줄이려면release 메시지를 보낼 수 있습니다.
보류 카운터가 0으로 되어 있는 객체가 제거되면 Objective-C는 객체에 dealloc 메시지를 자동으로 보냅니다.너는 자신의 대상에서 dealloc 방법을 다시 쓸 수 있다.이런 방식을 통해 이미 분배된 모든 관련 자원을 방출할 수 있다.dealloc 방법을 직접 사용하지 마십시오.보존 카운터의 현재 값을 얻으려면retainCount 메시지를 보낼 수 있습니다.서명은 다음과 같습니다.
-
(id) retain;
//
-
(
void
) release;
//
-
(unsigned) retainCount;
//
예를 들어 [[[car retain] setTire: tire atIndex:2];카의 객체가 보존 카운터 값을 1씩 더하고 setTire 작업을 수행해야 함을 나타냅니다.Example:
1
//
2
//
Main.m
3
//
RetainCount1
4
//
1
5
//
6
//
Created by Elf Sundae on 10/23/10.
7
//
Copyright 2010 Elf.Sundae(at)Gmail.com. All rights reserved.
8
//
9
10
#import
<
Cocoa
/
Cocoa.h
>
11
12
@interface RetainTracker : NSObject
13
14
@end
15
16
@implementation RetainTracker
17
18
-
(id) init
19
{
20
if
(self
=
[super init])
21
{
22
NSLog(
@"
init: Retain count of %d.
"
,[self retainCount]);
23
}
24
return
self;
25
}
26
27
-
(
void
) dealloc
28
{
29
NSLog(
@"
dealloc called.Bye Bye.
"
);
30
[super dealloc];
31
}
32
33
@end
34
35
36
37
int
main (
int
argc,
const
char
*
argv[])
38
{
39
40
41
RetainTracker
*
tracker
=
[RetainTracker
new
];
42
43
[tracker retain];
44
NSLog(
@"
%d
"
,[tracker retainCount]);
45
46
[tracker retain];
47
NSLog(
@"
%d
"
,[tracker retainCount]);
48
49
[tracker release];
50
NSLog(
@"
%d
"
,[tracker retainCount]);
51
52
53
[tracker release];
54
NSLog(
@"
%d
"
,[tracker retainCount]);
55
56
[tracker retain];
57
NSLog(
@"
%d
"
,[tracker retainCount]);
58
59
[tracker release];
60
NSLog(
@"
%d
"
,[tracker retainCount]);
61
62
[tracker release];
63
64
65
return
0
;
66
}
67
출력:
init: Retain count of 1.232121dealloc called.Bye Bye.
2. 대상 소유권(object ownership): 만약에 한 대상이 다른 대상을 가리키는 실례 변수를 가지고 있다면 그 대상이 이러한 대상을 가지고 있다고 한다.즉, 솔리드는 자신이 소유한 객체의 정리를 책임져야 합니다.여러 개의 실체가 특정한 대상을 가지고 있을 때 대상의 소유권 관계는 더욱 복잡해진다. 이것도 보존계수기 값이 1보다 클 수 있는 원인이다.위의 RetainCount1 예에서main() 함수는RetainTracker 클래스의 대상을 가지고 있기 때문에main()은 클래스의 대상을 정리해야 한다.OOP 기본 섹션에서 Car의 engine setter 방법을 생각해 보십시오.
-
(
void
) setEngine: (Engine
*
) newEngine;
main() 함수에서 이 메서드를 호출하는 방법:
Engine
*
engine
=
[Engine
new
];
[car setEngine: engine];
현재 어느 실체가engine 대상을 가지고 있습니까?main () 함수입니까? 아니면 Car 클래스입니까?
다음은 setEngine을 작성하는 더 나은 방법입니다.
1
-
(
void
) setEngine: (Engine
*
) newEngine
2
{
3
[newEngine retain];
4
[engine release];
5
engine
=
newEngine;
6
}
//
setEngine
방문 방법에서 새 대상을 보류한 다음에 옛 대상을 풀어주면 문제가 되지 않습니다.In your accessors, if you retain the new object before you release the old object, you’ll be safe.
3. 자동 방출(Autorelease) 자동 방출 탱크(autorelease pool)는 실체를 저장하는 탱크(집합)로 이 실체들은 대상일 수 있고 자동으로 방출될 수 있다.NSObject 클래스는 autorelease 메서드를 제공합니다.
-
(id) autorelease;
이 방법은 미래의 어느 시간에 보내는release 메시지를 미리 설정하고, 그 반환값은 메시지를 받는 대상이다.객체에 autorelease 메시지를 보낼 때 NSAutoreleasePool에 객체를 실제로 추가합니다.자동 방출 탱크가 소각되면, 이 탱크의 모든 대상에게release 메시지를 보냅니다.
1
-
(NSString
*
) description
2
{
3
NSString
*
description;
4
description
=
[[NSString alloc]
5
initWithFormat:
@"
I am %d years old
"
,
4
];
6
return
([description autorelease]);
7
}
//
description
자동 풀의 제거 시간: Foundation 라이브러리 도구에서 자동 풀을 생성하고 제거하는 방법은 다음과 같습니다.
NSAutoreleasePool
*
pool;
pool
=
[[NSAutoreleasePool alloc] init];
…
[pool release];
자동 해제 탱크를 만들 때, 이 탱크는 자동으로 활성 탱크가 됩니다.풀을 풀면 예약된 카운터 값이 0이 되고 풀은 제거됩니다.풀을 제거하는 동안 풀에 포함된 모든 객체가 해제됩니다.AppKit를 사용할 때, 코코아는 정기적으로 자동으로 자동 방출 탱크를 만들고 폐기합니다.일반적으로 프로그램에서 현재 이벤트(예를 들어 마우스 클릭이나 버튼)를 처리한 후에 이 동작을 실행합니다.너는 임의의 자동 방출 대상을 사용할 수 있다. 더 이상 사용하지 않을 때, 자동 방출 탱크는 자동으로 이 대상들을 정리할 것이다.설명: Xcode가 자동으로 생성한 코드에서 자동 방출 탱크의 대상을 제거하는 또 다른 방식을 사용했다. -drain 방법, 이 방법은 자동 방출 탱크를 비우고 제거하지 않는다-drain 방법은 Mac OS X 10.4(Tiger) 이상 버전에만 적용됩니다.
풀 자동 풀기 작업: 예: RetainCount2
OBJECTIVE-C CODE :RetainCount2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//
// Main.m
// RetainCount2
// 2:
//
// Created by Elf Sundae on 10/25/10.
// Copyright 2010 Elf.Sundae(at)Gmail.com. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface RetainTracker : NSObject
@end
@implementation RetainTracker
- (id) init
{
if (self = [super init])
{
NSLog(@"init: Retain count of %d.",[self retainCount]);
}
return self;
}
- (void) dealloc
{
NSLog(@"dealloc called.Bye Bye.");
[super dealloc];
}
@end
int main (int argc, const char * argv[])
{
//
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
// (new) RetainTracket
RetainTracker *tracker = [RetainTracker new]; // count:1
NSLog(@"%d",[tracker retainCount]);
// ,retain trancker
[tracker retain]; // count:2
NSLog(@"%d",[tracker retainCount]);
// autorelease , pool
[tracker autorelease]; // count: still 2
NSLog(@"%d",[tracker retainCount]);
// release retain
[tracker release]; //count: 1
NSLog(@"%d",[tracker retainCount]);
NSLog(@"releaseing pool");
[pool release];
return 0;
}
//
// Main.m
// RetainCount2
//메모리 관리 연습2: 자동 방출 탱크 사용
//
// Created by Elf Sundae on 10/25/10.
// Copyright 2010 Elf.Sundae(at)Gmail.com. All rights reserved.
//
#import
@interface RetainTracker : NSObject
@end
@implementation RetainTracker
- (id) init
{
if (self = [super init])
{
NSLog(@"init: Retain count of %d.",[self retainCount]);
}
return self;
}
- (void) dealloc
{
NSLog(@"dealloc called.Bye Bye.");
[super dealloc];
}
@end
int main (int argc, const char * argv[])
{
//자동 방출 탱크 만들기
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
//RetainTracket 객체 만들기(new)
RetainTracker *tracker = [RetainTracker new];//count:1
NSLog(@"%d",[tracker retainCount]);
//프레젠테이션 목적, retain 하나의trancker
[tracker retain];//count:2
NSLog(@"%d",[tracker retainCount]);
//대상에게 autorelease 메시지를 보내고 이 대상을 자동 방출 탱크pool에 추가합니다
[tracker autorelease];//count: still 2
NSLog(@"%d",[tracker retainCount]);
//release 이 대상은 위의retain을 상쇄합니다
[tracker release];//count: 1
NSLog(@"%d",[tracker retainCount]);
NSLog(@"releaseing pool");
[pool release];
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
PreferenceBundle에서 오른쪽 상단에 Respring 버튼을 클릭합니다.만나서 반갑습니다, Minazuki라고합니다. 프로필 이름 : Minazuki_dev Twitter : Repo : 아직 중학생이므로 말이 이상한 곳이 있습니다만 용서해 주세요… 🙏 theos (Mac이든 단품이든 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.