Reputation: 4373
I want to make an array of structs of which the size is known only at runtime
NSMutableArray *styleSettingsArray = [NSMutableArray array];
NSString *fontAlignmentAttribute = [element attributeNamed:@"TextAlignment"];
if(fontAlignmentAttribute)
{
CTTextAlignment alignment = [self getTextAlignment:fontAlignmentAttribute];
CTParagraphStyleSetting styleSetting = {kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment};
[styleSettingsArray addObject:[NSValue valueWithBytes:&styleSettings objCType:@encode(CTParagraphStyleSetting)]];
}
// other posible attributes
CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate((__bridge const CTParagraphStyleSetting *)(styleSettingsArray), [styleSettingsArray count]);
[dictionary setObject:(__bridge id)(paragraphStyleRef) forKey:(NSString*)kCTParagraphStyleAttributeName];
CFRelease(paragraphStyleRef);
This code does not work.
EDIT:
CTParagraphStyleCreate
takes a pointer to an array of CTParagraphStyleSetting
, such as
CTParagraphStyleSetting styleSettings[] = {
{ kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), alignment},
{...},
{...}
};
How can I allocate this array, and add stuff to it without knowing how much stuff will be in it ? (how do I use malloc ?)
Upvotes: 2
Views: 227
Reputation: 81856
To avoid having to collect the number of attributes and then create them in a second pass I suggest to use NSMutableData
instead of a plain C array or malloc. This style would allow you to use your existing code with only minimal changes:
NSMutableData *styleSettingsArray = [NSMutableData array];
NSString *fontAlignmentAttribute = [element attributeNamed:@"TextAlignment"];
CTTextAlignment alignment;
if (fontAlignmentAttribute)
{
alignment = [self getTextAlignment:fontAlignmentAttribute];
CTParagraphStyleSetting styleSetting = { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment};
[styleSettingsArray appendBytes:&styleSetting length:sizeof(styleSetting)];
}
// other posible attributes
CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate([styleSettingsArray bytes], [styleSettingsArray length] / sizeof(CTParagraphStyleSetting));
Edit: Please note the extension of the lifetime of the alignment
variable, compared to your code. This is necessary because it is referenced after the block ends in which it was declared before.
Upvotes: 1
Reputation: 122381
You cannot mix Objective-C or Core Foundation collections with plain C arrays in this way. Also as you have found out you need to wrap those CTParagraphStyleSetting
structs
in NSNumber
objects in order to store them. What a mess.
The approach I would take would be to do 2-passes; the first to determine how many attributes you have and the second to generate those attributes.
malloc()
).free()
).NOTE I have edited this answer as my previous answer was way off.
Upvotes: 2