I stuck with replacement the function sizeWithFont that was deprecated - objective-c

I have this line code.
CGSize size = [(text ? text : #"") sizeWithFont:font constrainedToSize:CGSizeMake(220, 9999) lineBreakMode:NSLineBreakByWordWrapping];
And the function sizeWithFont was deprecated.
After search here i found this solution.
Replace the deprecation sizeWithFont:minFontSIze:actualFontSize in ios 7
And I use this method :
-(CGSize)frameForText:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode {
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = lineBreakMode;
NSDictionary * attributes = #{NSFontAttributeName:font,
NSParagraphStyleAttributeName:paragraphStyle
};
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
//Contains both width & height ... Needed: The height
return textRect.size;
}
But I still do not understand something in my code that I found so I can not restore the original line
What this line code does? (text ? text : #"")
How can I send this to the frameForText function for it to work for me?

Related

How do I center a number in a circle?

I'm trying to produce a set of custom page numbers. The current page number will be displayed. The others will simply be open circles.
Using the code below, I'm getting the desired results - except, with the new text attributes in iOS7, I cannot figure out how to center the number.
Any help will be appreciated.
Original iOS6 code:
[pageNumber drawInRect:CGRectMake(x,(self.frame.size.height-_currentPageDiameter)/2-1,_currentPageDiameter,_currentPageDiameter) withFont:[UIFont systemFontOfSize:_currentPageDiameter-2] lineBreakMode:UILineBreakModeCharacterWrap alignment:NSTextAlignmentCenter];
My iOS7 code:
NSString *pageNumber = [NSString stringWithFormat:#"%i", i+1];
CGContextSetFillColorWithColor(myContext, [[UIColor whiteColor] CGColor]);
UIFont* font = [UIFont systemFontOfSize:_currentPageDiameter-2];
NSDictionary *attrs = #{ NSForegroundColorAttributeName : [UIColor whiteColor],
NSFontAttributeName : font,
NSTextEffectAttributeName : NSTextEffectLetterpressStyle};
CGRect r = CGRectMake(x,(self.frame.size.height-_currentPageDiameter)/2-1,_currentPageDiameter,_currentPageDiameter);
[pageNumber drawInRect:r withAttributes:attrs];
The property you're missing for center alignment is defined the following way. I also added the line break mode you had defined on the iOS6 code:
NSMutableParagraphStyle *paragrapStyle = [[NSMutableParagraphStyle alloc] init];
paragrapStyle.alignment = NSTextAlignmentCenter;
paragrapStyle.lineBreakMode = NSLineBreakByCharWrapping;
You just place them in the attributes dictionary under the key:
NSArray *attrs = #{
NSParagraphStyleAttributeName : paragraphStyle,
...
};

drawInRect:withFont:lineBreakMode:alignment deprecation in IOS 7

I have a message of deprecated method.
The line of code is this one :
[string drawInRect:drawArea withFont:uifont lineBreakMode:linebreaks[lineBreakMode] alignment:alignments[hAlignment]];
So I want to replace it with this code :
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = #{ NSFontAttributeName: uifont,
NSParagraphStyleAttributeName: paragraphStyle};
[string drawInRect:drawArea withAttributes:attributes];
After this replacement, the warning is not here anymore. But, all my text is invisible. For example, I have a text "Options" which is not visible (but I can still click on it).
Someone can help on this please?
Regard

NSTextAttachment with text flowing around it

I have a TextKit based editor with support to adding images. I want to show each image on separate lines.
My code looks like this (Thank you TextEdit), in my subclass of NSTextStorage
- (void)addImageAssets:(NSArray *)allAssets atRange:(NSRange)range;
{
NSMutableAttributedString *attachments = [NSMutableAttributedString new];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentCenter;
paragraphStyle.lineSpacing = 20.0f;
for (ALAsset *newAsset in allAssets)
{
UIImage *theImage = [UIImage imageWithCGImage:newAsset.aspectRatioThumbnail];
NSTextAttachment *textAttachment = [NSTextAttachment new];
textAttachment.image = theImage;
NSMutableAttributedString *replacementString = [NSMutableAttributedString new];
[replacementString appendAttributedString:[NSAttributedString attributedStringWithAttachment:textAttachment]];
[replacementString addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, [replacementString length])];
[attachments appendAttributedString:replacementString];
}
_isEditing = YES;
[self beginEditing];
[_backingStore replaceCharactersInRange:range
withAttributedString:attachments];
[self edited:NSTextStorageEditedAttributes
range:range changeInLength:allAssets.count];
[super processEditing];
[self endEditing];
_isEditing = NO;
}
(the _isEditing is a boolean flag used for book-keeping)
The output looks like this Output http://take.ms/QCvRK
I have tried various parameters on the NSMutableParagraphStyle but I couldn't get a line break after each image.
Appending a line break ("\r") around the text attachment will result in a glyph error
!!! _NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 1
!!! _NSGlyphTreeInvalidateGlyphsForCharacterRange invalid char range 1
!!! _NSGlyphTreeInvalidateGlyphsForCharacterRange character count mismatch
!!! _NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 0
!!! _NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 0
!!! _NSLayoutTreeLineFragmentUsedRectForGlyphAtIndex invalid glyph index 2147483647
I tried to subclass the NSTextAttachment to over-ride the attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex: so that the width is set to the device width, this resulted in the attached image looking blown up.
Any suggestion on how I can introduce a line break right after each image ? Also it would be great if I can get the text to flow around the image attachments.
Thanks in advance.

How to get the width of an NSString?

I am trying to get the width of an NSString (ex. NSString *myString = #"hello"). Is there a way to do this?
Thanks.
Here's a relatively simple approach. Just create an NSAttributedString with the appropriate font and ask for its size:
- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
}
UIFont * font = [UIFont systemFontOfSize:15];
CGSize stringSize = [aString sizeWithFont:font];
CGFloat width = stringSize.width;
Using the UILabel's attributed string:
- (CGSize)getStringSizeWithText:(NSString *)string font:(UIFont *)font{
UILabel *label = [[UILabel alloc] init];
label.text = string;
label.font = font;
return label.attributedText.size;
}
Send the string a sizeWithAttributes: message, passing a dictionary containing the attributes with which you want to measure the string.
i dont know if you are suppose to use this in cocoa touch. if it is, then:
- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
}
wont work.
in cocoa touch, you gotta add coretext framework and import the header
and write your code like this:
UIFont *font = [UIFont fontWithName:#"HelveticaNeue-BoldItalic" size:DEFAULT_FONT_SIZE];
// NSLog(#"%#", NSFontAttributeName);
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, (NSString *)kCTFontAttributeName, nil];
but, GEE!!!!!
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:self.caption attributes:attributes];
[as size].width;
there's no size this method in NSMutableAttributedString!
finally, this would work
[self.caption sizeWithFont:font].width
as for ios 7 and up this is the correct way:
NSString * buttonTitle = #"demo title";
CGSize stringSize = [buttonTitle sizeWithAttributes:#{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];
This works with iOS 14.5
Objective-C
Define attributes:
NSDictionary *attributes = #{
NSFontAttributeName: [UIFont fontWithName:#"Helvetica" size:25],
NSStrokeWidthAttributeName: #(0),
NSStrokeColorAttributeName: [UIColor blackColor]
};
Get width and height:
- (CGFloat)widthOfString:(NSString *)string {
CGSize stringSize = [string sizeWithAttributes:attributes];
return stringSize.width;
}
- (CGFloat)heightOfString:(NSString *)string {
CGSize stringSize = [string sizeWithAttributes:attributes];
return stringSize.height;
}
Sorry my question was not detailed enough and is not exactly what I'm trying to do. I am using a text storage, layout manager and a text container. The solution is to use the layout manager to determine the rectangle that bounds the rect. Here is the code.
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:#"hello"];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] init];
[layoutManager addTextContainer:textContainer];
[textContainer release];
[textStorage addLayoutManager:layoutManager];
[layoutManager release];
//Figure out the bounding rectangle
NSRect stringRect = [layoutManager boundingRectForGlyphRange:NSMakeRange(0, [layoutManager numberOfGlyphs]) inTextContainer:textContainer];
UIKit has a nice addition to NSString, making sizeWithAttributes: a bit lighter:
CGSize titleSize = [title sizeWithFont:titleFont
constrainedToSize:contentCellSize
lineBreakMode:UILineBreakModeWordWrap];
Here's Stephen's solution in Clozure Common Lisp, when using the Objective C bridge. I came across this post when searching for a solution, and I just rewrote Stephen's version which worked fine for me. Others using Clozure might find this helpful:
(defun string-width (str font)
(let* ((dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
font #$NSFontAttributeName
ccl:+null-ptr+))
(attr (#/initWithString:attributes: (#/alloc ns:ns-attributed-string)
(ccl::%make-nsstring str)
dict))
(size (#/size attr)))
(ns:ns-size-width size)))
This will work. You can try it.
NSDictionary *attrDict = #{NSFontAttributeName : [GenericUtility getOpenSansRegularFontSize:12]};
CGSize stringBoundingBox = [selectedReservationModel.DateLabel sizeWithAttributes: attrDict];
lblDeliveryDateWidth = stringBoundingBox.width;
Just in case you are wondering how to check a label size, you should use the UIFont, instead of the NSFont (not even sure if exists)

How to change only font size for the whole styled text in NSTextView

I need to set a text size (for example to 42) of the selected rich text which uses multiple fonts.
I imagine I can check attributes of each group of characters, modify the font size and set attributes back, but looking at the floating Font panel it seems like there should be a very easy and straightforward way to accomplish that. Do I miss something obvious?
On 10.6 there is a convenient way to iterate over the attributes and increase the font size.
This method can be added to an NSTextView category.
- (IBAction)increaseFontSize:(id)sender
{
NSTextStorage *textStorage = [self textStorage];
[textStorage beginEditing];
[textStorage enumerateAttributesInRange: NSMakeRange(0, [textStorage length])
options: 0
usingBlock: ^(NSDictionary *attributesDictionary,
NSRange range,
BOOL *stop)
{
#pragma unused(stop)
NSFont *font = [attributesDictionary objectForKey:NSFontAttributeName];
if (font) {
[textStorage removeAttribute:NSFontAttributeName range:range];
font = [[NSFontManager sharedFontManager] convertFont:font toSize:[font pointSize] + 1];
[textStorage addAttribute:NSFontAttributeName value:font range:range];
}
}];
[textStorage endEditing];
[self didChangeText];
}
Generalizing on Jonathan's answer a bit, here is a category interface you can simply paste into appropriate files in your Xcode project:
#interface NSTextView (FrameworkAdditions)
- (IBAction)decrementFontSize:(id)sender;
- (IBAction)incrementFontSize:(id)sender;
#end
And the corresponding implementation:
#implementation NSTextView (FrameworkAdditions)
- (void)changeFontSize:(CGFloat)delta;
{
NSFontManager * fontManager = [NSFontManager sharedFontManager];
NSTextStorage * textStorage = [self textStorage];
[textStorage beginEditing];
[textStorage enumerateAttribute:NSFontAttributeName
inRange:NSMakeRange(0, [textStorage length])
options:0
usingBlock:^(id value,
NSRange range,
BOOL * stop)
{
NSFont * font = value;
font = [fontManager convertFont:font
toSize:[font pointSize] + delta];
if (font != nil) {
[textStorage removeAttribute:NSFontAttributeName
range:range];
[textStorage addAttribute:NSFontAttributeName
value:font
range:range];
}
}];
[textStorage endEditing];
[self didChangeText];
}
- (IBAction)decrementFontSize:(id)sender;
{
[self changeFontSize:-1.0];
}
- (IBAction)incrementFontSize:(id)sender;
{
[self changeFontSize:1.0];
}
#end
This will double the font size, but you may change the scale property to any value, or provide your fixed size
NSFont * font = ...;
CGFloat fontSize = [[font fontDescriptor].fontAttributes[NSFontSizeAttribute] floatValue];
font = [NSFont fontWithDescriptor:[font fontDescriptor] size:fontSize * 2.];
self.textField.font = font;
Note: I assume that you are using a NSTextView and that you can access its text storage (NSTextStorage).
I think it is not possible to only change the font's size over a text that use multiple fonts. In NSAttributedString, font's size is part of the NSFontAttributeName attribute which controls both the font and the size.
One solution is to iterate over the selection and use the attribute:atIndex:longestEffectiveRange:inRange: to capture the range when each font apply, change the font's size and then use the addAttribute:value:range: to set the new font over the range.
Update:
If you take a look at the GNUstep GUI source code for NSTextView (under LGPL), you will see that their implementation use the range iteration.
Since NSTextView is a subclass of NSView, you can use -scaleUnitSquareToSize: to change the magnification level of the text view. For example, to make all the text double sized you'd call:
[textView scaleUnitSquareToSize:NSMakeSize(2.0, 2.0)];
You may need to make some adjustments to the dimensions of the text view's NSTextContainer after performing this operation to ensure the text is laid out correctly.