2013-01-22 36 views
5

我在ARC下使用[UIBezierPath CGPath]CAShapeLayer發生了BAD ACCESS錯誤。我嘗試了各種橋接方式,但我不清楚這是否是問題所在。我已隔離崩潰使用makeToPath方法的結果:在ARC下使用帶有CAShapeLayer的[UIBezierPath CGPath]崩潰

maskLayer = [CAShapeLayer layer]; 
maskLayer.path = [self makeToPath]; 

但這不會崩潰:

maskLayer = [CAShapeLayer layer]; 
maskLayer.path = [self makeFromPath]; 

有什麼無效與makeToPath創建的路徑?我計劃使用路徑與CABasicAnimation一旦我排序這崩潰了。什麼是從UIBezierPathCGPathRef s正確的ARC橋接?

-(CGPathRef)makeToPath 
{ 
    UIBezierPath* triangle = [UIBezierPath bezierPath]; 
    [triangle moveToPoint:CGPointZero]; 
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)]; 
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)]; 
    [triangle closePath]; 
    return [triangle CGPath]; 
} 

-(CGPathRef)makeFromPath 
{ 
    UIBezierPath*rect = [UIBezierPath bezierPathWithRect:self.view.frame]; 
    return [rect CGPath]; 
} 

UPDATE所以我改變了我的.h文件中按照下面的答案,但我仍然得到崩潰

-(CGPathRef)makeToPath CF_RETURNS_RETAINED; 
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED; 

我也試圖讓我的方法每答案here(返回UIBezierPath實例如下所示)。仍然沒有成功。任何人都想給我關於如何解決這個問題的長篇解釋?

maskLayer.path = [[self makeToPath] CGPath];// CRASHES 
morph.toValue = CFBridgingRelease([[self makeToPath] CGPath]);// CRASHES 

-(UIBezierPath*)makeToPath 
{ 
    UIBezierPath* triangle = [UIBezierPath bezierPath]; 
    [triangle moveToPoint:CGPointZero]; 
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)]; 
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)]; 
    [triangle closePath]; 
    return triangle; 
} 
+0

[設備上運行時EXC \ _ARM \ _DA \ _ALIGN錯誤(HTTP的可能重複:// stackoverflow.com/questions/14129785/exc-arm-da-align-error-when-running-on-a-device) –

+0

我使用最後的語法,讓'makeToPath'返回'UIBezierPath *',然後使用'maskLayer。 path = [[self makeToPath] CGPath];',所有的時間。但我也立即使用'maskLayer',例如'[self.view.layer addSublayer:maskLayer]'。在設置'path'後,你用'maskLayer'做了什麼?你能告訴我們嗎? – Rob

+1

@Rob - 我清理了一些代碼,運行了'nap debugger',現在它工作。 –

回答

8

問題是與返回CGPath。返回的值是ARC不包含的CGPathRef。方法結束後,您創建的UIBezierPath被釋放。因此也釋放了CGPathRef。 您可以指定源註解,讓ARC知道你的意圖:

在.h文件:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED; 
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED; 
+0

謝謝 - 我沒有使用'bezierPathWithRect'函數的方法得到崩潰。這很混亂。你知道爲什麼這種方法不會崩潰嗎? –

+1

呵呵。我不知道這些註釋是否可用。太棒了,謝謝! (文檔在這裏,好奇:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#conversion-to-retainable-object-pointer-type-of-expressions-with-known-semantics) –

+0

@skinnyTOD :訪問釋放對象的行爲未定義。 – diederikh

3

正如其他海報指出,要返回從UIBezierPath對象採取了CGPath引用,在方法結束時超出範圍。作爲對UIBezierPath CGPath屬性的文件說:

的路徑對象本身是由UIBezierPath對象所擁有的,是 有效期至您做進一步的修改路徑。

您需要創建CGPath的副本,並返回:

-(CGPathRef)makeToPath 
{ 
    UIBezierPath* triangle = [UIBezierPath bezierPath]; 
    [triangle moveToPoint:CGPointZero]; 
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)]; 
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)]; 
    [triangle closePath]; 
    CGPathRef theCGPath = [triangle CGPath]; 
    return CGPathCreateCopy(theCGPath); 
} 

我讀的鏈接LLVM項目的方式,我認爲cf_returns_retained預選賽旨在告訴來電者的內存管理策略的返回值,而不是爲你保留。

因此,我認爲你們都需要創建路徑的副本並添加cf_returns_retained限定符。但是,我不清楚該限定符的語法。 (以前從未使用過。)

假設其他海報有正確的語法,它會是這個樣子:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED; 
{ 
    UIBezierPath* triangle = [UIBezierPath bezierPath]; 
    [triangle moveToPoint:CGPointZero]; 
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)]; 
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)]; 
    [triangle closePath]; 
    CGPathRef theCGPath = [triangle CGPath]; 
    return CGPathCreateCopy(theCGPath); 
} 
+2

CF_RETURNS_RETAINED註釋實際上只在您的方法不符合[CoreFoundation命名規則]時才需要(http://developer.apple.com/library/ios/DOCUMENTATION/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html #// apple_ref/DOC/UID/20001148-103029)。建議改爲重命名你的方法。 –

相關問題