Reputation: 51374
Could some one help me convert the below code to support ARC?
UIFont *boldFont = [UIFont fontWithName:@"DINPro-Medium" size:14];
CTFontRef ctBoldFont = CTFontCreateWithName((__bridge CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
CGColorRef cgColor = UIColorFromRGB(0x2b776d).CGColor;
NSNumber* underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];
NSDictionary *ULSubattributes = [NSDictionary dictionaryWithObjectsAndKeys:
CFBridgingRelease(ctBoldFont), (id)(id)kCTFontAttributeName,
cgColor, (id)kCTForegroundColorAttributeName,underline, (NSString*)kCTUnderlineStyleAttributeName, nil];
I am getting a crash on the last line saying,
*** -[Not A Type retain]: message sent to deallocated instance 0x20ad4910
*** -[Not A Type class]: message sent to deallocated instance 0x20ad4910
I hope this is a duplicate question. But I am stuck. Thanks.
Upvotes: 2
Views: 846
Reputation: 41642
/* OK */UIFont *boldFont = [UIFont fontWithName:@"DINPro-Medium" size:14];
assert(boldFont); // just be sure
/* OK */CTFontRef ctBoldFont = CTFontCreateWithName((__bridge CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
assert(boldFont); // just be sure
/* 1) CGColorRef cgColor = UIColorFromRGB(0x2b776d).CGColor; */
CGColorRef cgColor = CGColorCreateCopy( UIColorFromRGB(0x2b776d).CGColor );
assert(cgColor); // just to be sure
/* OK */NSNumber* underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];
NSDictionary *ULSubattributes = @{
/* you don't own the kCT strings */(__bridge NSString *)kCTFontAttributeName : CFBridgingRelease(ctBoldFont),
/* ... */ (__bridge NSString *)kCTForegroundColorAttributeName : CFBridgingRelease(cgColor),
/* ... */ (__bridge NSString *)kCTUnderlineStyleAttributeName : underline };
1) There is a bug in iOS pre-iOS6 where ARC will release the UIColor backing the CGColorRef while you are still using the CGColorRef. I know this since I created a rdar which was then reported as fixed in iOS 6.
PS: a nice blog by Mike Ash here
EDIT: this code works fine in my iOS demo app (deploy set to 5.1 and 6 both) - see the log message. I made the dict an ivar.
{
UIFont *boldFont = [UIFont fontWithName:@"Helvetica" size:14];
assert(boldFont); // just be sure
CTFontRef ctBoldFont = CTFontCreateWithName((__bridge CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
assert(boldFont); // just be sure
CGColorRef cgColor = CGColorCreateCopy( [UIColor colorWithRed:0.8f green:0.8f blue:0.8f alpha:0.8f].CGColor );
assert(cgColor);
NSNumber* underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];
assert(underline);
ULSubattributes = @{
(__bridge NSString *)kCTFontAttributeName : CFBridgingRelease(ctBoldFont),
(__bridge NSString *)kCTForegroundColorAttributeName : CFBridgingRelease(cgColor),
(__bridge NSString *)kCTUnderlineStyleAttributeName : underline };
NSLog(@"ULSubattributes: %@", ULSubattributes);
}
2013-04-12 11:48:20.294 WebViewScrollTester[44147:c07] ULSubattributes: { CTForegroundColor = " [ (kCGColorSpaceDeviceRGB)] ( 0.8 0.8 0.8 0.8 )"; NSFont = "CTFont \nCTFontDescriptor {type = mutable dict, count = 1,\nentries =>\n\t1 : {contents = \"NSFontNameAttribute\"} = {contents = \"Helvetica\"}\n}\n>"; NSUnderline = 1; }
EDIT2: I even added a dispatch_after to show nothing has gotten released by ARC:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^
{
NSLog(@"ULSubattributes: %@", ULSubattributes);
} );
Upvotes: 2
Reputation: 535306
Here is some actual working code of mine that does something quite similar to yours:
CTFontRef font2 =
CTFontCreateCopyWithSymbolicTraits (
basefont, f, nil, kCTFontBoldTrait, kCTFontBoldTrait);
NSDictionary* d2 =
@{(NSString*)kCTFontAttributeName: CFBridgingRelease(font2)};
[mas addAttributes:d2 range:encRange];
Note that I do not release font2
! CFBridgingRelease
means "ARC, this object has been retained; you release it when the time comes." And ARC does. No leak, no zombie, no crash, no problem.
(On the other hand, basefont
, which was created earlier with CTFontCreateWithName
and was never handed over to ARC for control, must be released explicitly with CFRelease
.)
Here is a whole lot more Core Text code from my book, showing ARC memory management throughout:
http://www.apeth.com/iOSBook/ch23.html#_core_text
And here is the section of my book about CFType memory management with ARC:
http://www.apeth.com/iOSBook/ch12.html#_memory_management_of_cftyperefs
Upvotes: 3