版本記錄
版本號 | 時間 |
---|---|
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‰Ω?‰o?á???êó?oü 0x00000001000897d7 -[JJStringTestVC drawNSString] + 263
8 NSString‰Ω?‰o?á???êó?oü 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‰Ω?‰o?á???êó?oü 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
結論:還是直接看代碼吧。
后記
周六放假了,未完,待續,歡迎留言哦~~~