assign properties, ARC and Core Foundation objects

2019-01-14 10:29发布

问题:

Edit 2.

Thanks to Ken this is now working. And I even think I understand why :-)

Here's the amended line:

- (void) reCreatePath {
    CGMutablePathRef p = ::CGPathCreateMutable() ;

    ::CGPathMoveToPoint         (p, 0, TL.x, TL.y) ;
    // [snip]
    ::CGPathAddLineToPoint      (p, 0, BL.x, BL.y) ;
    ::CGPathCloseSubpath(p) ;


    self.path = p ;
    ::CGPathRelease(p) ;   // <<== THIS IS IT!! :-)
}

Edit.

I still don't get it. I tried Chuck suggestion:

@property (nonatomic, strong) __attribute__((NSObject)) CGPathRef  path ;

Like so:

@interface TopLeftSlidingView  ()

@property (nonatomic, strong) __attribute__((NSObject)) CGPathRef  path ;

@end

And at the point where I recreate the CGPath:

- (void) reCreatePath {
    CGMutablePathRef p = ::CGPathCreateMutable() ;

    ::CGPathMoveToPoint         (p, 0, TL.x, TL.y) ;
    // [snip]
    ::CGPathAddLineToPoint      (p, 0, BL.x, BL.y) ;
    ::CGPathCloseSubpath(p) ;


//    self.path = (__bridge CGMutablePathRef) p ;
//    self.path = (__bridge_transfer CGMutablePathRef) p ;
//    self.path = (__bridge_retained CGMutablePathRef) p ;
    self.path = p ;
}

Either of the three commented out lines results in a compiler error. The non commented line does compile, but generates an analyser warning:

/Users/verec/Projects/WordGame/WordGame/classes/TopLeftSlidingView.mm:211:26:
 Call to function 'CGPathCreateMutable' returns a Core Foundation object with
 a +1 retain count

followed by:

/Users/verec/Projects/WordGame/WordGame/classes/TopLeftSlidingView.mm:225:5:
 Object leaked: object allocated and stored into 'p' is not referenced later 
 in this execution path and has a retain count of +1

I just do not get it :(


Consider:

@interface Test : NSObject

@property (nonatomic, assign) CGColorRef color ;

@end

@implementation Test

- (void) dealloc {
    if (self.color) {
        ::CGColorRelease(self.color) ;
        self.color = 0 ;
    }
}

- (id) init {
    if (self = [super init]) {
        self.color = ::CGColorRetain([UIColor blueColor].CGColor) ;
    }
    return self ;
}

@end

This all compiles (and seemingly runs) fine except that the analyser keeps reporting warnings.

In essence what this code is saying is: "Please ARC, don't bother doing anything at all with color, please treat it the way you'd treat any other assign property, be it an BOOL or CGFloat, I'm handling memory management all by my own!"

Except that ARC refuses to listen to me and still complains!

I have read many questions here on SO, but none of them seem to address this issue ...

The key thing here, and the compiler (though not the analyser) seems to agree, is that by declaring the property `assign' I have claimed to handle it all on my own...

So I must be wrong, but I just don't see why ...

What's wrong?

回答1:

If you're using the automatically synthesized getters and setters, there is indeed a memory management problem here. In the setter, your CGColor needs to be released and the new value retained, but the assign accessor will not do this for you — it literally just assigns the new pointer value to the variable. You'll need to implement your own accessors in order to manage the memory correctly.

However, if you'd like, ARC can handle this for you instead of you having to do it yourself. Just declare it like so:

@property(nonatomic, strong) __attribute__((NSObject)) CGColorRef color;