ARC 및 비 ARC 하oc 객체 및 CF 객체 변환

OC와 FC 사이를 전환할 때 주로 대상의 귀속 문제다.다음과 같은 두 가지 방법이 있습니다.
1. 매크로를 사용하면 귀속자가 OC에서 CF로 갈지, 아니면 CF에서 OC로 갈지 표시할 수 있다.
NS_INLINE CFTypeRef CFBridgingRetain(id X) { 
    return (__bridge_retain CFTypeRef)X; 
} 
  
NS_INLINE id CFBridgingRelease(CFTypeRef X) { 
    return (__bridge_transfer id)X; 
}

2. 전환부호를 사용한다. 예를 들어bridge,__bridge_transfer,__bridge_retained
__bridge: 대상의 모든 관계 변화와 관련이 없습니다
__bridge_transfer: ARC 소유권 부여
__bridge_retained: ARC 소유권 해제
id my_id; 
CFStringRef my_cfref; 
 
NSString   *a = (__bridge NSString*)my_cfref;     // Noop cast. 
CFStringRef b = (__bridge CFStringRef)my_id;      // Noop cast. 


NSString   *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef 
CFStringRef d = (__bridge_retained CFStringRef)my_id;  // returned CFRef is +1

ARC 이외의 모드:
#pragma mark – View lifecycle 


- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSLog(@"=%@", [self escape:@"LIN986LIN"]); 
} 
-(NSString *)escape:(NSString *)text 
{ 
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)text,NULL,CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
}

ARC 모드:
위의 함수를 다음과 같이 자동으로 변환하는 xcode를 볼 수 있습니다.
#pragma mark – View lifecycle 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSLog(@"=%@", [self escape:@"wangjun"]); 
} 
-(NSString *)escape:(NSString *)text  
{ 
     return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)text,NULL,CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
}
arc에서 CF와 OC 간의 전환교량은bridge, 두 가지 방법이 있습니다.
__bridge_transfer ARC 관리 메모리
__bridge_retained ARC 메모리 관리 해제
oc에서 CF로의 전환은 OC의 메모리 관리권을 방출해야 한다.
NSString *str = [[NSString alloc] initWithFormat:@"Welcome 	, %@!", name]; 
CFStringRef strref = (__bridge_retained CFStringRef)str; 
// do something with strref  
CFRelease(strref);
마지막으로 CF가 메모리를 방출합니다.
위 코드는 다음과 같습니다.
CFStringRef strref = CFBridgingRetain(str); 
// do something with strref    
CFRelease(strref);
CF가 OC로 전환되고 객체의 소유자가 변경되면 CFBridgingRelease() 또는bridge_transfer .
OC가 CF로 전환되고 객체의 소유자가 변경되면 CFBridgingRetain() 또는bridge_retained
한 유형이 다른 유형으로 전환되지만 대상 소유자가 바뀌지 않으면 을 사용합니다bridge.
CF 객체와 OC 객체를 혼용하면 발생할 수 있는 문제:
ARC 모드에서 자동 회수는 Objective-C 대상에게만 유효하며, Core Foundation 대상에 대해서는 저희가 수동으로 방출해야 합니다. CFRelease().
다음 상황을 분석합니다.
하나의 방법으로 CGColorRef 객체 정의: CGColorRef cf
각각 다음과 같은 세 가지 방식을 통해 cf에 값을 부여한 후 cf를 사용할 때 어떤 차이가 있을까요?
방법 1:
UIColor* color = [[UIColor alloc] initWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f];
cf = color.CGColor;
방법2:
cf = [[UIColor alloc] initWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f].CGColor;
방법3:
cf = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f].CGColor;
방식 1과 방식 3은 운행에 문제가 없다.방식 2 다음에 cf를 사용하면 crash를 할 수 있습니다. 왜냐하면 이때 cf는 이미 야외 지침이기 때문입니다.
분석은 다음과 같습니다.
방식1에서 color 대상은 기본적으로strong강인용으로 이 방법의 생명주기 내에 모두 유효하며, 이 방법을 종료할 때 자동으로 풀에 방출됩니다.그래서 그 CGColor로 하는 건 문제 없어요.
방식 3은 유사합니다. colorWithRed:... 이것은 클래스입니다. autorelease 대상을 되돌려줍니다. 대상은 자동으로 풀을 풀기 전에 모두 유효하기 때문에 문제가 발생하지 않습니다.
방식2에서 생성된 UIColor 대상은 어떤 owner에게도 주지 않았고 weak의 약한 인용에 해당하며 alloc는 그 후에 바로 방출되었다. 그래서 그의 CGColor 변수도 이에 따라 야생 지침이 되었다.
ARC 아래 OC 객체가 CF 객체와 브리지됩니다.
다음 코드 행:
CFStringRef s1 = (CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
ARC 아래에 컴파일 문제가 보고되고 권장 솔루션이 제공됩니다.
CFStringRef s1 = (__bridge CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
여기서 NSString은 OC의 대상을 생성하고 메모리는 ARC가 책임진다.s1은 CF의 대상이며, 메모리는 스스로 수동으로 관리해야 한다.두 변수가 변환될 때 브리지 표식을 추가해야 합니다.
위의 경우 Crash도, 메모리 유출도 없습니다.alloc에서 나온 메모리는 ARC에서 회수되기 때문에 이 메모리의 모든 관계는 변하지 않습니다.
뒤에 CFRelease(s1)가 붙으면이 메모리는 ARC가 관리하기 때문에 과도하게 방출될 수 있다.
수정:
CFStringRef s1 = (__bridge_retained CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];
이 경우 대상의 소유권은 CF 대상에게 넘어간다.CFRelease(s1)를 추가해야 합니다.석방을 진행하지 않으면 누설이 발생할 수 있다.
다음 코드를 다시 보십시오.
CFUUIDRef uu = CFUUIDCreate(NULL);
CFStringRef s2 = CFUUIDCreateString(NULL, uu);
CFRelease(uu);


NSString* str = (__bridge NSString*)s2;
NSLog(@”STR:%@”,str);
CFRelease(s2);
이곳의 u와 s2는 모두 CFRelease를 사용하여 방출해야 한다. 왜냐하면 그들은 OC 대상이 아니고create에서 나온 메모리이며 소유권이 방출되지 않았기 때문이다.
다음 코드를 변경하면
NSString* str = (__bridge_transfer NSString*)s2;
이 때 프로그램을 실행하면crash를 일으킬 수 있습니다. s2의 소유권은 ARC의str에 맡겼기 때문에 ARC는 이 메모리를 방출하는 것을 책임집니다.
이때 CFRelease(s2)를 호출합니다.과도한 석방을 초래할 수 있다.그래서 이 업종을 대행해야 한다.
참고:
ARC 모드에서는 Objective-C 대상만 자동 회수가 유효하며,create,copy,retain 등을 사용하여 생성된CoreFoundation 대상은 우리가 수동으로 방출해야 합니다.CFRelease().

좋은 웹페이지 즐겨찾기