iOS 项目小结

1.iOS中的round、ceil、floor函数略解

round如果参数是小数,则求本身的四舍五入.ceil如果参数是小数,则求最小的整数但不小于本身.floor如果参数是小数,则求最大的整数但不大于本身.

Example:如何值是3.4的话,则

-- round 3.000000

-- ceil 4.000000

-- floor 3.00000



登录|注册

xiaoxiaobukuang的专栏

目录视图

摘要视图

订阅

【CSDN技术主题月】深度学习框架的重构与思考深度学习代码专栏攒课--我的学习我做主知识库个人图谱上线,快来领取~

关闭

CoreText(四):行 CTLineRef

标签:字体coretext

2016-09-08 18:14241人阅读评论(0)收藏举报

分类:

iOS连载(8)

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

一、字符(Character)和字形(Glyphs)

排版过程中一个重要的步骤就是从字符到字形的转换,字符表示信息本身,而字形是它的图形表现形式。字符一般就是指某种编码,如Unicode编码,而字形则是这些编码对应的图片。但是他们之间不是一一对应关系,同个字符的不同字体族,不同字体大小,不同字体样式都对应了不同的字形。而由于连写(Ligatures)的存在,多个字符也会存在对应一个字形的情况。

下面就来详情看看字形的各个参数也就是所谓的字形度量Glyph Metrics

(1)、边界框 bbox(bounding box)

这是一个假想的框子,它尽可能紧密的装入字形。

(2)、基线(baseline)

一条假想的线,一行上的字形都以此线作为上下位置的参考,在这条线的左侧存在一个点叫做基线的原点,

(3)、上行高度(ascent)

从原点到字体中最高(这里的高深都是以基线为参照线的)的字形的顶部的距离,ascent是一个正值

(4)、下行高度(descent)

从原点到字体中最深的字形底部的距离,descent是一个负值(比如一个字体原点到最深的字形的底部的距离为2,那么descent就为-2)

(5)、行距(line gap)

line gap也可以称作leading(其实准确点讲应该叫做External leading),行高line Height则可以通过 ascent + |descent| + linegap 来计算。

(6)、字间距(Kerning)

字与字之间的距离,为了排版的美观,并不是所有的字形之间的距离都是一致的,但是这个基本步影响到我们的文字排版。

(7)、基础原点(Origin)

基线上最左侧的点。

红框高度既为当前行的行高,绿线为baseline,绿色到红框上部分为当前行的最大Ascent,绿线到黄线为当前行的最大Desent,而黄框的高即为行间距。由此可以得出:lineHeight = Ascent + |Decent| + Leading。

二、坐标系

传统的Mac中的坐标系的原点在左下角,比如NSView默认的坐标系,原点就在左下角。但Mac中有些View为了其实现的便捷将原点变换到左上角,像NSTableView的坐标系坐标原点就在左上角。

iOSUIKit中,UIView是以左上角为原点,而Core Text一开始的定位是使用与桌面应用的排版系统,桌面应用的坐标系是以左下角为原点,即Core Text在绘制的时候也是参照左下角为原点进行绘制的,所以需要对当前的坐标系进行处理。

实际上,Core Graphic 中的context也是以左下角为原点的, 但是为什么我们用Core Graphic

绘制一些简单的图形的时候不需要对坐标系进行处理呢,是因为通过这个方法UIGraphicsGetCurrentContext()来获得的当前context是已经被处理过的了,用下面方法可以查看指定的上下文的当前图形状态变换矩阵。

方法一

//因为Core Text要配合Core Graphic 配合使用的,如Core Graphic一样,绘图的时候需要获得当前的上下文进行绘制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"当前context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));//翻转当前的坐标系(因为对于底层绘制引擎来说,屏幕左下角为(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flipNSLog(@"翻转后context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

打印结果为:

当前context的变换矩阵[2, 0, 0, -2, 0, 800]翻转后context的变换矩阵[2, 0, 0, 2, 0, 0]

1

2

1

2

方法二

//因为Core Text要配合Core Graphic 配合使用的,如Core Graphic一样,绘图的时候需要获得当前的上下文进行绘制CGContextRefcontext= UIGraphicsGetCurrentContext();NSLog(@"当前context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));//翻转当前的坐标系(因为对于底层绘制引擎来说,屏幕左下角为(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);CGContextTranslateCTM(context,0, self.bounds.size.height);CGContextScaleCTM(context,1.0, -1.0);NSLog(@"翻转后context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

打印:

当前context的变换矩阵[2, 0, 0, -2, 0, 800]翻转后context的变换矩阵[2, 0, -0, 2, 0, 0]

1

2

1

2

可以发现变换矩阵与CGAffineTransformIdentity的值[1, 0, 0, 1, 0,

0]是不相同的,并且与设备是否为Retina屏和设备尺寸相关。他的作用是将上下文空间坐标系进行翻转,并使原来的左下角原点变成左上角是原点,并将向上为正y轴变为向下为正y轴。

所以在使用drawRect的时候,当前的context已经被做了一次翻转,如果不对当前的坐标系进行处理,会发现,绘制出来的文字是镜像上下颠倒的。所以在UIView的drawRect方法中的context上进行Core

Text绘制之前需要对context进行一次Flip。

三、主要函数

1、传入CTFrame,返回一个装有多个CTLine对象的数组。

CFArrayRefCTFrameGetLines(

CTFrameRef frame )CT_AVAILABLE(10_5,3_2);

1

2

1

2

2、获取数组中的元素个数

CFIndexCFArrayGetCount(CFArrayRef theArray);

1

1

3、获取数组中第idx个元素

constvoid*CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);

1

1

4、 获取所有CTLineRef的基础原点,传入CTFrame,CFRange,和一个CGPoint的结构体数组指针,该函数会把每一个CTLine的origin坐标写到数组里。

voidCTFrameGetLineOrigins(        CTFrameRef frame,        CFRange range,CGPointorigins[] ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

1

2

3

4

5、获取CTLine中文字在整段文字中的Range

CFRangeCTLineGetStringRange(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

6、获取CTLine中的CTRun的数组

CFArrayRefCTLineGetGlyphRuns(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

7、获取CTRun在整段文字中的Range

CFRangeCTRunGetStringRange(

CTRunRef run )CT_AVAILABLE(10_5,3_2);

1

2

1

2

8、 获取点击处position文字在整段文字中的index

CFIndexCTLineGetStringIndexForPosition(

CTLineRef line,

CGPoint position )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

9、获取整段文字中charIndex位置的字符相对line的原点的x值

CGFloatCTLineGetOffsetForStringIndex(    CTLineRef line,    CFIndex charIndex,CGFloat* __nullable secondaryOffset ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

1

2

3

4

10、获取数组中字形个个数

CFIndexCTLineGetGlyphCount(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

11、设置CoreText绘制前的坐标。设置基线位置

CG_EXTERNvoidCGContextSetTextPosition(CGContextRef __nullable c,CGFloatx,CGFloaty)    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

1

2

3

1

2

3

12、绘制CTLine。

voidCTLineDraw(

CTLineRef line,

CGContextRef context )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

13、获取CTLine的上行高度,下行高度,行距

doubleCTLineGetTypographicBounds(    CTLineRef line,CGFloat* __nullable ascent,CGFloat* __nullable descent,CGFloat* __nullable leading ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

5

1

2

3

4

5

14、设置当前文本矩阵

CG_EXTERN voidCGContextSetTextMatrix(CGContextRef __nullable c,

CGAffineTransform t)CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

1

2

3

1

2

3

15、获取一行文字的范围,

就是指把这一行文字点有的像素矩阵作为一个image图片,来得到整个矩形区域。相对于每一行基线原点的偏移量和宽高(例如:{{1.2,

-2.57227}, {208.025,

19.2523}},就是相对于本身的基线原点向右偏移1.2个单位,向下偏移2.57227个单位,后面是宽高)

CGRectCTLineGetImageBounds(

CTLineRef line,

CGContextRef __nullable context )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

例如:

//获取frame中CTLineRef数组CFArrayRef Lines = CTFrameGetLines(frame);//获取数组Lines中的个数CFIndex lineCount = CFArrayGetCount(Lines);//获取数组中第一个CTLineRefCTLineRef lineRef = CFArrayGetValueAtIndex(Lines,0);//获取lineRef中CTRunRef数组CFArrayRef runs = CTLineGetGlyphRuns(lineRef);//获取CTLineRef中字形个数CFIndex rus = CTLineGetGlyphCount(lineRef);//获取数组runs中的个数CFIndex runCount = CFArrayGetCount(runs);NSLog(@"lines =%ldruns =%ldrus =%ld",lineCount,runCount,rus);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

打印:

lines=7  runs = 5 rus = 37

1

1

四、举例

1、绘框

- (void)drawRect:(CGRect)rect{// 步骤1:得到当前用于绘制画布的上下文,用于后续将内容绘制在画布上// 因为Core Text要配合Core Graphic 配合使用的,如Core Graphic一样,绘图的时候需要获得当前的上下文进行绘制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"当前context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步骤2:翻转当前的坐标系(因为对于底层绘制引擎来说,屏幕左下角为(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);    CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flipNSLog(@"翻转后context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步骤3:创建绘制区域CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path,NULL,self.bounds);// 步骤4:创建需要绘制的文字与计算需要绘制的区域NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"iOS程序在启动时会创建一个主线程,而在一个线程只能执行一件事情,如果在主线程执行某些耗时操作,例如加载网络图片,下载资源文件等会阻塞主线程(导致界面卡死,无法交互),所以就需要使用多线程技术来避免这类情况。iOS中有三种多线程技术 NSThread,NSOperation,GCD,这三种技术是随着IOS发展引入的,抽象层次由低到高,使用也越来越简单。"];// 步骤5:根据AttributedString生成CTFramesetterRefCTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attrString length]), path,NULL);//获取frame中CTLineRef数组CFArrayRef Lines = CTFrameGetLines(frame);//获取数组Lines中的个数CFIndex lineCount = CFArrayGetCount(Lines);//获取基线原点CGPointorigins[lineCount];    CTFrameGetLineOrigins(frame, CFRangeMake(0,0), origins);for(CFIndex i =0; i < lineCount; i ++) {        CTLineRef line = CFArrayGetValueAtIndex(Lines, i);//相对于每一行基线原点的偏移量和宽高(例如:{{1.2, -2.57227}, {208.025, 19.2523}},就是相对于本身的基线原点向右偏移1.2个单位,向下偏移2.57227个单位,后面是宽高)CGRectlineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds = %@",NSStringFromCGRect(lineBounds));NSLog(@"point = %@",NSStringFromCGPoint(origins[i]));//每一行的起始点(相对于context)加上相对于本身基线原点的偏移量lineBounds.origin.x+= origins[i].x;        lineBounds.origin.y+= origins[i].y;//填充CGContextSetLineWidth(context,1.0);        CGContextAddRect(context,lineBounds);        CGContextSetStrokeColorWithColor(context, [[UIColorredColor] CGColor]);        CGContextStrokeRect(context, lineBounds);    }// 步骤6:进行绘制CTFrameDraw(frame, context);// 步骤7.内存管理CFRelease(frame);    CFRelease(path);    CFRelease(frameSetter);}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

打印:

当前context的变换矩阵 [2,0,0,-2,0,800]翻转后context的变换矩阵 [2,0,0,2,0,0]lineBounds={{0.7734375,-2.052}, {354.70246875000004, 11.964}}point= {0,387}lineBounds={{0.44400000000000001,-2.052}, {371.06400000000002, 11.94}}point= {0,370}lineBounds={{0.38400000000000001,-2.052}, {371.06400000000002, 11.975999999999999}}point= {0,353}lineBounds={{0.41999999999999998,-2.052}, {320.66929687499999, 11.927999999999999}}point= {0,336}lineBounds={{0.9140625,-2.501953125}, {366.28096875, 12.473953125}}point= {0,319}lineBounds={{0.40800000000000003,-2.052}, {148.16400000000002, 11.94}}point= {0,302}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

1

2

3

4

5

6

7

8

9

10

11

12

13

14

2、单行绘制

- (void)drawRect:(CGRect)rect{// 步骤1:得到当前用于绘制画布的上下文,用于后续将内容绘制在画布上// 因为Core Text要配合Core Graphic 配合使用的,如Core Graphic一样,绘图的时候需要获得当前的上下文进行绘制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"当前context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步骤2:翻转当前的坐标系(因为对于底层绘制引擎来说,屏幕左下角为(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);    CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flipNSLog(@"翻转后context的变换矩阵 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步骤3:创建绘制区域CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path,NULL,self.bounds);// 步骤4:创建需要绘制的文字与计算需要绘制的区域NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"门梁真可怕 当中英文混合之后,����������会出现行高不统一的情况,现在在绘制的时候根据字体的descender来偏移绘制,对齐baseline。����������同时点击链接的时候会调用drawRect: 造成绘制异常,所以将setNeedsDisplay注释,如需刷新,请手动调用。带上emoji以供测试��������������������"];    CTFontRef font = CTFontCreateWithName(CFSTR("Georgia"),20,NULL);    [attrString addAttribute:(id)kCTFontAttributeName value:(__bridgeid)font range:NSMakeRange(0, attrString.length)];// 步骤5:根据AttributedString生成CTFramesetterRefCTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attrString length]), path,NULL);//获取frame中CTLineRef数组CFArrayRef Lines = CTFrameGetLines(frame);//获取数组Lines中的个数CFIndex lineCount = CFArrayGetCount(Lines);//获取基线原点CGPointorigins[lineCount];    CTFrameGetLineOrigins(frame, CFRangeMake(0,0), origins);for(CFIndex i =0; i < lineCount; i ++) {        CTLineRef line = CFArrayGetValueAtIndex(Lines, i);//遍历每一行CTLineCGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 该函数除了会设置好ascent,descent,leading之外,还会返回这行的宽度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = origins[i];NSLog(@"point = %@",NSStringFromCGPoint(lineOrigin));CGRectoldLineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds改动前:%@",NSStringFromCGRect(oldLineBounds));NSLog(@"y = %f  d = %f  fontD = %f",lineOrigin.y,lineDescent,CTFontGetDescent(font));NSLog(@"Position修改前%@",NSStringFromCGPoint(CGContextGetTextPosition(context)));        CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y-lineDescent - CTFontGetDescent(font));NSLog(@"Position修改后%@",NSStringFromCGPoint(CGContextGetTextPosition(context)));CGRectlineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds改动后 = %@",NSStringFromCGRect(lineBounds));//填充CGContextSetLineWidth(context,1.0);        CGContextAddRect(context,lineBounds);        CGContextSetStrokeColorWithColor(context, [[UIColorredColor] CGColor]);        CGContextStrokeRect(context, lineBounds);        CTLineDraw(line, context);//绘制原点为左下角}// 步骤6:进行绘制//    CTFrameDraw(frame, context);// 步骤7.内存管理CFRelease(frame);    CFRelease(path);    CFRelease(frameSetter);}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

打印数据:

当前context的变换矩阵 [2,0,0, -2,0,800]翻转后context的变换矩阵 [2,0,0,2,0,0]lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 378}lineBounds改动前:{{1.98, -3.5499999999999998},{328.34421874999998, 22}}y =378.000000d =6.875000fontD =4.384766Position修改前{0, 0}Position修改后{0, 366.740234375}lineBounds改动后 ={{1.98, 363.19023437499999},{328.34421874999998, 22}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 349}lineBounds改动前:{{331.32421875, 363.19023437499999},{367.41999999999996, 22}}y =349.000000d =6.875000fontD =4.384766Position修改前{330.82421875, 366.740234375}Position修改后{0, 337.740234375}lineBounds改动后 ={{0.5, 334.19023437499999},{367.41999999999996, 22}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 321}lineBounds改动前:{{369.83999999999997, 335.58023437499997},{368.16703124999998, 18.66}}y =321.000000d =6.800000fontD =4.384766Position修改前{369, 337.740234375}Position修改后{0, 309.81523437499999}lineBounds改动后 ={{0.83999999999999997, 307.65523437499996},{368.16703124999998, 18.66}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 292}lineBounds改动前:{{370.40703124999999, 306.26523437499998},{365.81625000000003, 22}}y =292.000000d =6.875000fontD =4.384766Position修改前{369.70703125, 309.81523437499999}Position修改后{0, 280.740234375}lineBounds改动后 ={{0.70000000000000007, 277.19023437499999},{365.81625000000003, 22}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 264}lineBounds改动前:{{368.41624999999999, 278.58023437499997},{353.68367187500002, 18.620000000000001}}y =264.000000d =6.800000fontD =4.384766Position修改前{367.65625, 280.740234375}Position修改后{0, 252.81523437499999}lineBounds改动后 ={{0.76000000000000001, 250.65523437499999},{353.68367187500002, 18.620000000000001}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 236}lineBounds改动前:{{356.94367187500001, 248.47929687499999},{363.27226562499999, 20.775937499999998}}y =236.000000d =6.800000fontD =4.384766Position修改前{355.263671875, 252.81523437499999}Position修改后{0, 224.81523437499999}lineBounds改动后 ={{1.6799999999999999, 220.47929687499999},{363.27226562499999, 20.775937499999998}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 208}lineBounds改动前:{{367.25226562500001, 220.47929687499999},{328.44562499999995, 20.915937499999998}}y =208.000000d =6.800000fontD =4.384766Position修改前{366.572265625, 224.81523437499999}Position修改后{0, 196.81523437499999}lineBounds改动后 ={{0.68000000000000005, 192.47929687499999},{328.44562499999995, 20.915937499999998}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 179}lineBounds改动前:{{330.265625, 193.26523437499998},{229, 22}}y =179.000000d =6.875000fontD =4.384766Position修改前{329.765625, 196.81523437499999}Position修改后{0, 167.740234375}lineBounds改动后 ={{0.5, 164.19023437499999},{229, 22}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

3、固定行间距

行高=每行的asent + 每行的descent + 行数*行间距

.m

#import"MyView.h"#import// 行距constCGFloatkGlobalLineLeading =5.0;@interfaceMyView()@property(nonatomic,assign)CGFloattextHeight;@end@implementationMyView- (instancetype)initWithFrame:(CGRect)frame{self= [superinitWithFrame:frame];if(self) {self.text= @"我自横刀向天笑,去留肝胆两昆仑。--谭嗣同同学你好啊。This is my first CoreText demo,how are you ?I love three things,the sun,the moon,and you.the sun for the day,the moon for the night,and you forever.��������������去年今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风。��������������少年不知愁滋味,爱上层楼,爱上层楼,为赋新词强说愁。56321363464.而今识尽愁滋味,欲说还休,欲说还休,却道天凉好个秋。123456,7890,56321267895434。缺月挂疏桐,漏断人初静。谁见幽人独往来,缥缈孤鸿影。惊起却回头,有恨无人省。捡尽寒枝不肯栖,寂寞沙洲冷。";self.font= [UIFontsystemFontOfSize:15];    }returnself;}#pragma mark - 计算高度/**

*  高度 = 每行的asent + 每行的descent + 行数*行间距

*  行间距为指定的数值

*/+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont{    NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithString:aText];// 设置全局样式[selfaddGlobalAttributeWithContent:content font:aFont];    CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)content);//粗略的计算高度CGSizesuggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, aText.length),NULL, CGSizeMake(aWidth, MAXFLOAT),NULL);    CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path,NULL, CGRectMake(0,0, aWidth, suggestSize.height*10));// 10这个数值是随便给的,主要是为了确保高度足够CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, aText.length), path,NULL);    CFArrayRef lines = CTFrameGetLines(frameRef);    CFIndex lineCount = CFArrayGetCount(lines);CGFloatascent =0;CGFloatdescent =0;CGFloatleading =0;CGFloattotalHeight =0;NSLog(@"计算高度开始");for(CFIndex i =0; i < lineCount; i++){        CTLineRef lineRef = CFArrayGetValueAtIndex(lines, i);        CTLineGetTypographicBounds(lineRef, &ascent, &descent, &leading);NSLog(@"ascent = %f---descent = %f---leading = %f",ascent,descent,leading);        totalHeight += ascent + descent + kGlobalLineLeading;//行间距}NSLog(@"totalHeight = %f",totalHeight);returntotalHeight;}#pragma mark - 工具方法#pragma mark 给字符串添加全局属性,比如行距,字体大小,默认颜色+ (void)addGlobalAttributeWithContent:(NSMutableAttributedString *)aContent font:(UIFont*)aFont{CGFloatlineLeading = kGlobalLineLeading;// 行间距constCFIndex kNumberOfSettings =2;//设置段落格式CTParagraphStyleSetting lineBreakStyle;    CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;    lineBreakStyle.spec= kCTParagraphStyleSpecifierLineBreakMode;    lineBreakStyle.valueSize=sizeof(CTLineBreakMode);    lineBreakStyle.value= &lineBreakMode;//设置行距CTParagraphStyleSetting lineSpaceStyle;    CTParagraphStyleSpecifier spec;    spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;    lineSpaceStyle.spec= spec;    lineSpaceStyle.valueSize=sizeof(CGFloat);    lineSpaceStyle.value= &lineLeading;// 结构体数组CTParagraphStyleSetting theSettings[kNumberOfSettings] = {        lineBreakStyle,        lineSpaceStyle,    };    CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);// 将设置的行距应用于整段文字[aContent addAttribute:NSParagraphStyleAttributeName value:(__bridgeid)(theParagraphRef) range:NSMakeRange(0, aContent.length)];    CFStringRef fontName = (__bridge CFStringRef)aFont.fontName;    CTFontRef fontRef = CTFontCreateWithName(fontName, aFont.pointSize,NULL);// 将字体大小应用于整段文字[aContent addAttribute:NSFontAttributeName value:(__bridgeid)fontRef range:NSMakeRange(0, aContent.length)];// 给整段文字添加默认颜色[aContent addAttribute:NSForegroundColorAttributeName value:[UIColorblackColor] range:NSMakeRange(0, aContent.length)];// 内存管理CFRelease(theParagraphRef);    CFRelease(fontRef);}/**

*  一行一行绘制,未调整行高(行高不固定)

*/- (void)drawRectWithLineByLine{// 1.创建需要绘制的文字NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithString:self.text];// 2.设置行距等样式[[selfclass] addGlobalAttributeWithContent:attributed font:self.font];self.textHeight= [[selfclass] textHeightWithText:self.textwidth:CGRectGetWidth(self.bounds) font:self.font];// 3.创建绘制区域,path的高度对绘制有直接影响,如果高度不够,则计算出来的CTLine的数量会少一行或者少多行CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path,NULL, CGRectMake(0,0, CGRectGetWidth(self.bounds),self.textHeight));// 4.根据NSAttributedString生成CTFramesetterRefCTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributed);    CTFrameRef ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributed.length), path,NULL);// 1.获取上下文CGContextRef contextRef = UIGraphicsGetCurrentContext();// 2.转换坐标系CGContextSetTextMatrix(contextRef, CGAffineTransformIdentity);    CGContextTranslateCTM(contextRef,0,self.textHeight);// 此处用计算出来的高度CGContextScaleCTM(contextRef,1.0, -1.0);// 重置高度//    CGPathAddRect(path, NULL, CGRectMake(0, 0, CGRectGetWidth(self.bounds), self.textHeight));// 一行一行绘制CFArrayRef lines = CTFrameGetLines(ctFrame);    CFIndex lineCount = CFArrayGetCount(lines);CGPointlineOrigins[lineCount];// 把ctFrame里每一行的初始坐标写到数组里,注意CoreText的坐标是左下角为原点CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);for(inti =0; i < lineCount; i++){CGPointpoint = lineOrigins[i];NSLog(@"point.y = %f",point.y);    }NSLog(@"font.ascender = %f,descender = %f,lineHeight = %f,leading = %f",self.font.ascender,self.font.descender,self.font.lineHeight,self.font.leading);CGFloatframeY =0;for(CFIndex i =0; i < lineCount; i++){// 遍历每一行CTLineCTLineRef line = CFArrayGetValueAtIndex(lines, i);CGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 该函数除了会设置好ascent,descent,leading之外,还会返回这行的宽度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = lineOrigins[i];NSLog(@"i = %ld, lineOrigin = %@",i,NSStringFromCGPoint(lineOrigin));// 微调Y值,需要注意的是CoreText的Y值是在baseLine处,而不是下方的descent。// lineDescent为正数,self.font.descender为负数if(i >0){// 第二行之后需要计算frameY = frameY - kGlobalLineLeading - lineAscent;            lineOrigin.y= frameY;        }else{// 第一行可直接用frameY = lineOrigin.y;        }// 调整坐标CGContextSetTextPosition(contextRef, lineOrigin.x, lineOrigin.y);        CTLineDraw(line, contextRef);// 微调frameY = frameY - lineDescent;    }    CFRelease(path);    CFRelease(framesetter);    CFRelease(ctFrame);}- (void)drawRect:(CGRect)rect{    [selfdrawRectWithLineByLine];}@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

.h文件

#import@interfaceMyView:UIView@property(nonatomic,copy)NSString*text;@property(nonatomic,strong)UIFont*font;+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont;@end

1

2

3

4

5

6

7

8

9

10

11

1

2

3

4

5

6

7

8

9

10

11

结果:

3、固定行高

总高度 = 行数*每行的高度

.m

#import"MyView.h"#import// 行距constCGFloatkGlobalLineLeading =5.0;// 在15字体下,比值小于这个计算出来的高度会导致emoji显示不全constCGFloatkPerLineRatio =1.4;@interfaceMyView()@property(nonatomic,assign)CGFloattextHeight;@end@implementationMyView- (instancetype)initWithFrame:(CGRect)frame{self= [superinitWithFrame:frame];if(self) {self.text= @"我自横刀向天笑,去留肝胆两昆仑。--谭嗣同同学你好啊。This is my first CoreText demo,how are you ?I love three things,the sun,the moon,and you.the sun for the day,the moon for the night,and you forever.��������������去年今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风。��������������少年不知愁滋味,爱上层楼,爱上层楼,为赋新词强说愁。56321363464.而今识尽愁滋味,欲说还休,欲说还休,却道天凉好个秋。123456,7890,56321267895434。缺月挂疏桐,漏断人初静。谁见幽人独往来,缥缈孤鸿影。惊起却回头,有恨无人省。捡尽寒枝不肯栖,寂寞沙洲冷。";self.font= [UIFontsystemFontOfSize:15];    }returnself;}/**

*  高度 = 每行的固定高度 * 行数

*/+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont{    NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithString:aText];// 给字符串设置字体行距等样式[selfaddGlobalAttributeWithContent:content font:aFont];    CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)content);// 粗略的高度,该高度不准,仅供参考CGSizesuggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, content.length),NULL, CGSizeMake(aWidth, MAXFLOAT),NULL);NSLog(@"suggestHeight = %f",suggestSize.height);    CGMutablePathRef pathRef = CGPathCreateMutable();    CGPathAddRect(pathRef,NULL, CGRectMake(0,0, aWidth, suggestSize.height));    CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, content.length), pathRef,NULL);    CFArrayRef lines = CTFrameGetLines(frameRef);    CFIndex lineCount = CFArrayGetCount(lines);NSLog(@"行数 = %ld",lineCount);// 总高度 = 行数*每行的高度,其中每行的高度为指定的值,不同字体大小不一样CGFloataccurateHeight = lineCount * (aFont.pointSize* kPerLineRatio);CGFloatheight = accurateHeight;    CFRelease(pathRef);    CFRelease(frameRef);returnheight;}#pragma mark - 工具方法#pragma mark 给字符串添加全局属性,比如行距,字体大小,默认颜色+ (void)addGlobalAttributeWithContent:(NSMutableAttributedString *)aContent font:(UIFont*)aFont{CGFloatlineLeading = kGlobalLineLeading;// 行间距constCFIndex kNumberOfSettings =2;//设置段落格式CTParagraphStyleSetting lineBreakStyle;    CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;    lineBreakStyle.spec= kCTParagraphStyleSpecifierLineBreakMode;    lineBreakStyle.valueSize=sizeof(CTLineBreakMode);    lineBreakStyle.value= &lineBreakMode;//设置行距CTParagraphStyleSetting lineSpaceStyle;    CTParagraphStyleSpecifier spec;    spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;    lineSpaceStyle.spec= spec;    lineSpaceStyle.valueSize=sizeof(CGFloat);    lineSpaceStyle.value= &lineLeading;// 结构体数组CTParagraphStyleSetting theSettings[kNumberOfSettings] = {        lineBreakStyle,        lineSpaceStyle,    };    CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);// 将设置的行距应用于整段文字[aContent addAttribute:NSParagraphStyleAttributeName value:(__bridgeid)(theParagraphRef) range:NSMakeRange(0, aContent.length)];    CFStringRef fontName = (__bridge CFStringRef)aFont.fontName;    CTFontRef fontRef = CTFontCreateWithName(fontName, aFont.pointSize,NULL);// 将字体大小应用于整段文字[aContent addAttribute:NSFontAttributeName value:(__bridgeid)fontRef range:NSMakeRange(0, aContent.length)];// 给整段文字添加默认颜色[aContent addAttribute:NSForegroundColorAttributeName value:[UIColorblackColor] range:NSMakeRange(0, aContent.length)];// 内存管理CFRelease(theParagraphRef);    CFRelease(fontRef);}#pragma mark - 一行一行绘制,行高确定,行与行之间对齐- (void)drawRectWithLineByLineAlignment{// 1.创建需要绘制的文字NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithString:self.text];// 2.设置行距等样式[[selfclass] addGlobalAttributeWithContent:attributed font:self.font];self.textHeight= [[selfclass] textHeightWithText:self.textwidth:CGRectGetWidth(self.bounds) font:self.font];// 3.创建绘制区域,path的高度对绘制有直接影响,如果高度不够,则计算出来的CTLine的数量会少一行或者少多行CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path,NULL, CGRectMake(0,0, CGRectGetWidth(self.bounds),self.textHeight*2));// 4.根据NSAttributedString生成CTFramesetterRefCTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributed);    CTFrameRef ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributed.length), path,NULL);// 获取上下文CGContextRef contextRef = UIGraphicsGetCurrentContext();// 转换坐标系CGContextSetTextMatrix(contextRef, CGAffineTransformIdentity);    CGContextTranslateCTM(contextRef,0,self.textHeight);// 此处用计算出来的高度CGContextScaleCTM(contextRef,1.0, -1.0);// 一行一行绘制CFArrayRef lines = CTFrameGetLines(ctFrame);    CFIndex lineCount = CFArrayGetCount(lines);CGPointlineOrigins[lineCount];// 把ctFrame里每一行的初始坐标写到数组里,注意CoreText的坐标是左下角为原点CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);for(inti =0; i < lineCount; i++)    {CGPointpoint = lineOrigins[i];NSLog(@"point.y = %f",point.y);    }NSLog(@"font.ascender = %f,descender = %f,lineHeight = %f,leading = %f",self.font.ascender,self.font.descender,self.font.lineHeight,self.font.leading);CGFloatframeY =0;NSLog(@"self.textHeight = %f,lineHeight = %f",self.textHeight,self.font.pointSize* kPerLineRatio);for(CFIndex i =0; i < lineCount; i++){// 遍历每一行CTLineCTLineRef line = CFArrayGetValueAtIndex(lines, i);CGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 该函数除了会设置好ascent,descent,leading之外,还会返回这行的宽度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = lineOrigins[i];NSLog(@"i = %ld, lineOrigin = %@",i,NSStringFromCGPoint(lineOrigin));// 微调Y值,需要注意的是CoreText的Y值是在baseLine处,而不是下方的descent。CGFloatlineHeight =self.font.pointSize* kPerLineRatio;        frameY =self.textHeight- (i +1)*lineHeight -self.font.descender;NSLog(@"frameY = %f",frameY);        lineOrigin.y= frameY;// 调整坐标CGContextSetTextPosition(contextRef, lineOrigin.x, lineOrigin.y);        CTLineDraw(line, contextRef);    }    CFRelease(path);    CFRelease(framesetter);    CFRelease(ctFrame);}- (void)drawRect:(CGRect)rect{    [selfdrawRectWithLineByLineAlignment];}@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

.h

#import@interfaceMyView:UIView@property(nonatomic,copy)NSString*text;@property(nonatomic,strong)UIFont*font;+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont;@end

1

2

3

4

5

6

7

8

9

10

11

1

2

3

4

5

6

7

8

9

10

11

结果

参考

CoreText使用教程(三)

0

0

上一篇CoreText(四):图文混排

下一篇CoreText(五):省略号

我的同类文章

iOS连载(8)

CoreText(五):省略号2016-09-19阅读293

CoreText(三):绘制文本2016-08-31阅读210

CoreText(一):基本用法2016-08-30阅读128

颜色(二):CGColor2016-01-09阅读257

CoreText(四):图文混排2016-08-31阅读241

CoreText(二):段落CTParagraphStyle2016-08-31阅读195

颜色(三):CIColor2016-01-09阅读137

颜色(一):UIColor2016-01-09阅读197

参考知识库

Swift知识库

1792关注|395收录

猜你在找

iOS8开发技术(Swift版):屏幕适配

老郭全套iOS开发课程【UI技术】

iOS8开发视频教程Swift语言版-Part 3:iOS 8多分辨率屏幕适配

iOS8开发技术(Swift版):本地化

iOS企业级应用开发-iOS6定位服务与地图

javascript对象小探之四---undefinednullNaN的相互运算

Nodejs 在命令行下执行Consolelog命令时第二行会打印undefined的原因

ios-CoreText-核心文本

关于coretext绘图字体始终无法改变大小的原因

CoreText ios 上的用法

查看评论

暂无评论

您还没有登录,请[登录][注册]

* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

核心技术类目

全部主题HadoopAWS移动游戏JavaAndroidiOSSwift智能硬件DockerOpenStackVPNSparkERPIE10EclipseCRMJavaScript数据库UbuntuNFCWAPjQueryBIHTML5SpringApache.NETAPIHTMLSDKIISFedoraXMLLBSUnitySplashtopUMLcomponentsWindows MobileRailsQEMUKDECassandraCloudStackFTCcoremailOPhoneCouchBase云计算iOS6RackspaceWeb AppSpringSideMaemoCompuware大数据aptechPerlTornadoRubyHibernateThinkPHPHBasePureSolrAngularCloud FoundryRedisScalaDjangoBootstrap

个人资料

xiaoxiaobukuang

访问:69977次

积分:1736

等级:

排名:第16926名

原创:104篇

转载:4篇

译文:0篇

评论:3条

文章搜索

文章分类

疯狂iOS(上)(12)

疯狂iOS(下)(11)

iOS多线程和推送(11)

HTTP和Socket套接字(2)

iOS管理(7)

iOS崩溃(3)

iOS总结(11)

iOS控件(1)

iOS基础(6)

iOS三方库(8)

iOS连载(9)

iOS视图切换(4)

iOS动画(7)

iOS 8 新增控件(3)

iOS 9 新特性(7)

UIKit性能优化(3)

iOS提高(8)

阅读排行

第十章:使用MapKit开发地图服务(3979)

自动引用计数(3516)

block(3360)

第六章:加速计与陀螺仪(3271)

BlocksKit的使用(3136)

第九章:使用CoreLocation定位(3111)

第七章:多线程(2984)

第五章:管理手机(2859)

第四章:多媒体应用开发(2794)

第三章:iOS的数据存储与IO(2768)

评论排行

第七章:多线程(2)

iOS 常用公共方法(1)

第三章:C语言特性(0)

第二章:流程控制与数组(0)

第一章:数据类型和运算符(0)

CAShapeLayer和UIBezierPath(0)

HTTP协议(0)

TCP/IP协议(0)

CoreText(五):省略号(0)

iOS并发编程指南(0)

推荐文章

* 2016 年最受欢迎的编程语言是什么?

* Chromium扩展(Extension)的页面(Page)加载过程分析

* Android Studio 2.2 来啦

* 手把手教你做音乐播放器(二)技术原理与框架设计

* JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

最新评论

iOS 常用公共方法

那个小五先生:Cool

第七章:多线程

xiaoxiaobukuang:@goldenepoch:第一个评论,多谢!!!以后多多指教

第七章:多线程

goldenepoch:介绍的很详细

公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈

网站客服杂志客服微博客服webmaster@csdn.net400-600-2320|北京创新乐知信息技术有限公司 版权所有|江苏乐知网络技术有限公司 提供商务支持

京 ICP 证 09002463 号|Copyright © 1999-2016, CSDN.NET, All Rights Reserved

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容