版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.06.03 |
前言
前面我简单的写了些NSString的初始化,写了几篇,都不难,但是可以对新手有一定的小帮助,对于大神级人物可以略过这几篇,NSString本来就没有难的,都是细枝末节,忘记了查一下就会了,没有技术难点,下面我们继续~~~
1. NSString简单细说(一)—— NSString整体架构
2. NSString简单细说(二)—— NSString的初始化
3. NSString简单细说(三)—— NSString初始化
4. NSString简单细说(四)—— 从URL初始化
5. NSString简单细说(五)—— 向文件或者URL写入
6. NSString简单细说(六)—— 字符串的长度
7. NSString简单细说(七)—— 与C字符串的转化
8. NSString简单细说(八)—— 识别和比较字符串
9. NSString简单细说(九)—— 字符串的合并
10. NSString简单细说(十)—— 字符串的分解
11. NSString简单细说(十一)—— 字符串的查找
12. NSString简单细说(十二)—— 字符串的替换
13. NSString简单细说(十三)—— 字符串的分行和分段
14. NSString简单细说(十四)—— 字符串位置的计算
15. NSString简单细说(十五)—— 字符串转化为propertyList
画字符串
一、- (void)drawAtPoint:(CGPoint)point withAttributes:(NSDictionary<NSString *,id> *)attrs;
这个方法的作用是:在指定的图形上下文中,画出具有字体大小和给定特性的字符串。下面看一下这个方法的两个参数。
- point:该点就是当前图形上下文中你想开始画字符串的点,图形上下文的坐标由你想画字符串的视图决定,在AppKit中,原点位于画图区域的左下角,但是如果对焦视图被翻转,那么原点位于左上角。
- attrs:该参数是字典类型,是字符串的特性。这些特性也可以用于NSAttributedString对象,但是,在NSString对象中,特性被应用于整个字符串,而不是用于一段字符串。
- 注意:不同于drawInRect:withAttributes:方法使用边界矩形,这个方法的渲染区域是没有限制的,因此,此方法渲染在一行中,但是,如果字符串中包含换行符,那么这个换行符也会被解释和使用,导致后续文本放在起始点的下一行。在调用该方法时,必须有一个显示视图或者可用的图形上下文。
下面我们看代码
#import "JJStringDrawView.h"
@implementation JJStringDrawView
//画字符串
- (void)drawRect:(CGRect)rect
{
/**
* 1. - (void)drawAtPoint:(CGPoint)point withAttributes:(NSDictionary<NSString *,id> *)attrs;
*
* @param point:The point in the current graphics context where you want to start drawing the string. The coordinate system of the graphics context is usually defined by the view in which you are drawing. In AppKit, the origin is normally in the lower-left corner of the drawing area, but the origin is in the upper-left corner if the focused view is flipped.
* @param attrs:A dictionary of text attributes to be applied to the string. These are the same attributes that can be applied to an NSAttributedString object, but in the case of NSString objects, the attributes apply to the entire string, rather than ranges within the string.
*
*/
NSString *str = @"我只是一个字符串而已!";
CGPoint point = CGPointMake(50.0, 200.0);
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0],NSForegroundColorAttributeName:[UIColor redColor]};
[str drawAtPoint:point withAttributes:attrDict];
}
@end
上面我就是在view的drawRect里面画的字符串,下面看结果。
结论:看代码大家都能看懂,但是这里我碰到了bug
2017-06-03 00:28:38.485 NSString你会用吗?[2840:95594] -[__NSCFConstantString pointSize]: unrecognized selector sent to instance 0x10008c120
2017-06-03 00:28:38.545 NSString你会用吗?[2840:95594] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString pointSize]: unrecognized selector sent to instance 0x10008c120'
*** First throw call stack:
(
0 CoreFoundation 0x0000000100c00d4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010066221e objc_exception_throw + 48
2 CoreFoundation 0x0000000100c70f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000100b86005 ___forwarding___ + 1013
4 CoreFoundation 0x0000000100b85b88 _CF_forwarding_prep_0 + 120
5 UIFoundation 0x0000000104075dd6 __NSStringDrawingEngine + 3204
6 UIFoundation 0x00000001040734fa -[NSString(NSStringDrawing) drawAtPoint:withAttributes:] + 229
7 NSString你会用吗? 0x00000001000897d7 -[JJStringTestVC drawNSString] + 263
8 NSString你会用吗? 0x00000001000896bd -[JJStringTestVC viewDidLoad] + 189
9 UIKit 0x00000001011c6a3d -[UIViewController loadViewIfRequired] + 1258
10 UIKit 0x00000001011cd062 -[UIViewController __viewWillAppear:] + 118
11 UIKit 0x00000001011f81d3 -[UINavigationController _startCustomTransition:] + 1290
12 UIKit 0x0000000101208e48 -[UINavigationController _startDeferredTransitionIfNeeded:] + 697
13 UIKit 0x0000000101209fdb -[UINavigationController __viewWillLayoutSubviews] + 58
14 UIKit 0x0000000101400dd7 -[UILayoutContainerView layoutSubviews] + 223
15 UIKit 0x00000001010e9ab8 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
16 QuartzCore 0x00000001058f8bf8 -[CALayer layoutSublayers] + 146
17 QuartzCore 0x00000001058ec440 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
18 QuartzCore 0x00000001058ec2be _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
19 QuartzCore 0x000000010587a318 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
20 QuartzCore 0x00000001058a73ff _ZN2CA11Transaction6commitEv + 475
21 QuartzCore 0x00000001058a7d6f _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 113
22 CoreFoundation 0x0000000100ba5267 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
23 CoreFoundation 0x0000000100ba51d7 __CFRunLoopDoObservers + 391
24 CoreFoundation 0x0000000100b89f8e __CFRunLoopRun + 1198
25 CoreFoundation 0x0000000100b89884 CFRunLoopRunSpecific + 420
26 GraphicsServices 0x00000001049f2a6f GSEventRunModal + 161
27 UIKit 0x0000000101024c68 UIApplicationMain + 159
28 NSString你会用吗? 0x00000001000895df main + 111
29 libdyld.dylib 0x0000000103a6268d start + 1
30 ??? 0x0000000000000001 0x0 + 1
)
是因为
NSDictionary *attrDict = @{NSFontAttributeName:@"16",NSForegroundColorAttributeName:[UIColor redColor]};
这里字号不能直接写@"16",而是要像下边这样写
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0],NSForegroundColorAttributeName:[UIColor redColor]};
修改以后就不崩溃了。打印出来就会发现,苹果是这么转化这个字典的。
(lldb) po attrDict
{
NSColor = "UIExtendedSRGBColorSpace 1 0 0 1";
NSFont = "<UICTFont: 0x7f9537508c40> font-family: \".SFUIText\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}
二、- (void)drawInRect:(CGRect)rect withAttributes:(NSDictionary<NSString *,id> *)attrs;
有上面的方法做基础,那么这个也不难理解,这个是在某个固定区域上画字符串。我们还是先看参数。
- rect:绘制字符串的矩形边界,在AppKit中,边框的原点位于左下角,但是如果视图被翻转,那么原点就位于左上角。
- attrs:该参数是字典类型,是字符串的特性。这些特性也可以用于NSAttributedString对象,但是,在NSString对象中,特性被应用于整个字符串,而不是用于一段字符串。
- 注意:该方法尽可能的在指定的矩形区域中画尽量多的字符串,如果字符串相对于矩形框太长,该方法会尽量去渲染并切除多余的部分,如果字符串中包含换行符,那么换行符会起作用,并且换行后会在初始原点的下方显示。在调用该方法时,必须有一个显示视图或者可用的图形上下文。
下面看代码
//画字符串
- (void)drawRect:(CGRect)rect
{
/**
* 2. - (void)drawInRect:(CGRect)rect withAttributes:(NSDictionary<NSString *,id> *)attrs;
*
* @param rect:The bounding rectangle in which to draw the string. In AppKit, the origin of the bounding box is normally in the lower-left corner, but the origin is in the upper-left corner if the focused view is flipped.
* @param attrs:A dictionary of text attributes to be applied to the string. These are the same attributes that can be applied to an NSAttributedString object, but in the case of NSString objects, the attributes apply to the entire string, rather than ranges within the string.
*
*/
NSString *str = @"1.我只是一个字符串而已,就是有点长!2.我只是一个字符串而已,就是有点长!3.我只是一个字符串而已,就是有点长!4.我只是一个字符串而已,就是有点长!5.我只是一个字符串而已,就是有点长!6.我只是一个字符串而已,就是有点长!7.我只是一个字符串而已,就是有点长!";
CGRect drawRect = CGRectMake(250.0, 400.0, 50.0, 50.0);
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:20.0],NSForegroundColorAttributeName:[UIColor blueColor]};
[str drawInRect:rect withAttributes:attrDict];
}
下面看输出结果
结论:字符串是画出来了,但是我还是有一个疑问,这里我已经显示了rect区域,但是不管rect原点设置在哪里,都不起作用,都是在左上角开始画,方法一中的drawPoint就起作用。希望知道的能给我解答下,谢谢,待我后续更改。
三、- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *,id> *)attributes context:(NSStringDrawingContext *)context;
该方法的作用就是根据指定的选型option,在指定区域中画字符串。还是先看参数配置
- rect :画字符串的边界
- options:选项也就是配置参数,在渲染时候需要参考这个额外的参数,这个是个枚举值
typedef enum NSStringDrawingOptions : NSInteger {
// 整个文本将以每行组成的矩形为单位计算整个文本的尺寸
// The specified origin is the line fragment origin, not the base line origin
NSStringDrawingUsesLineFragmentOrigin = 1 << 0,
// 使用字体的行间距来计算文本占用的范围,即每一行的底部到下一行的底部的距离计算
// Uses the font leading for calculating line heights
NSStringDrawingUsesFontLeading = 1 << 1,
// 将文字以图像符号计算文本占用范围,而不是以字符计算。也即是以每一个字体所占用的空间来计算文本范围
// Uses image glyph bounds instead of typographic bounds
NSStringDrawingUsesDeviceMetrics = 1 << 3,
// 当文本不能适合的放进指定的边界之内,则自动在最后一行添加省略符号。如果NSStringDrawingUsesLineFragmentOrigin没有设置,则该选项不生效
// Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified.
NSStringDrawingTruncatesLastVisibleLine = 1 << 5
} NSStringDrawingOptions;
attributes:该参数是字典类型,是字符串的特性。这些特性也可以用于NSAttributedString对象,但是,在NSString对象中,特性被应用于整个字符串,而不是用于一段字符串。
context:这个参数就是上下文,当attribute=nil的时候,这里的方法使用<UIKit/NSAttributedString.h>中每个attribute的默认方法,当stringDrawingContext=nil时,相当于使用默认的初始化方法,[[NSStringDrawingContext alloc] init], 看下面:
// When attributes=nil, the methods declared here uses the default behavior for each attribute described in <UIKit/NSAttributedString.h>. When stringDrawingContext=nil, it's equivalent of passing the default instance initialized with [[NSStringDrawingContext alloc] init].
NS_CLASS_AVAILABLE(10_11, 6_0) @interface NSStringDrawingContext : NSObject
下面直接看代码
//画字符串
- (void)drawRect:(CGRect)rect
{
/**
* 3. - (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *,id> *)attributes context:(NSStringDrawingContext *)context;
*
* @param rect:The bounding rectangle in which to draw the string.
* @param options:Additional drawing options to apply to the string during rendering. For a list of possible values, see NSStringDrawingOptions.
* @param attributes:The text attributes with which to draw the string. These are the same attributes that can be applied to an NSAttributedString object, but in the case of NSString objects, the attributes apply to the entire string, rather than ranges within the string.
* @param context:A context object with information about how to adjust the font tracking and scaling information. On return, the specified object contains information about the actual values used to render the string. This parameter may be nil.
*
*/
NSString *str = @"1.我只是一个字符串而已,就是有点长!";
CGRect drawRect = CGRectMake(10.0, 400.0, 150.0, 50.0);
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:20.0],NSForegroundColorAttributeName:[UIColor blueColor]};
[str drawWithRect:drawRect options:NSStringDrawingUsesDeviceMetrics attributes:attrDict context:nil];
}
下面看输出结果
四、- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *,id> *)attributes context:(NSStringDrawingContext *)context;
该方法计算并返回在当前图形上下文中指定的矩形内使用给定选项和字符串绘制的矩形。还是先看参数:
- size:要画字符串的尺寸边界
- options:选项值,这个是一个枚举。
- attributes:该参数是字典类型,是字符串的特性。这些特性也可以用于NSAttributedString对象,但是,在NSString对象中,特性被应用于整个字符串,而不是用于一段字符串。
- context:画字符串的上下文,指定最小比例因子和缩进调整值。
- 注意:为了正确的画和计算多行文本,那么option参数需要传递值NSStringDrawingUsesLineFragmentOrigin。这个方法使用返回的尺寸计算视图大小,必须使用ceil函数得到最近的最大整数。这个方法返回字符串字形的实际边界,一些字形(例如空格)可以覆盖传入尺寸的布局约束,因此有些时候,返回的CGRect的width可能会超过size参数的宽度值。
下面直接看代码
- (void)drawRect:(CGRect)rect
{
/**
* 4. - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *,id> *)attributes context:(NSStringDrawingContext *)context;
*
* @param size:The size of the rectangle to draw in.
* @param options:String drawing options.
* @param attributes:The text attributes with which to draw the string. These are the same attributes that can be applied to an NSAttributedString object, but in the case of NSString objects, the attributes apply to the entire string, rather than ranges within the string.
* @param context:The string drawing context to use for the receiver, specifying minimum scale factor and tracking adjustments.
*
* @return :The bounding rect for the receiver drawn using the given options and display characteristics. The rect origin returned from this method is the first glyph origin.
*/
NSString *str = @"1.我只是一个字符串而已,就是有点长!";
CGSize size = CGSizeMake(MAXFLOAT, 22);
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:20.0],NSForegroundColorAttributeName:[UIColor magentaColor]};
CGRect strRect = [str boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrDict context:nil];
NSLog(@"strRect=%@",NSStringFromCGRect(strRect));
}
下面看输出结果
2017-06-03 16:22:22.159 NSString你会用吗?[8190:292756] strRect={{0, 0}, {345.95304687499998, 23.8671875}}
结论:还是直接看代码吧。
五、- (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs;
该方法返回的是在给定特性下计算得到的边界尺寸。下面先看参数
- attrs:该参数是字典类型,是字符串的特性。这些特性也可以用于NSAttributedString对象,但是,在NSString对象中,特性被应用于整个字符串,而不是用于一段字符串。
- return:给定特性下的字符串size。
- 注意:该方法返回的是份数尺寸,要使用返回的尺寸来约束视图,必须利用ceil函数得到这个返回值的最近最小的整数。
下面还是直接看代码。
- (void)drawRect:(CGRect)rect
{
/**
* 5. - (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs;
*
* @param attrs:The text attributes with which to draw the string. These are the same attributes that can be applied to an NSAttributedString object, but in the case of NSString objects, the attributes apply to the entire string, rather than ranges within the string.
*
* @return :The bounding box size the receiver occupies when drawn with the specified attributes.
*/
NSString *str = @"1.我只是一个字符串而已,就是有点长!";
NSDictionary *attrDict = @{NSFontAttributeName:[UIFont systemFontOfSize:20.0],NSForegroundColorAttributeName:[UIColor magentaColor]};
CGSize strSize = [str sizeWithAttributes:attrDict];
NSLog(@"strSize=%@",NSStringFromCGSize(strSize));
NSLog(@"size=%.f--height=%.f",ceil(strSize.width),ceil(strSize.height));
}
下面看输出结果
2017-06-03 16:37:34.959 NSString你会用吗?[8584:306231] strSize={345.95304687499998, 23.8671875}
2017-06-03 16:37:34.959 NSString你会用吗?[8584:306231] size=346--height=24
结论:还是直接看代码吧。
后记
周六放假了,未完,待续,欢迎留言哦~~~