2012-04-01 1 views
2

iOS 5 용 응용 프로그램을 만들고 일부 그라디언트를 그립니다. 다음 그라디언트 코드는 ARC 전에 항상 사용해 왔지만 지금은 여러 번 사용할 때 (즉, 메모리 관리 문제 일 때) 내 장치에서 더 이상 작동하지 않습니다 (그러나 시뮬레이터에서 작동 함). 어쨌든, 여기에 코드입니다 : ARC에서 CoreGraphics 그라데이션에 __bridge를 사용하면 응용 프로그램이 중단됩니다.

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGFloat locations[] = { 0.0, 1.0 }; 

NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil]; 

CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations); 

CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); 
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)); 

CGContextSaveGState(context); 
CGContextAddRect(context, rect); 
CGContextClip(context); 
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); 
CGContextRestoreGState(context); 

CGGradientRelease(gradient); 

원래, 더 __bridge 문 없었다, 엑스 코드에 의해 제안 내가 그들을했다. 문제의 원인은 무엇입니까?

+0

stacktrace에서 어느 시점에서 충돌이 발생합니까? 나는 그것이 실패 할 수있는 몇 가지 점을 생각할 수있다. 그라디언트 그리기, 그라디언트 만들기 등의 작업을 수행 할 때 오류가 발생합니까? –

+0

objc 객체에 대한 __bridge 대화를 할 때 정확하게 꺽쇠를.습니다. –

답변

4

변수는 startColor 등의 변수 일 수 있습니다. UIColor의 -CGColor 메소드를 통해 생성 된 CGColorRef가 위 코드의 어느 지점보다 위에있는 것으로 추측됩니다.

this answer에 명시된대로 CGColorRef를 명시 적으로 보유하지 않으면 해당 CGColorRef를 생성 한 UIColor가 할당 해제 된 후에 사라질 수 있습니다. CGColorRefs를 추출한 후에 UIColors를 다시 사용하지 않는다면 ARC는 CGColorRefs를 사용할 기회를 갖기 전에이 UIColors를 할당 해제하기로 결정할 수 있습니다. 시뮬레이터와 실제 장치 사이의 개체 수명이 다르기 때문에이 충돌이 하나의 충돌을 설명 할 수는 있지만 다른 충돌은 설명 할 수 없습니다. 이것에

내 솔루션은 다음과 같은 ID로 즉시 캐스트를 사용하는 것이 었습니다 : 컴파일러가 CGColorRefs의 소유권 이전으로까지 올바른 일을

NSArray *colors = [NSArray arrayWithObjects:(id)[color1 CGColor], 
              (id)[color2 CGColor], nil]; 

.

NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil]; 

CFArrayRef colorArray = (__bridge_retained CFArrayRef)colors; 
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, locations); 
CFRelease(colorArray); 

이것은 뒤에 남겨두고, 핵심 재단에 걸쳐있는 NSArray 교량 : 다음 코드는 확인이 충분히 배회 할 수있는 경우에 대비하여 NSArray를 조기에 해제 될 가능성도있다

CFArrayRef는 최소한 1의 보유 수를 갖습니다. 그런 다음 그래디언트 생성에서 그라디언트를 사용하여 참조를 유지하고 완료되면 수동으로 릴리스 할 수 있습니다.

그러나 Bringo가 Core Graphics의 C API에서이 작업을 수행하는 것이 가장 쉬운 방법 일 수 있습니다. 나는 당신이 미래에 어떤 비슷한 문제에 부딪 힐 경우에 대비하여 문제의 잠재적 원인을 설명 할 것이라고 생각했습니다.

5

정확하게 똑같은 문제가 발생했습니다. 나는 나를 위해 문제를 해결 CGGradientCreateWithColorComponents를 사용하여 resorted있다. 의 NSArray를 CGFloat의 배열로 변환해야합니다.

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGFloat locations[2] = { 0.0, 1.0 }; 

CGFloat components[8] = { 0.909, 0.909, 0.909, 1.0, // Start color 
          0.698f, 0.698f, 0.698f, 1.0 }; // End color 

CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, 
            locations, 2);