ARC 컴파일러가 아닌 ARC, 당신이 알아서 의미 메모리 관리을 담당하지만 두 경우 모두에서 메모리 관리가 정확히 같은 방식으로 작동합니다 의미 : 객체가 살아 남기해야하는 경우
- 을 그 분실되는 개체가 더 이상 필요하지 않은 경우
- (즉
retain
가하는 일입니다) 증가 카운터를 유지, 그 유지 카운터를 사용하면 객체에 수행하는 경우
- (즉
release
가하는 일입니다) 참조하기 전에 감소하지만, 아직 죽지 않아야한다. 메소드 결과로 반환해야하므로 (그리고 죽은 객체를 반환하지 않으려는 경우) 나중에 자동 보유 풀에 추가해야합니다 (예 : autorelease
의 경우와 같습니다. "나중에 해당 객체에 release
을 호출하십시오.")
- 새로 생성 된 객체의 보유 수는
1
입니다.
- 보유 계수가 0에 도달하면 개체가 해제됩니다.
직접 처리하든 컴파일러가 처리하든 관계없이 아무런 역할을하지 않습니다. 컴파일 후,이 메소드는 ARC와 함께 호출되지만 ARC에서는 컴파일러가 호출 된 메소드를 결정합니다. 몇 가지 추가 마법이 있습니다. ARC는 메소드 결과로 반환 할 때 autorelease 풀에 객체를 추가 할 필요가 항상있는 것은 아니지만 종종 최적화 될 수 있지만 호출자와 호출 된 메소드가 모두 사용중인 경우에만이 마법이 적용되므로주의하지 않아도됩니다. 호; 그 중 하나가 아니라면 보통 autorelease
이 사용됩니다 (ARC에서 이전과 똑같이 작동 함).
유일한주의해야 할 것은주기를 유지하는 것입니다. ARC를 사용하든 사용하지 않든, 참조 계산은 보유주기를 처리 할 수 없습니다. 차이점이 없습니다.
함정? 수신자 부담 브리징에주의하십시오. NSString *
과 CFStringRef
은 실제로 동일한 것이지만 ARC는 CF 세계에 대해 알지 못하므로 ARC가 NSString
을 처리하는 동안 CFString
을 처리해야합니다. ARC를 사용할 때 ARC에게 브리지 방법을 알려야합니다.
CFStringRef cfstr = ...;
NSString * nsstr = (__bridge_transfer NSString *)cfstr;
// NSString * nsstr = [(NSString *)cfstr autorelease];
코드는 위의 "ARC는 그 CFString
개체의 소유권을하고 당신이 그것으로 완료로 즉시 해제 알아서하십시오"를 의미한다. 코드는 아래 주석에 표시된 코드와 같이 동작합니다. 신중하게, cfstr
은 적어도 하나 이상의 보유 수를 가져야하며 ARC는 최소한 한 번만 그것을 해제합니다. 라운드 다른 방법 :
NSString * nsstr = ...;
CFStringRef cfstr = (__bridge_retained CFStringRef)cftr;
// CFStringRef cfstr = (CFStringRef)[nsstr retain];
코드는 위의 의미는 "ARC는 나에게 그 NSString
의 소유권을 적어주세요, 나는 그것으로 끝났어요 일단 해제 알아서 할게요." 물론, 당신은 그 약속을 지켜야합니다! 때때로 CFRelease(cfstr)
에 전화해야합니다. 그렇지 않으면 메모리가 누출됩니다.
마지막으로 유형 캐스트 인 (__bridge ...)
이 있으며 소유권이 이전되지 않았습니다. 캐스팅 결과를 주변에 유지하려고하면 포인터가 매달릴 수 있으므로 이런 종류의 캐스팅은 위험합니다. 일반적으로 ARC 객체가 함수가 반환 될 때까지 ARC가 유지하도록 CF 객체를 기대하는 함수에 ARC 객체를 공급할 때 사용합니다.이 기능을 반환하고 함수의 인자에 의해입니다 전에
이
doSomethingWithString((__bridge CFStringRef)nsstr);
ARC가 이제까지 그것을 액세스 더 이상 그 선 아래에 어떤 코드로 언제든지 nsstr
를 공개 하였다하더라도, 그것은 확실히 그것을 공개하지 않습니다이 항상 안전 정의가 함수가 반환 될 때까지 계속 살아있을 수 있습니다 (함수가 문자열을 활성 상태로 유지하려는 경우 유지해야하며 ARC는 보유 수가 0이되지 않으므로 ARC가이를 해제 한 후에 할당을 해제하지 않습니다).
가끔 오래된 API와에있는 대부분의 사람들은 ARC를 전달하고 투쟁하는 것 것은, void *
컨텍스트로 객체, 아직 실제로 죽은 간단하다
- (void)doIt {
NSDictionary myCallbackContext = ...;
[obj doSomethingWithCallbackSelector:@selector(iAmDone:)
context:(__bridge_retained void *)myCallbackContext
];
// Bridge cast above makes sure that ARC won't kill
// myCallbackContext prior to returning from this method.
// Think of:
// [obj doSomethingWithCallbackSelector:@selector(iAmDone:)
// context:(void *)[myCallbackContext retain]
// ];
}
// ...
- (void)iAmDone:(void *)context {
NSDictionary * contextDict = (__bridge_transfer NSDictionary *)context;
// Use contextDict as you you like, ARC will release it
// prior to returning from this method. Think of:
// NSDictionary * contextDict = [(NSDictionary *)context autorelease];
}
그리고 나는 진짜 큰해야 첫눈에 분명하지 않은 당신을위한 잡았다. 다음 코드를 고려하십시오 :
@implementation SomeObject {
id _someIVAR;
}
- (void)someMethod {
id someValue = ...;
_someIVAR = someValue;
}
이 코드는 ARC 및 비 ARC와 동일하지 않습니다. ARC에서 모든 변수는 기본적으로 강한, 그래서 ARC이 코드는 것 그냥이 코드처럼 동작 :
@interface SomeObject
@property (retain,nonatomic) id someIVAR;
@end
@implementation SomeObject
- (void)someMethod {
id someValue = ...;
self.someIVAR = someValue;
}
을 유지합니다 someValue
지정 개체가 살아 유지! 그들은 ARC에서 (단지 포인터, 그들은 아무것도 아닌 ARC에 바르 년대도 strong
또는 weak
이기 때문에 속성이, 다른
@interface SomeObject
@property (assign,nonatomic) id someIVAR;
@end
@implementation SomeObject
- (void)someMethod {
id someValue = ...;
self.someIVAR = someValue;
}
주 : 비 ARC의 코드는이 같은 동작합니다 __unsafe_unretained
라고하며 여기에 키워드는 안전하지 않은입니다.
ivars를 직접 사용하고 setters/getters에서 속성에 액세스하지 않는 코드가있는 경우 ARC가 아닌 값에서 ARC로 전환하면 정상적인 메모리 관리를 사용하는 코드의 유지주기가 발생할 수 있습니다. 반면에 ARC에서 ARC가 아닌 코드로 이동하면 포인터가 매달려 있습니다 (이전 객체에 대한 포인터이지만 객체가 이미 사망했기 때문에 아무데도 가리키고 사용하면 예기치 않은 결과가 발생 함). 전에는 예기치 않게 죽을 수도 있습니다.
이것은 합의로 보인다. 당신의 도움을 주셔서 감사합니다. – TomSwift